SEATMLについて
Simple Wiki Based Contents Management System
ソフトウェア関連 >> RTコンポーネント関連 >> eSEAT2 >> SEATMLについて

SEATMLについて

SEATMLは、eSEATで使用しているスクリプトファイル記述です。seatml.xsd というファイルにXMLスキーマが定義されています。
SEALMLで記述ファイルは、下記の構造を持っています。
  • XML宣言文: <?xml version="1.0" uncoding="UFT-8" ?>
  • seatml要素:SEATの振舞の定義
    • general要素:ポートの定義(0コまたは1コ)
      • adapptor要素: データポート、TCPソケットポート、Webアダプタの定義(0コ以上)
      • script要素: SEATMLの読込時に実行されるPythonスクリプト(0コ以上)
      • onexec要素: onExecutionで状態に依存せず実行するスクリプトの定義(0コまたは1コ)
      • ontimeout要素: 入力またはGUIのイベントが一定時間ない時に実行するスクリプトの定義(0コまたは1コ)
    • state要素:状態の定義(0コ以上)
      • <onentry>:この状態に遷移した時のルール(0コまたは1コ)
        • <cond>:動作ルールの実行条件を定義(0コまたは1コ)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
      • <onexit>:この状態を抜けるときのルール(0コまたは1コ)
        • <cond>:動作ルールの実行条件を定義(0コまたは1コ)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
      • <ontimeout>: 入力またはGUIのイベントが一定時間ない時に実行するスクリプトの定義(0コまたは1コ)
        • <cond>:動作ルールの実行条件を定義(0コまたは1コ)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
      • <onexit>:この状態を抜けるときのルール(0コまたは1コ)
        • <cond>:動作ルールの実行条件を定義(0コまたは1コ)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
      • <rule>:1つの動作ルールの記述(0コ以上)
        • <cond>:動作ルールの実行条件を定義(0コまたは1コ)お
        • <key>:入力ポートからのデータ(文字列)またはデータポート名(0コ以上)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
        • <statetransition>: 状態を遷移させる(0コまたは1コ)
      • <label>:GUIパネル用のラベルアイテムを生成(0コ以上)
      • <button>:GUIパネル用のボタンアイテムを生成(0コ以上)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
        • <statetransition>: 状態を遷移させる(0コまたは1コ)
      • <input>:GUIパネル用の一行入力アイテムを生成(0コ以上)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
        • <statetransition>: 状態を遷移させる(0コまたは1コ)
      • <text>:GUIパネル用の複数行入力アイテムを生成(0コ以上)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
      • <brk>:GUIパネル用のアイテムを次の行へ配置する(0コ以上)
      • <space>:GUIパネル用のアイテムをスキップさせて配置させる(0コ以上)
      • <onexec>: onExecutionで実行するスクリプトの定義(0コ以上)
        • <message>: 出力する文字列(0コ以上)
        • <script>: 実行するPythonスクリプト(0コ以上)
        • <shell>: 実行するシェルコマンド(0コ以上)
        • <statetransition>: 状態を遷移させる(0コまたは1コ)
上記からもわかるように、SEATMLのスクリプトは、基本的に1つのgeneral要素と複数のstate要素によって構成されています。general要素では、主にデータポートの定義を行い、stat要素による状態の定義し、各状態で実行するルールとGUIの定義をすることができます。
以下に、SEATMLで使用する主な要素について説明していきます。

seatml要素

seatml要素は、SEATMLのトップレベルの要素であり、<seatml>タグによって記述されます。この要素は、一つのSEATMLのスクリプトファイルに唯一つ存在します。SEATMLスクリプトは必ずこのタグ内に記述する必要があります。
また、<seatml>タグには、0個または1個のgeneral要素と0個以上のstate要素を子要素として持つことができます。
seatml.xsdでは下記のように定義されています。
  <xs:element name="seatml">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="general"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="state"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
タグ名
<seatml>
属性
なし
子要素
<general>入出力ポートの設定および初期起動スクリプトの設定 [0または1個]
<state>内部状態の設定 [0個以上]

general要素

general>タグは、SEATMLスクリプトの最初に配置され、RTCデータポートの定義とTCPソケットポートの定義およびSEATML読込時に実行するPythonスクリプトの定義を行います。
general>タグでは、0個以上の<adaptor>タグと<script>タグを子要素として持つことができます。また、属性値としてnameを定義する必要がありますが、現在のところeSEATの振舞には何も影響がありません。
seatml.xsdでは下記のように定義されています。
  <xs:element name="general">
    <xs:complexType>
      <xs:sequence>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="adaptor"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="agent"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="var"/>
          <xs:element minOccurs="0" maxOccurs="1" ref="onexec"/>
          <xs:element minOccurs="0" maxOccurs="1" ref="ontimeout"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute name="name" use="required" type="xs:string"/>
    </xs:complexType>
  </xs:element>
この定義では、<agent>タグが利用できるようになっていますが、以前のSEATで利用していたSEATスクリプトとの互換性を確保するためのタグ定義であり、<adaptor>タグと同じです。
タグ名
<general>
属性
name識別子(ID) [必須]
子要素
<adaptor>入出力ポートの設定および [0個以上]
<agent >同 上
<script>初期起動スクリプトの設定 [0個以上]
<onexec>周期実行(onExecution)スクリプトの設定 [0個または1個]
<ontimeout>一定時間入力またはGUIイベントが発生しなかったときに実行されるスクリプト [0個または1個]

adaptor要素 (agent要素)

eSEATでは、外部のコンポーネントとの通信のためにRTCのデータポートまたはTCPソケットポート(以下、ポートという)を定義することができます。
ポートのの定義は、<adaptor>タグ(または<agent>タグ)で設定を行います。このタグの定義は下記のようになっています。
  <xs:element name="adaptor">
    <xs:complexType>
      <xs:attribute name="name" use="required" type="xs:string"/>
      <xs:attribute name="type" use="required" type="xs:string"/>
      <xs:attribute name="datatype" use="optional" type="xs:string"/>
      <xs:attribute name="host" use="optional" type="xs:string"/>
      <xs:attribute name="port" use="optional" type="xs:string"/>
      <xs:attribute name="dir" use="optional" type="xs:string"/>
      <xs:attribute name="interface" use="optional" type="xs:string"/>
      <xs:attribute name="if_class" use="optional" type="xs:string"/>
    </xs:complexType>
  </xs:element>
この定義からもわかるように<adaptor>タグには、nameとtypeという属性を必ず記述する必要があります。nameは、eSEATコンポーネント内でポートを識別するためのIDであり、typeは、作成するポートの種類にになります。ポートの種類として、rtcin, rtcout, consumer, provider, socket,web の6つを設定することができます。
また、ポートの定義には、datatype, host, port, dir, interface, if_classの属性を持つことができますが、
  • typeがrtcin,rtcoutのときには、OpenRTM-aistのデータポートが生成され、データ型をdatatype属性で設定します。
  • typeがcomsumer,providerのときには、OpenRTM-aistのサービスポートが生成され、インターフェース型をinterface属性で, インターフェスの実装をif_class属性で設定します。
  • typeがsocketの場合には、TCPソケットポートを生成しますので、hostとportの属性で、接続先のホスト名とポート番号を設定します。
  • typeがwebの場合には、HTTPサービスのポートを生成し、dir属性でHTTPサービスのROOTディレクトリを設定します。
下記の例では、gestureとlongalueという名前の入力データポート(データ型は、それぞれTimedStrng,TimedLong)とcommandという名前の出力データポート(データ型は、TimedString)、ppt,mplayerという名前のTCPソケットポートを生成しています。
ソケットポートを用いる場合には、eSEATコンポーネントがActivateになるとき(onActivatedの実行時)に接続されます。
   <general name="demo1">
     <adaptor rname="gesture" type="rtcin" datatype="TimedString" />
     <adaptor name="longvalue" type="rtcin" datatype="TimedLong" />
     <adaptor name="command" type="rtcout" datatype="TimedString" />
     <adaptor name="ppt" type="socket" host="localhost" port="10030" />
     <adaptor name="mplayer" type="socket" host="localhost" port="10020" />
     <adaptor name="Comet" type="web"  port="8080" host="myhost" />
   </general>
タグ名
<adaptor>
属性
name識別子(ID) [必須]
typeポートの種類(rtcin, rtcout, socket, web, consumer, provider) [必須]
datatypertcin, rtcoutのポート設定時、入出力するデータ型
hostsocketのポート設定時、接続先のマシン名またはIPアドレス,webのポート設定時、exec関数実行可能なマシン名またはIPアドレス
portsocket,webのポート設定時、接続先のポート番号
dirWebAdaptorのドキュメントルート
interfaceサービスポート(consumer, provider)設定時、インターフェース型+"|"+インターフェース名
if_classサービスポート(consumer)設定時、インターフェース名 
サービスポート(consumer)設定時、実装クラス名
子要素
なし
注意:
eSEATでは、入力されるデータの入力ボートを同定する時にname属性で設定された識別子を使います。ただし、全ての入力ポートを対象にするための識別子としてdefaultという識別子を予約語として使っていますのでSEATMLスクリプトでは、利用することができませんのでご注意下さい。

script要素

eSEATでは、外部ファイルに記述したPythonのスクリプトまたはSEATMLのscript要素内に記載されたPythonスクリプトを実行する機能があります。この機能は、後述のrule要素等でも利用可能ですが、general要素の子要素として記載した場合には、SEATMLの読込時に対応するPythonスクリプトコードが評価されます。
eSEATの内部では、execfile関数を用いたスクリプトコードの評価を実行しています。
scriptタグの定義は下記のようになっています。
  <xs:element name="script">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="execfile" use="optional" type="xs:string"/>
          <xs:attribute name="sendto" use="optional" type="xs:string"/>
          <xs:attribute name="host" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
この定義では、sendtoという属性を設定することができますが、general要素の子要素の場合には、無視されますのでご注意ください。
タグ名
<script>
属性
execfile実行するPythonスクリプトの外部ファイル名
sendtogeneralの子要素の時には、無視されます
子要素
実行するPythonのスクリプトコード

var要素

var要素は、eSEATのscript要素で共通に使う変数の宣言を行うことができます。通常のPythonのプログラムでいう大域変数の設定になります。value属性がない場合には、初期値は 'None' になっています。
このvar要素は、<script>要素を使っても同等の機能を実現できますので付加的な機能と理解して頂ければよいと思います。
  <xs:element name="var">
    <xs:complexType>
      <xs:attribute name="name" use="required" type="xs:string"/>
      <xs:attribute name="value" use="optional" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<var>
属性
nameeSEATのScriptタグの中で有効な大域変数名 [必須]
value初期値[任意]
子要素
なし

onexec要素

onexec要素は、RTコンポーネントの周期動作時(onExecuteの呼出し時)に実行するコマンドを指定します。この要素は、general要素またはstate要素の子要素となるが、general要素の子要素の場合には、eSEATの動作時に共通のコマンドとなり、state要素の子要素の場合には、その状態の時の周期実行コマンドになります。なお、state要素とgeneral要素の両方に指定されていた場合、まずstate要素の子要素となっている<onexec>のコマンドが実行され、次にgeneral要素の子要素となっている<onexec>コマンドが実行されます。
なお、ontimeout要素が設定されている場合、<ontimeout>の実行がonexec要素のコマンドよりも先に実行され、その周期では、<onexec>のコマンドは実行されません。
  <xs:element name="onexec">
    <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
        </xs:choice>
    </xs:complexType>
  </xs:element>
タグ名
<onexec>
属性
なし
子要素
messagesendto属性に指定されたポートに対して、子要素に記載された文字列を送信する
shell子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。
scriptexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。

ontimeout要素

ontimeout要素は、データポートからの入力またはGUIのイベントがtimeout属性で設定した時間以上なければ実行するコマンドを指定します。この要素は、general要素またはstate要素の子要素となるが、general要素の子要素の場合には、eSEATの動作時に共通のコマンドとなり、state要素の子要素の場合には、その状態の時のタイムアウト動作となります。なお、state要素とgeneral要素の両方に指定されていた場合、state要素内の<ontimeout>のみが有効になります。
  <xs:element name="ontimeout">
    <xs:complexType>
      <xs:sequence>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="log"/>
          <xs:element minOccurs="0" maxOccurs="1" ref="statetransition"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute name="timeout" use="required" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<ontimeout>
属性
timeoutタイムアウトの秒数(浮動小数点型の値)[必須]
子要素
messagesendto属性に指定されたポートに対して、子要素に記載された文字列を送信する
shell子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。
scriptexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。
log子要素の内容をLoggerに出力する。
statetransition[ 0または1個 ]

state要素

state要素は、eSEATコンポーネントの中心となる要素です。このstate要素は、eSEATの内部状態を表し、この要素の子要素で記述された振舞を設定、statetransition要素による状態間遷移を設定することでeSEATコンポーネントは、有限状態機械と同等の振舞いをします。
SEATMLでは、複数の状態を<state>タグで内部状態を定義することができます。state>タグには、name属性を記述する必要があります。また、state要素の子要素として、onentry要素、onexit要素、rule要素を設定することで、その状態に遷移時(開始時)の振舞、その状態から別の状態に遷移するとき(終了時)の振舞、その状態ないでのイベントに対する振舞を設定することができます。
さらに、state要素には、GUIによる入力パネルを設定する機能も有しており、ボタン、テキスト入力などの簡単な入力パネルからのイベント処理も記述可能になっている。
state要素は、seatmlスキーマでは下記のように定義されています。
 <xs:element name="state">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="onentry"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="onexit"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="ontimeout"/>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="rule"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="label"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="button"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="input"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="text"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="brk"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" ref="space"/>
        </xs:choice>
      </xs:sequence>
      <xs:attribute name="name" use="required" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<state>
属性
name状態の識別子(ID)[必須]
子要素
onentryこの状態の開始時に子要素で設定したコマンドを実行する。
onexitこの状態の終了時にに子要素で設定したコマンドを実行する。
ontimeout一定時間入力またはGUIイベントが発生しなかったときにコマンドを実行する。general要素で指定した<ontimeout>を上書きする。
rule外部コンポーネント等からのイベントに対応してに子要素で設定したコマンドを実行する。
labelGUIパネルのラベルアイテム
buttonGUIパネルのボタンアイテム。ボタン押下時に、子要素で設定したコマンドを実行する。
inputGUIパネルの一行文字列入力アイテム。<ENTER>キー入力時に子要素で設定したコマンドを実行する。
textGUIパネルの複数行文字列出力アイテム。
brkGUIパネルのアイテム配置制御用。
spaceGUIパネルのアイテム配置制御用。
注意:
state要素では、name属性の値で内部状態を識別しています。ただし、予め全ての内部状態を識別するためにallという識別子を予約語として使っています。従って、SEATMLスクリプトでは、state要素のname属性には、allという識別子を使うことができませんのでご注意下さい。

onentry要素

この要素は、eSEATの内部状態が、親要素のstate要素で定義された内部状態に遷移したときに実行するコマンドを定義します。この要素は、<onentry>タグを用いて記述します。
onentry要素に定義するコマンドは、この要素の子要素として記述します。コマンドして記述可能な要素は、後述のrule要素、button要素とほぼ同様にcond要素、message要素、shell要素、script要素になります。これらの要素に関する詳細は、後述いたしますのでそちらを参照してください。
また、この要素は、onexit要素よりも前に記述する必要があります。
onentry>タグは、スキーマでは、下記のように定義されています。
  <xs:element name="onentry">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="cond"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
タグ名
<onentry>
属性
なし
子要素
condexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、コマンド実行のための条件を設定する。[ 0または1個 ]
messagesendto属性に指定されたポートに対して、子要素に記載された文字列を送信する
shell子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。
scriptexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。
例えば子要素として message要素で設定されたコマンドが設定された場合、eSEATの内部状態が親要素のstateで識別される内部状態に遷移した時に、<message>タグの必須属性sendtoに対応した識別子を持つポート(adaptor要素のnameの属性と一致したポート)に対してmessage要素の子要素の文字列を送信します。
すなわち"command"という名前を持ったadaptorに"TEST"文字列を出力したい場合には、下記のように記述します。
  <message sendto="command">TEST</message>

onexit要素

この要素は、eSEATの内部状態が、親要素のstate要素で定義された内部状態から別の内部状態に遷移するときに実行するコマンドを定義します。この要素は、<onexit>タグを用いて記述します。
onexit要素に定義するコマンドは、前述のonentry要素と同じです。
また、この要素は、onentry要素よりも後かつrule要素等よりも前に記述する必要があります。
onexit>タグは、スキーマでは、下記のように定義されています。
  <xs:element name="onexit">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="cond"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
タグ名
<onexit>
属性
なし
子要素
condexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、コマンド実行のための条件を設定する。[ 0または1個 ]
messagesendto属性に指定されたポートに対して、子要素に記載された文字列を送信する
shell子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。
scriptexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。
onexit要素の子要素として定義されるコマンドの記述方法に関しては、onentry要素と同じです。

rule要素

rule要素は、eSEATコンポーネント内部動作を記述する最も代表的な要素です。親要素のstate要素で定義された内部状態での振舞いをこの要素で定義しています。rule要素には、0または1つのcond要素、0個以上のkey要素でコマンドの実行条件を設定し、その条件のいづれかを見たした時にrule要素の子要素として記述されたmessage要素、script要素、shell要素、statetransition要素のコマンドが実行されます。コマンドは、任意の数を記述することができます。
以下では、message要素、script要素、shell要素、statetransition要素のことをコマンド要素と呼びます。
rule要素のスキーマでの定義は下記のようになっています。
  <xs:element name="rule">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="1" ref="cond"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="key"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="statetransition"/>
      </xs:sequence>
      <xs:attribute name="source" use="optional" type="xs:string"/>
      <xs:attribute name="file" use="optional" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<rule>
属性
sourceこの属性は、ポートの識別子を指定することで、指定されたポートからのデータを対象としたruleとして振る舞います。
fileこの属性で指定されたseatmlファイル内の指定された状態内のrule群をインポートします。状態が明示的に指定されていない場合には、最初に定義している状態のrule群をインポートします。(test1.seatml:main_stateという指定の場合には、最初に読み込んだseatmlのあるディレクトリ内のtest1.seatml内のmain_stateという状態で定義されたrule群をインポートします。)
子要素
condexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、コマンド実行のための条件を設定する。[ 0または1個 ]
keyこの要素はコマンド実行のための条件を設定します。TEXT要素に指定された文字列と入力された文字列が一致した場合に真となります。この要素は任意の数だけ設定することができます。
messagesendto属性に指定されたポートに対して、子要素に記載された文字列を送信する
shell子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。
scriptexecfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。
statetransitionこの要素は、eSEATの内部状態を別の状態に遷移させます。
cond要素
cond要素は、rule要素とbutton要素、input要素などコマンド要素を子要素にもつ要素と同時に利用します。この要素は、並列にあるコマンド要素を実行するかどうかの条件を設定するために要素です。cond要素内のTEXTをeval関数で評価し、偽でない場合に並列に設定されたコマンド要素を実行します。
スキーマでは、下のように定義されています。
  <xs:element name="cond">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="execfile" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
cond要素は、execfile属性をとることができます。execfile属性で指定された値は、外部のPythonスクリプトファイル名でなければいけません。このファイルは、cond要素内のTEXTをeval関数で評価する前に、execfile関数で評価されます。
タグ名
<cond>
属性
execfileこの属性の値として指定された外部ファイルを、TEXT要素を評価する直前にexecfile関数で評価します。
子要素
なし
例えば、
  <cond execfile="cond1.py">cond_val</cond>
という記述があった場合には、eSEAT内部では、まずexecfile('cond1.py')が実行され、次にglobal変数である、cond_val がeval関数で評価されることになります。そのため、cond_valというglobal変数が、general要素内で定義されているか、cond1.pyの中でglobal変数を定義していなければいけません。
なお、この要素は、rule要素とbutton要素、input要素などの親要素には、複数定義することはできませんのでご注意してください。
key要素
key要素はcond要素と同じく並列のコマンド要素の実行条件を設定します。この要素はsourse属性を持つことができます。source属性値は、adaptor要素で定義したポート記述子(ID)であり、この属性値のポートからの文字列とkey要素のTEXT要素が一致した場合に、並列のコマンド要素が実行されます。
また、sourse属性値に対応するポートのデータ型がTimedString型ではない場合は、TEXT要素を評価して動作条件判定をおこないます。
sourse属性を設定してない場合には、全ての TimedStringのデータポートまたはTCPソケットポートから受信した文字列が条件評価の対象となります。
key要素のスキーマの定義は、下記のようになっています。
 <xs:element name="key">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="source" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
タグ名
<key>
属性
sourceこの属性の値同じ識別子を持つポートからの文字列対象とし、動作条件評価を行います。
子要素
なし
message要素(command要素)
message要素は、rule要素等の子要素として記述されます。並列の要素としてcond要素またはkey要素があった場合は、それらの要素で動作条件判定の結果によって、TEXT要素に記述された文字列またはその評価結果をsendto属性で指定したポートに送信します。
送信するデータは、送信ポートのデータ型によって下記のようになっています。
データ型TEXT要素の内容 (T)
TimedStringTimedString.data=T とし、代入して送信
TimedOctet,TimedShort,TimedLongTimedxxx.data = int(T) とし、代入して送信
TimedFloat,TimedDoubleTimedxxx.data = float(T) とし、代入して送信
上記のSequence型','でデータ分割し、上記と同じように代入して送信
上記以外のデータ型exec(T)を実行した結果をそのまま送信
例えば、TimedString のポート p1 へデータを送信する場合、
  <message sendto="p1">Test String</message>
の場合には、TimedString(Time(0,0), "Test String") と同等のデータに変換されて、p1という識別子を持つポートへデータ送信を行います。
また、TimedPose2Dのポート p2 へデータを送信する場合、TimedPose2Dとうデータ型は
 TimedPose2D = { Time tm; Pose2D data; }
 Pose2D = { Point2D position; double heading; }
 Point2D = { double x, y;  }
のように定義されていますので、message要素は、下記のように定義することができます。
  <message sendto="p2">Time(0,0), Pose2D(Point2D(10, 20), 30)</message>
eSEATの内部では、message要素のTEXT要素を出力データポートのデータ型に、TEXT要素をeval関数で評価、変換を行いますので、message要素で任意のデータ型を送信する場合にはご注意ください。
この要素は、任意の数だけ記述することができます。
その他の属性として、message要素には、encode属性とinput属性を設定することができます。
encode属性は、TimedString型の出力データポートまたはSocketポートへの文字列の出力を行う場合に、文字コードの変換を行うことができます。文字コードの変換は、Pythonの文字列に対するencodeメソッドを使って実装していますので、属性値を設定するときは、ご注意ください。
input属性は、出力するデータをmessage要素のTEXT要素のように固定値ではなく、後述するinput要素で生成される一行入力GUIアイテムから実行時に指定できるようにするために付加したものです。利用されるGUIアイテムは、input属性値と同じ識別子を持つinput要素になります。この属性が設定されるとTEXT要素は完全に置き換えられますのでご注意ください。
なお、message要素のスキーマの定義は、下記のようになっています。
  <xs:element name="message">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="sendto" use="required" type="xs:string"/>
          <xs:attribute name="encode" use="optional" type="xs:string"/>
          <xs:attribute name="input" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
タグ名
<message>
属性
sendto[必須]属性値と一致した識別子を持つポートに対してTEXT要素の文字列またはその評価の結果を送信する
inputこの識別子と一致するinput要素の一列入力文字入力にある文字列をTEXT要素の代わりに送信する。
encode文字列を送信する場合に、TEXT要素をこの属性で指定されている文字コードへ変換した後送信する。
子要素
なし
script要素
script要素は、rule要素等の要素内では、key要素やcond要素で設定された動作条件が満たされた場合に評価されるPythonスクリプトを設定します。
この要素には、sendto属性を記述することができ、この属性値と同じ識別子を持つポートに評価結果を出力することができます。ただし、出力データは出力ポートのデータ型に合わせてrtc_resultというグローバル変数のデータを結果を出力しておく必要があります。
ここで注意しなければいけないのは、記述されたコードは、Pythonスクリプトとして評価(実行)されますので、インデントなしで記述してください。
例えば、下記の例では、グローバル変数current_itemが10の場合に、この値を1減じて9とし、pptという名前のポートにを(select 9)という文字列を出力します。
 <script sendto="ppt">
 global current_item
 current_item -= 1
 rtc_result="(select %d)" % current_item
 </script>
また、script要素では、execfile属性とsendto属性を設定することができます。
execfile属性は、eSEATの外部にあるPythonスクリプトのファイル名を指定することで、script要素の動作時に、外部ファイルからPythonのコードを読み込み、実行します。この機能は、execfile関数で実装されていますので、eSEATの動作時にこの外部ファイルを修正すると全体の振舞が変更されますので注意してください。また、この外部スクリプト実行は、TEXT要素を評価する前に実行されます。
sendto属性は、script要素の動作結果をデータポート等に出力するために使用します。sendto属性値と一致すする識別子を持つポート(adaptor要素)に対して、script要素の動作終了時に、rtc_resultというグローバル変数に格納されたデータの出力を行います。このとき出力するデータは、必ず、出力データポート等のデータ型に合わせるようにしてください。正しいデータ型になっていない場合には、内部的にはエラーとなり何も出力されません。
この要素は、rule要素内では、任意の数だけ記述することができます。
なお、script要素のスキーマは下記のように定義されており、これは前述のgeneral要素の子要素となるscript要素と同じ定義です。
script要素内にPythonスクリプトを記述する場合に、"<"の記号を書いてしまうとXMLのタグと間違えてしまいますので、そのままでは開始時にエラーになってしまいます。そのため、スクリプトを直接記述する場合にが、"<!--", "-->"で挟んで、コメントにしてしまうとうまくいきます。
また、ここに記載するPythonスクリプトには、eSEAT.pyで定義している関数、クラス関数が使えます。自分のコンポーネントオブジェクトは、"seat"という大域変数に格納されています。
  <xs:element name="script">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="execfile" use="optional" type="xs:string"/>
          <xs:attribute name="sendto" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
タグ名
<script>
属性
execfileこの属性の値として指定された外部ファイルを、TEXT要素を評価する直前にexecfile関数で評価します。
sendtoこの属性の値と同じ識別子をもつポートに対してrtc_resultの内容を出力します。
子要素
なし
shell要素
shell要素は、rule要素等の要素内では、key要素やcond要素で設定された動作条件が満たされた場合に実行されるシェルコマンドを設定します。この要素の動作時には、eSEAT内ではPythonのsystem関数にTEXT要素の文字列を引き渡して実行しています。
この要素には、sendto属性を記述することができます。''sendto'属性が設定されると、その属性値と一致する識別子を持つポート(adptor要素)に対して、system関数の返り値を結果として出力します。
この要素は、任意の数だけ記述することができ、スキーマの定義は下記のようになっています。
  <xs:element name="shell">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="sendto" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
タグ名
<shell>
属性
sendtoこの属性の値と同じ識別子をもつポートに対してsystem関数の返り値を出力します。
子要素
なし
statetransition要素
statetransition要素は、rule要素等の要素内では、key要素やcond要素で設定された動作条件が満たされた場合にeSEATの内部状態の遷移を行います。
遷移する状態の指定は、この要素のTEXT要素の値と一致した識別子を持つstate要素になります。
例えば、
   <statetransition>ppt_mode</statetransition>
のように記述した場合は、ppt_modeに内部状態を遷移させることができます。
このとき、TEXT要素に空白等があった場合には、誤動作等が生じる可能性がありますので注意してください。
この要素が動作するとeSEAT内の状態が即座に遷移しますので、他のコマンド要素と並列して使用する場合には、message要素、script要素、shell要素のコマンド要素よりも後(一番最後)に記述するようにしてください。
上記のような理由により、この要素はrule要素等の子要素としては、1つつだけ記述することができます。
また、この要素には、func属性を設定することができます。この属性値は、push,popという値をとることができます。この属性値が設定されると内部状態の遷移履歴の操作を行います。(通常は、状態の履歴管理は行いません)この属性値として、pushが指定されると遷移前の状態の識別子を内部スタックに挿入し、popが指定されると内部状態の最上部の要素を取り除きます。
statetransition要素のスキーマの定義は下記のようになっています。
  <xs:element name="statetransition">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:NCName">
          <xs:attribute name="func" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
タグ名
<statetransition>
属性
funcこの属性値は、push,popという値をとることができます。この属性値が設定されると内部状態の遷移履歴の操作を行います。(通常は、状態の履歴管理は行いません)
子要素
なし

GUIパネルを構成する要素

eSEATでは、SUITで実装していたGUIパネルの作成機能を一部拡張を伴いながら統合を行いました。このGUIに関しては、PythonのTkinterのみを使用しており、以下に記載された要素をSEATLML内で定義した場合のみ、Tkinterの初期化とメインループをTkinterの方へ切り替えを行っています。
このメインループ部分の実装は、下記のようになっています。
        if self.comp.hasGUI() :
            self.manager.runManager(True)
            
            # GUI part
            self.comp.root = Tk()
            for st in self.comp.states:
                self.comp.newFrame(st)
                self.comp.create_gui(st)
            self.comp.show_frame(self.comp.init_state)
            self.comp.frames[self.comp.init_state].pack()
            self.comp.setTitle(self.comp.getInstanceName())
            self.comp.root.mainloop()
            
            self.comp.disconnectAll()
            
            # Shutdown Component
            try:
               self.manager.shutdown()
            except:
               pass 
            
            sys.exit(1)
        else:
            self.manager.runManager()
GUIパネルとしては、最低限のGUIを実現することを念頭において実装していますので、あまりいろいろなことはできません。また、GUIアイテムのレイアウトもGRID形式のみをサポートしており、複雑なレイアウトや各アイテムの大きさの調整等は実装していません。
基本的には、HTMLの表のようなパネルをイメージし、各アイテムがSEATMLスクリプト内での出現順に配置されていくと考えるとよいと思います。
このGUIパネル生成機能を使うと下記のようなGUIを簡単に作成することができます。

以下では、eSEATでサポートしているGUIパネル構成要素について述べます。
label要素
label要素は、単純な文字列表示のラベルアイテムを生成します。この要素は、text属性を必須属性としており、必ず設定しなければいけません。このtext属性値がLabelアイテムに表示されます。また、オプション属性としてcolor, bg_color, colspanの属性を設定することができます。
color属性とbg_color属性は、それぞれLabelアイテムの文字列の色、背景の色に対応しており、text属性値、color属性値、bg_color属性値が name, fg, bg だった場合に、eSEAT内部では、
  Label(frame, text=name, bg=bg, fg=fg )
のようにLabelアイテムを生成します。
また、colspan属性は、Labelアイテムをパネルに配置する場合に指定可能な属性です。
eSEATでは、GRID形式のアイテム配置packのみを利用するようにしています。そのため、横方向に何カラム分の大きさで配置するかをこの属性値で設定することができます。
なお、この要素のスキーマは下記のように定義されています。
  <xs:element name="label">
    <xs:complexType>
      <xs:attribute name="text" use="required" type="xs:string"/>
      <xs:attribute name="color" use="optional" type="xs:string"/>
      <xs:attribute name="bg_color" use="optional" type="xs:string"/>
      <xs:attribute name="colspan" use="optional" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<label>
属性
text表示するテキスト[必須]
colorテキストの色
colspanGIRD形式のpack時にLabelを配置する横方向の幅
子要素
なし
button要素
button要素は、単純な文字列をラベルとして持つのボタンアイテムを生成します。この要素は、label属性を必須属性として必ず設定しなければならず、この文字列を持ったボタンアイテムを生成し、配置します。
また、オプション属性として、color,bg_color, colspanを設定することができます。このオプション属性を設定することでGUIパネル上のボタンアイテムの見た目を変更することができます。各属性の機能としては、label要素と同じです。
また、この要素は子要素としてコマンド要素を持つことができます。対応するボタンアイテムが押下された場合に、子要素であるコマンド要素が動作します。
この要素は、rule要素と非常によく似た動作をしますが、rule要素が外部からのデータによって駆動しますが、button要素は、GUIのボタンを押下することで動作することが大きな違いです。
この要素のスキーマの定義を下に示します。
  <xs:element name="button">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="statetransition"/>
      </xs:sequence>
      <xs:attribute name="label" use="required" type="xs:string"/>
      <xs:attribute name="color" use="optional" type="xs:string"/>
      <xs:attribute name="bg_color" use="optional" type="xs:string"/>
      <xs:attribute name="colspan" use="optional" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<button>
属性
label表示するテキスト[必須]
colorテキストの色
colspanGIRD形式のpack時にButtonを配置する横方向の幅
子要素
messageボタンアイテム押下時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する
shellボタンアイテム押下時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。
scriptボタンアイテム押下時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。
statetransitionボタンアイテム押下時に、この要素は、eSEATの内部状態を別の状態に遷移させます。
input要素
input要素は、一行の文字列入力を行うためのGUIアイテムを生成します。eSEATの内部では、TkinterのEntryを用いて実現しています。
この要素は、id属性を必須属性として必ず設定しなければならず、この属性値を識別子として使用します。前述していますが、script要素のPythonスクリプトでこのアイテムの入力フィールドの中の文字列を得るには、
 seat.getEntry('id属性値')
とします。また、このアイテムの入力フィールドに文字列を入れたい場合には、
 seat.setEntry('id属性値', '入力したい文字列')
のようなスクリプトを設定してください。
例えば、下記のようにinput1というIDを持つinput要素とexecというラベルのbutton要素作成し、input1に入力したPythonのコマンドを実行させたい場合には、
   <input id="input1" width="50" colspan="3"></input>
   <button label="exec">
      <script>
 exec(seat.getEntry("input1"), globals())
      </script>
   </button>
