Help us understand the problem. What is going on with this article?

Pepperのファイル探訪(プロジェクトファイル)

More than 5 years have passed since last update.

Pepperの開発ツールChoregrapheにおいて、プロジェクト単位で共同作業しようとか考え始めると、これらのファイルの形式や内容が知りたくなってきます。
特に、GitHubとかそういうところでバージョン管理、共同編集しようとすると、差分がどう見えるのかが重要になってくるので、テキストだったらいいなとか思うわけです。

ドキュメントを読んでも、あまり形式については詳しく言及されていなかったのでざっくり見てわかる範囲で調べてみたので簡単に書いてみます。今回はプロジェクトファイルをお題に。

結論としては、XMLをベースにファイルが構成されているので、GitHubとかでもうまく差分が見えて、比較的気持ちよく管理できるかも、といった感じ。

プロジェクトファイル

Choregrapheでプロジェクトを保存すると、以下のような感じの構成のファイルができる。

  • (プロジェクト名)フォルダ
    • (プロジェクト名).pml
    • manifest.xml
    • .metadata
    • (ビヘイビア名)フォルダ
      • behavior.xar

基本的には、[プロジェクトの内容]パネルで見えているファイル構成ができている雰囲気。

(プロジェクト名).pml

プロジェクトファイルの基点となるファイルで、この拡張子のファイルを開くと関連付けられているChoregrapheが起動する。
*mlなのでXMLだろうと思って開くとこんな感じ。

<?xml version="1.0" encoding="UTF-8" ?>
<Package name="HogeHoge" format_version="4">
    <Manifest src="manifest.xml" />
    <BehaviorDescriptions>
        <BehaviorDescription name="behavior" src="behavior_1" xar="behavior.xar" />
    </BehaviorDescriptions>
    <Dialogs />
    <Resources />
    <Topics />
</Package>

これなら、リソース追加したとか、そういった差分が簡単にわかりそう。

manifest.xml

拡張子の通りでXML。

<?xml version='1.0' encoding='UTF-8'?>
<package uuid="hogehoge-ee8dd3">
 <names>
  <name lang="en_US">Hogehoge</name>
 </names>
 <supportedLanguages>
  <language>en_US</language>
 </supportedLanguages>
 <descriptionLanguages>
  <language>en_US</language>
 </descriptionLanguages>
 <contents>
  <behaviorContent path="behavior_1">
   <nature>interactive</nature>
   <permissions/>
  </behaviorContent>
 </contents>
</package>

プロジェクトのプロパティで設定しているような内容が入っている。ドキュメントによると、Storeにアップロードする際に必要となるような種類の情報っぽい。

.metadata

自分が作成したプロジェクトでは、空のファイルだった。ドキュメントにも言及なし?

behavior.xar

拡張子的に、何か圧縮されたアーカイブかな・・・と思ってバイナリエディタで開いてみるも、これもXML。
フローダイアグラムで書いていた内容が、ボックスの内容合わせてXMLとして保存されている感じで、これも変更があれば差分で見えてきそう。

<?xml version="1.0" encoding="UTF-8" ?>
<ChoregrapheProject xmlns="http://www.aldebaran-robotics.com/schema/choregraphe/project.xsd" xar_version="3">
    <Box name="root" id="-1" localization="8" tooltip="Root box of Choregraphe&apos;s behavior. Highest level possible." x="0" y="0">
        <bitmap>media/images/box/root.png</bitmap>
        <script language="4">
            <content>
                <![CDATA[]]>
