eSEATでSeqIO
Simple Wiki Based Contents Management System
ソフトウェア関連 >> RTコンポーネント関連 >> eSEAT_v2.5 >> SEATMLファイルの書き方 >> RTコンポーネントの作成(eSEAT) >> eSEATでSeqIO

eSEATでSeqIO

SimpleIOに引き続き、SeqIOのサンプルをSEATMLで作成していきます。
作成するSeqInとSeqOutは、以下のようになっています。
SeqOut
TimedOcte型,TimedShort型,TimedLong型, TimedFloat型, TimedDoule型及びそれぞれのSequence型の、出力データポート(合計10個)を有し、各データポートにランダムなデータを周期的に出力する。
SeqIn
TimedOcte型,TimedShort型,TimedLong型, TimedFloat型, TimedDoule型及びそれぞれのSequence型の入力データポート(合計10個)を有し、コンソールに受信したデータをすべて表示します。

SeqOut octet (TimeOctet) short (TimeShort) long (TimeLong) float (TimeFloat) double (TimeDouble) octetSeq (TimeOctetSeq) shortSeq (TimeShortSeq) longSeq (TimeLongSeq) floatSeq (TimeFloatSeq) doubleSeq (TimeDoubleSeq)

SeqIn octet (TimeOctet) short (TimeShort) long (TimeLong) float (TimeFloat) double (TimeDouble) octetSeq (TimeOctetSeq) shortSeq (TimeShortSeq) longSeq (TimeLongSeq) floatSeq (TimeFloatSeq) doubleSeq (TimeDoubleSeq)

SeqOutの実装

まずは、ひな形のSEATMLファイルをSeqOut.seatmlといファイルにコピーします。
 # cd ~/work
 # source/usr/local/eSEAT/setup.bash
 # gen_seatml SeqOut
次に、適当なエディタでSeqOut.seatmlを開き、出力データポートの追加を行います。
 <?xml version="1.0" encoding="UTF-8" ?>
 <seatml>
  <general name="SeqOut">
    <adaptor name="octet" type="rtcout" datatype="TimedOctet" />
    <adaptor name="short" type="rtcout" datatype="TimedShort" />
    <adaptor name="long" type="rtcout" datatype="TimedLong" />
    <adaptor name="float" type="rtcout" datatype="TimedFloat" />
    <adaptor name="double" type="rtcout" datatype="TimedDouble" />
    <adaptor name="octetSeq" type="rtcout" datatype="TimedOctetSeq" />
    <adaptor name="shortSeq" type="rtcout" datatype="TimedShortSeq" />
    <adaptor name="longSeq" type="rtcout" datatype="TimedLongSeq" />
    <adaptor name="floatSeq" type="rtcout" datatype="TimedFloatSeq" />
    <adaptor name="doubleSeq" type="rtcout" datatype="TimedDoubleSeq" />
  </general>

  <state name="main_state">
  </state>
 </seatml>
SeqOutは、乱数で発生させたoctet型、short型、long型、float型、double型の数字と10個の乱数からなるoctetSeq型、shortSeq型、longSeq型、floatSeq型、doubleSeq型の数字を周期的に出力するものです。(ただし、octet型は、'A'-'Z'(0x41 - 0x5a)の文字とします)
周期的な処理は、onexecで書くことができますので、SeqOut.pyの内容をほぼそのまま書くことができます。
<state>要素の子要素として、下記のコードを書き込みます。(Python2の場合)
 <onexec>
   <sript>
    import random

    octetSeq  = ""
    shortSeq  = []
    longSeq   = []
    floatSeq  = []
    doubleSeq = []

    seat._data['octet'].data=int(random.uniform(0x41, 0x5a))
    seat._data['short'].data=int(random.uniform(0, 10))
    seat._data['long'].data=long(random.uniform(0, 10))
    seat._data['float'].data=float(random.uniform(0.0, 10.0))
    seat._data['double'].data=float(random.uniform(0.0, 10.0))

    print('%3.2s   %10.8s %10.8s %10.8s %10.8s %10.8s' \
          % (' ', 'octet', 'short', 'long', 'float', 'double'))
    print('%3.2s   %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
          % (' ', seat._data['octet'].data, chr(seat._data['octet'].data),
            seat._data['short'].data, seat._data['long'].data,
            seat._data['float'].data, seat._data['double'].data))

    print( '-------------------------------------------------------------')
    print( '                 Sequence Data                     ')
    print( '-------------------------------------------------------------')

    for i in range(10):
      octetSeq = octetSeq + chr(int(random.uniform(0x41, 0x5a)))
      shortSeq.append(int(random.uniform(0, 10)))
      longSeq.append(long(random.uniform(0, 10)))
      floatSeq.append(float(random.uniform(0.0, 10.0)))
      doubleSeq.append(float(random.uniform(0.0, 10.0)))

      print( '%3.2s : %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
             % (str(i), ord(octetSeq[i]), octetSeq[i], shortSeq[i],
                longSeq[i], floatSeq[i], doubleSeq[i]))
    print('')
    seat._data['octetSeq'].data=octetSeq
    seat._data['shortSeq'].data=shortSeq
    seat._data['longSeq'].data=longSeq
    seat._data['floatSeq'].data=floatSeq
    seat._data['doubleSeq'].data=doubleSeq

    seat.writeData('octet')
    seat.writeData('short')
    seat.writeData('long')
    seat.writeData('float')
    seat.writeData('double')
    seat.writeData('octetSeq')
    seat.writeData('shortSeq')
    seat.writeData('longSeq')
    seat.writeData('floatSeq')
    seat.writeData('doubleSeq')
  </script>
 <onexec>
Python3を利用する場合には、octetSeqの実装型が異なりますので、下のようになります。
 <onexec>
   <sript>
    import random

    octetSeq  = b""
    shortSeq  = []
    longSeq   = []
    floatSeq  = []
    doubleSeq = []

    seat._data['octet'].data=int(random.uniform(0x41, 0x5a))
    seat._data['short'].data=int(random.uniform(0, 10))
    seat._data['long'].data=long(random.uniform(0, 10))
    seat._data['float'].data=float(random.uniform(0.0, 10.0))
    seat._data['double'].data=float(random.uniform(0.0, 10.0))

    print('%3.2s   %10.8s %10.8s %10.8s %10.8s %10.8s' \
          % (' ', 'octet', 'short', 'long', 'float', 'double'))
    print('%3.2s   %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
          % (' ', seat._data['octet'].data, chr(seat._data['octet'].data),
            seat._data['short'].data, seat._data['long'].data,
            seat._data['float'].data, seat._data['double'].data))

    print( '-------------------------------------------------------------')
    print( '                 Sequence Data                     ')
    print( '-------------------------------------------------------------')

    for i in range(10):
      octetSeq = octetSeq + chr(int(random.uniform(0x41, 0x5a))).encode()
      shortSeq.append(int(random.uniform(0, 10)))
      longSeq.append(long(random.uniform(0, 10)))
      floatSeq.append(float(random.uniform(0.0, 10.0)))
      doubleSeq.append(float(random.uniform(0.0, 10.0)))

      print( '%3.2s : %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
             % (str(i), ord(octetSeq[i]), octetSeq[i], shortSeq[i],
                longSeq[i], floatSeq[i], doubleSeq[i]))
    print('')
    seat._data['octetSeq'].data=octetSeq
    seat._data['shortSeq'].data=shortSeq
    seat._data['longSeq'].data=longSeq
    seat._data['floatSeq'].data=floatSeq
    seat._data['doubleSeq'].data=doubleSeq

    seat.writeData('octet')
    seat.writeData('short')
    seat.writeData('long')
    seat.writeData('float')
    seat.writeData('double')
    seat.writeData('octetSeq')
    seat.writeData('shortSeq')
    seat.writeData('longSeq')
    seat.writeData('floatSeq')
    seat.writeData('doubleSeq')
  </script>
 <onexec>
通常のRTCを実装する場合とことなるのは、出力データポートの出力バッファとデータの書き出しのメソッドです。通常は、データポートに対して write()メソッド呼び出しを行いますが、eSEATでは、writeDataメソッドを定義しています。
SimpleIOの時に行った<script>要素にsendto属性をつけるというやり方もあるのですが、複数のデータポートに周期的に実施するのには、少し向かないので上のような実装にしています。
もちろん、<onexec>要素に、出力データごとに'<script>要素+sendto属性'でも似たような機能は実装することができます。
最終的なSeqOut.seatmlは、このページに添付しておりますので、ダウンロードして使用して下さい。

SeqInの実装

まずは、ひな形のSEATMLファイルをSeqain.seatmlといファイルにコピーします。
 # cd ~/work
 # source /usr/local/eSEAT/setup.bash
 # gen_seatml SeqIn
次に、適当なエディタでSeqIn.seatmlを開き、入力データポートの追加を行います。
 <?xml version="1.0" encoding="UTF-8" ?>
 <seatml>
  <general name="SeqIn">
    <adaptor name="octet" type="rtcin" datatype="TimedOctet" />
    <adaptor name="short" type="rtcin" datatype="TimedShort" />
    <adaptor name="long" type="rtcin" datatype="TimedLong" />
    <adaptor name="float" type="rtcin" datatype="TimedFloat" />
    <adaptor name="double" type="rtcin" datatype="TimedDouble" />
    <adaptor name="octetSeq" type="rtcin" datatype="TimedOctetSeq" />
    <adaptor name="shortSeq" type="rtcin" datatype="TimedShortSeq" />
    <adaptor name="longSeq" type="rtcin" datatype="TimedLongSeq" />
    <adaptor name="floatSeq" type="rtcin" datatype="TimedFloatSeq" />
    <adaptor name="doubleSeq" type="rtcin" datatype="TimedDoubleSeq" />
  </general>

  <state name="main_state">
  </state>
 </seatml>
SeqInは、octet型、short型、long型、float型、double型、octetSeq型、shortSeq型、longSeq型、floatSeq型、doubleSeq型の入力データポートのデータを周期的に読み込み、その値を出力します。
周期的な処理は、onexecで書くことができますので、SeqIn.pyの内容をほぼそのまま書くことができます。
<state>要素の子要素として、下記のコードを書き込みます。(Python2の場合)
 <onexec>
   <sript>
 <!--
    octet_  = seat.readData('octet')
    short_  = seat.readData('short')
    long_   = seat.readData('long')
    float_  = seat.readData('float')
    double_ = seat.readData('double')

    octetSeq_  = seat.readData('octetSeq')
    shortSeq_  = seat.readData('shortSeq')
    longSeq_   = seat.readData('longSeq')
    floatSeq_  = seat.readData('floatSeq')
    doubleSeq_ = seat.readData('doubleSeq')

    octetSize_  = len(octetSeq_.data)
    shortSize_  = len(shortSeq_.data)
    longSize_   = len(longSeq_.data)
    floatSize_  = len(floatSeq_.data)
    doubleSize_ = len(doubleSeq_.data)

    octetSeqDisp_ = []
    for i in range(octetSize_):
      octetSeqDisp_.append(ord(octetSeq_.data[i]))

    maxsize = max(octetSize_, shortSize_, longSize_, floatSize_, doubleSize_)
    octetSeqDisp_   = octetSeqDisp_   + ['-'] * (maxsize - octetSize_)
    shortSeq_.data  = shortSeq_.data  + ['-'] * (maxsize - shortSize_)
    longSeq_.data   = longSeq_.data   + ['-'] * (maxsize - longSize_)
    floatSeq_.data  = floatSeq_.data  + ['-'] * (maxsize - floatSize_)
    doubleSeq_.data = doubleSeq_.data + ['-'] * (maxsize - doubleSize_)

    if 0x20 <= octet_.data < 0x7e :
      octetDisp_ = chr(octet_.data)
    else:
      octetDisp_ = ' '
    print( '%3.2s %10.8s %10.8s %10.8s %10.8s %10.8s' \
        % (' ', 'octet', 'short', 'long', 'float', 'double'))
    print( '%3.2s %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
        % (' ', octet_.data, octetDisp_, short_.data, long_.data,
           float_.data, double_.data))
    print( '===================================================' )
    print( '                 Sequence Data                     ' )
    print( '===================================================' )
    for i in range(maxsize):
      if 0x20 <= octetSeqDisp_[i] < 0x7e :
        octetDisp_ = chr(octetSeqDisp_[i])
      else:
        octetDisp_ = ' '
      print( '%3.2s %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
          % (i, octetSeqDisp_[i], octetDisp_, shortSeq_.data[i],
           longSeq_.data[i], floatSeq_.data[i], doubleSeq_.data[i]))

    print(' ')
-->
    </script>
   </onexec>
Python3で実行する場合には、下のようになります。
 <onexec>
   <sript>
 <!--
    octet_  = seat.readData('octet')
    short_  = seat.readData('short')
    long_   = seat.readData('long')
    float_  = seat.readData('float')
    double_ = seat.readData('double')

    octetSeq_  = seat.readData('octetSeq')
    shortSeq_  = seat.readData('shortSeq')
    longSeq_   = seat.readData('longSeq')
    floatSeq_  = seat.readData('floatSeq')
    doubleSeq_ = seat.readData('doubleSeq')

    octetSize_  = len(octetSeq_.data)
    shortSize_  = len(shortSeq_.data)
    longSize_   = len(longSeq_.data)
    floatSize_  = len(floatSeq_.data)
    doubleSize_ = len(doubleSeq_.data)

    octetSeqDisp_ = []
    for i in range(octetSize_):
      octetSeqDisp_.append(ord(octetSeq_.data[i]))

    maxsize = max(octetSize_, shortSize_, longSize_, floatSize_, doubleSize_)
    octetSeqDisp_   = octetSeqDisp_   + ['-'] * (maxsize - octetSize_)
    shortSeq_.data  = shortSeq_.data  + ['-'] * (maxsize - shortSize_)
    longSeq_.data   = longSeq_.data   + ['-'] * (maxsize - longSize_)
    floatSeq_.data  = floatSeq_.data  + ['-'] * (maxsize - floatSize_)
    doubleSeq_.data = doubleSeq_.data + ['-'] * (maxsize - doubleSize_)

    if 0x20 <= octet_.data < 0x7e :
      octetDisp_ = chr(octet_.data)
    else:
      octetDisp_ = ' '
    print( '%3.2s %10.8s %10.8s %10.8s %10.8s %10.8s' \
        % (' ', 'octet', 'short', 'long', 'float', 'double'))
    print( '%3.2s %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
        % (' ', octet_.data, octetDisp_, short_.data, long_.data,
           float_.data, double_.data))
    print( '===================================================' )
    print( '                 Sequence Data                     ' )
    print( '===================================================' )
    for i in range(maxsize):
      octetDisp_ = ord(octetSeqDisp_[i])
      print( '%3.2s %7s[%s] %10.8s %10.8s %10.8s %10.8s' \
          % (i, octetSeqDisp_[i], octetDisp_, shortSeq_.data[i],
           longSeq_.data[i], floatSeq_.data[i], doubleSeq_.data[i]))

    print(' ')
-->
    </script>
   </onexec>
このコードもほぼOpenRTM-aistのサンプルであるSeqIn.pyのonExecuteメソッドをそのまま書くことができます。通常のRTCとことなるのは、 入力データポートからのデータ取得の部分を、seat.readDataメソッドを使っている点です。
また、この実装では、<script>要素のPythonスクリプトの部分が <!-- --> で囲まれており、XMLのコメントになっています。これは、XMLの文書では、'<'の文字が予約語となっており、SEATMLの構文解釈のときにエラーが起こってしまうためです。
また、
    print( '===================================================' )
の部分も '-' から '='に変更しています。これも、XMLの構文による制限のためです。(XMLでは、コメント内部で、'--'を記述することができません。)
この実装でも、通常のeSEATの記法と異なるやり方をしています。通常のeSEATでは、'<rule>要素+source属性'で入力データをハンドリングするのですが、このように周期的に一括してデータ利用する場合(複数adaptorの同期的な使用)には、<onexec>要素の中で処理する方がよいと思います。
最終的なSeqIn.seatmlは、このページに添付しておりますので、ダウンロードして使用して下さい。

SeqInとSeqOutの動作確認

最後に、作成したSeqInとSeqOutを実行してみましょう。実行は、eSEATコマンドで行います。
ターミナルを2つ起動し、下記のコマンドを入力します。
ターミナル1:
 # cd ~/work
 # eSEAT SeqIn.seatml
ターミナル2:
 # cd ~/work
 # eSEAT SeqOut.seatml
SeqInとSeqOutが起動したら各データポートを接続し、アクティベートすれば、SeqOutで生成されたランダムデータがSeqInに送信されることが確認できると思います。
RTCの操作は、通常、RT SystemEditorで行いますが、今回は接続するポートが多いこともあり、rtshellを使用することを推奨いたします。このページに、データポートの接続、切断、RTCのアクティベート、ディアクティベート、終了を行うためのシェルスクリプトを添付しています。(seq_cmd.sh)
Windows上で動作させる場合には、eSEATのrtcmdコマンドを使います。rtcmdで作成したバッチファイルを添付しています。(seq_cmd.bat)
このスクリプトを使用すると下のようになります。
  • データポートの接続
 # bash ./seq_cmd.sh con
  • SeqIn, SeqOutのアクティベート
 # bash ./seq_cmd.sh act
この時点で、SeqInのコンソールには、下記のような表示が出力されると思います。
         octet      short       long      float     double
         88[X]          2          1   0.066247   3.844291
===================================================
                 Sequence Data                     
===================================================
  0      88[X]          5          6   2.672402   7.964075
  1      85[U]          6          8   3.296362   3.640238
  2      85[U]          9          9   1.650067   8.078001
  3      82[R]          0          0   2.689078   7.322640
  4      75[K]          4          1   7.294220   0.574901
  5      74[J]          4          3   6.709820   0.236388
  6      73[I]          2          2   8.187395   3.643058
  7      77[M]          1          8   7.101873   7.989470
  8      86[V]          4          9   5.151458   7.829076
  9      85[U]          3          6   4.885576   8.390419
動作確認ができれば、RTCをでアクティベートして、終了させて下さい。
  • SeqIn, SeqOutのデアクティベート
 # bash ./seq_cmd.sh deact
  • 接続されたデータポートの切断
 # bash ./seq_cmd.sh dis
  • SeqIn, SeqOutの終了
 # bash ./seq_cmd.sh exit
以上で、SeqIOの実装と動作確認は終了です。

資料