と記述できます。
また、オプション属性として、widthcolspanを指定することができます。width属性は、入力アイテムの幅を設定するための属性であり、単位は文字数です。上記の例では、50文字分の入力アイテムを生成します。
colsoan属性は、label要素やbutton要素の同名属性と同じ機能です。
この要素でも、子要素としてコマンド要素を持つことができます。子要素が設定された場合にが、<ENTER>キー入力時に動作するようになっています。現在のところ入力アイテムにおける他のキーバインドについてカスタマイズは不可にしています。
なお、input要素のスキーマでの定義は下のようになっています。
  <xs:element name="input">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
        <xs:element minOccurs="0" maxOccurs="1" ref="statetransition"/>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:string"/>
      <xs:attribute name="width" use="optional" type="xs:string"/>
      <xs:attribute name="colspan" use="optional" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<input>
属性
id入力アイテムの識別子[必須]
width入力アイテムの幅(文字数)
colspanGIRD形式のpack時にEntryを配置する横方向の幅
子要素
message<ENTER>キー入力時に、sendto属性に指定されたポートに対して、子要素に記載された文字列を送信する
shell<ENTER>キー入力時に、子要素に記載された文字列を、system関数で評価し、Shellコマンドを実行する。
script<ENTER>キー入力時に、execfile属性で指定されたPythonスクリプトファイルをexecfile関数で評価し、子要素に記載された文字列があれば、exec関数で評価しPythonスクリプトを実行する。
statetransition<ENTER>キー入力時に、この要素は、eSEATの内部状態を別の状態に遷移させます。
text要素
text要素は、複数行の文字列入力を行うためのGUIアイテムを生成します。eSEATの内部では、TkinterTextを用いて実現しています。
この要素は、id属性を必須属性として必ず設定しなければならず、この属性値を識別子として使用します。前述していますが、script要素のPythonスクリプトでこのアイテムの入力フィールドの中の文字列を得るには、
 seat.getText('id属性値')
とします。また、このアイテムの入力フィールドに文字列を入れたい場合には、
 seat.appendText('id属性値', '追加入力したい文字列')
とします。このメソッドは、現在のTextアイテム内に文字列を追加する機能であり、input要素のように文字列を置き換えるわけではありません。そのため、現在のアイテム内の文字列を消去するために clearTextというメソッドも定義しています。すなわち、
   seat.clearText('id属性値')
とすれは、アイテム内の文字列をすべて消去します。
また、オプション属性として、widthheight、'colspanrowspan''を指定することができます。width属性は、入力アイテムの幅を設定するための属性であり、単位は文字数です。height属性は、入力アイテムの高さを設定するための属性であり、単位は行数です。colsoan属性は、label要素やbutton要素の同名属性と同じ機能です。rowsoan属性は、colspan属性の縦方向版です。
この要素でも、子要素としてコマンド要素を持つことができようになっています。しかしながら、現在のところ子要素としてコマンド要素を設定しても動作しないと思います。
なお、text要素のスキーマでの定義は下のようになっています。
  <xs:element name="text">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="message"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="shell"/>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="script"/>
      </xs:sequence>
      <xs:attribute name="id" use="required" type="xs:string"/>
      <xs:attribute name="width" use="optional" type="xs:string"/>
      <xs:attribute name="height" use="optional" type="xs:string"/>
      <xs:attribute name="colspan" use="optional" type="xs:string"/>
      <xs:attribute name="rowspan" use="optional" type="xs:string"/>
    </xs:complexType>
  </xs:element>
タグ名
<text>
属性
id入力アイテムの識別子[必須]
width入力アイテムの幅(文字数)
height入力アイテムの行数
colspanGIRD形式のpack時にTextを配置する横方向の幅
rowspanGIRD形式のpack時にTextを配置する縦方向の幅
子要素
message〔動作条件が未実装〕
shell〔動作条件が未実装〕
script〔動作条件が未実装〕
brk要素
brk要素は、上述のlabel要素等とはことなり、GUIのパネルアイテムを生成しません。
この要素は、GUIのパネルアイテムを配置するための要素であり、HTML等での<br>のような機能を果たします。
すなわち、eSEATでは、GUIアイテムの配置を横方向のみの配置したサポートしていないためそのままでは複数行になるテーブルのようなGUIパネルの生成ができません。
そのため、この要素が出現したところで強制的に改行させるようにしています。
brk要素のスキーマの定義は、下記のようになっています。
  <xs:element name="brk">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="comment" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
タグ名
<brk>
属性
commentコメントの入力。eSEATでは不使用。
子要素
なし
space要素
space要素は、前述のbrk要素と同じようにGUIアイテムの配置を制御するための要素です。
brk要素が改行のような機能を実現していますが、このspace要素を、GRID形式は左詰めで配置されるGUIアイテムの途中で挿入することで、GUIアイテムをスキップさせて配置させることができます。
また、この要素は length属性を持つことができ、length="2"のように記載することで2枡スキップして次のGUIアイテムを配置させることができます。
space要素のスキーマの定義は、下記のようになっています。
 <xs:element name="space">
    <xs:complexType>
      <xs:simpleContent>
        <xs:extension base="xs:string">
          <xs:attribute name="length" use="optional" type="xs:string"/>
        </xs:extension>
      </xs:simpleContent>
    </xs:complexType>
  </xs:element>
タグ名
<space>
属性
lengthスキップする枡数
子要素
なし