</content>
        </script>
        <Input name="onLoad" type="1" type_size="1" nature="0" inner="1" tooltip="Signal sent when diagram is loaded." id="1" />
        <Input name="onStart" type="1" type_size="1" nature="2" inner="0" tooltip="Box behavior starts when a signal is received on this input." id="2" />
        <Input name="onStop" type="1" type_size="1" nature="3" inner="0" tooltip="Box behavior stops when a signal is received on this input." id="3" />
        <Output name="onStopped" type="1" type_size="1" nature="1" inner="0" tooltip="ボックス動作の終了時に信号を送る。" id="4" />
        <Timeline enable="0">
            <BehaviorLayer name="behavior_layer1">
                <BehaviorKeyframe name="keyframe1" index="1">
                    <Diagram>
                        <Box name="Say" id="1" localization="8" tooltip="Say some text. Note that you must open the box to enter the text." x="121" y="17">
                            <bitmap>media/images/box/interaction/say.png</bitmap>
                            <script language="4">
                                <content>...</content>
                            </script>
                            <Input name="onLoad" type="1" type_size="1" nature="0" inner="1" tooltip="Signal sent when Diagram is loaded." id="1" />
                            <Input name="onStart" type="1" type_size="1" nature="2" inner="0" tooltip="Box behavior starts when a signal is received on this Input." id="2" />
                            <Input name="onStop" type="1" type_size="1" nature="3" inner="0" tooltip="Box behavior stops when a signal is received on this Input." id="3" />
                            <Output name="onStopped" type="1" type_size="1" nature="1" inner="0" tooltip="Signal sent when box behavior is finished or stopped." id="4" />
                            <Parameter name="Voice shaping (%)" inherits_from_parent="0" content_type="1" value="100" default_value="100" min="50" max="150" tooltip='...' id="5" />
                            <Parameter name="Speed (%)" inherits_from_parent="0" content_type="1" value="100" default_value="100" min="50" max="200" tooltip="..." id="6" />
                            <Timeline enable="0">
                                <BehaviorLayer name="behavior_layer1">
                                    <BehaviorKeyframe name="keyframe1" index="1">
                                        <Diagram>
                                            <Box name="Say Text" id="2" localization="8" tooltip="Say the text received on its input." x="422" y="65">
                                                <bitmap>media/images/box/interaction/say.png</bitmap>
                                                <script language="4">
                                                    <content>
                                                        <![CDATA[import time

class MyClass(GeneratedClass):
    def __init__(self):
        GeneratedClass.__init__(self, False)
        self.tts = ALProxy('ALTextToSpeech')
        self.ttsStop = ALProxy('ALTextToSpeech', True) #Create another proxy as wait is blocking if audioout is remote

    def onLoad(self):
        self.bIsRunning = False
        self.ids = []

    def onUnload(self):
        for id in self.ids:
            try:
                self.ttsStop.stop(id)
            except:
                pass
        while( self.bIsRunning ):
            time.sleep( 0.2 )

    def onInput_onStart(self, p):
        self.bIsRunning = True
        try:
            sentence = "\RSPD="+ str( self.getParameter("Speed (%)") ) + "\ "
            sentence += "\VCT="+ str( self.getParameter("Voice shaping (%)") ) + "\ "
            sentence += str(p)
            sentence +=  "\RST\ "
            id = self.tts.post.say(str(sentence))
            self.ids.append(id)
            self.tts.wait(id, 0)
        finally:
            try:
                self.ids.remove(id)
            except:
                pass
            if( self.ids == [] ):
                self.onStopped() # activate output of the box
                self.bIsRunning = False

    def onInput_onStop(self):
        self.onUnload()]]>
</content>
                                                </script>
                                                <Input name="onLoad" type="1" type_size="1" nature="0" inner="1" tooltip="Signal sent when Diagram is loaded." id="1" />
                                                <Input name="onStart" type="3" type_size="1" nature="2" inner="0" tooltip="Box behavior starts when a signal is received on this Input." id="2" />
                                                <Input name="onStop" type="1" type_size="1" nature="3" inner="0" tooltip="Box behavior stops when a signal is received on this Input." id="3" />
                                                <Output name="onStopped" type="1" type_size="1" nature="1" inner="0" tooltip="Signal sent when Box behavior is finished." id="4" />
                                                <Parameter name="Voice shaping (%)" inherits_from_parent="1" content_type="1" value="100" default_value="100" min="50" max="150" tooltip='...' id="5" />
                                                <Parameter name="Speed (%)" inherits_from_parent="1" content_type="1" value="100" default_value="100" min="50" max="200" tooltip="..." id="6" />
                                            </Box>
                                            <Box name="Localized Text" id="5" localization="8" tooltip="..." plugin="localizationbox_plugin" x="114" y="68">...</Box>
                        <Link inputowner="1" indexofinput="2" outputowner="0" indexofoutput="2" />
                    </Diagram>
                </BehaviorKeyframe>
            </BehaviorLayer>
        </Timeline>
    </Box>
</ChoregrapheProject>

このフォーマットはすごくシンプルでよいのだけど、Say Textボックスのスクリプトがそのまま書かれているのを見る限り、ボックスライブラリからボックスを配置することで、ボックスのコピーが作成されるということなのだなー・・・

ボックスライブラリのアップデートがあった場合に、アップデートされたボックスを使用しているアプリケーション側がどうそのアップデートに追従するか、というのはちょっと考えておいたほうがよいのかもしれない。

こんな感じで、今回はプロジェクトファイルをみてみましたが、GitHubでも差分はおおむねテキストで見えそうなのでバージョン管理、共同作業だなと。
次は、ボックスライブラリファイルについてもみてみたいなとか考え中。またいずれ!

yacchin1205
インフラとかロボットとかとたわむれている人です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした