3. 設定ファイルでまとめて起動する
第 1 章では Process を、第 2 章では Container を、それぞれ別々に起動しました。 実際のロボットでは、カメラやモータ、それを処理する Process など、たくさんの部品を一度に動かします。 この章では、これまでの Process と Container を 1 つの設定ファイルに書いて、まとめて起動します。
サンプルを用意する
Section titled “サンプルを用意する”第 1 章でクローンしてビルドしたサンプル集をそのまま使います。 まだの場合は、第 1 章の「サンプルを用意する」 の手順を済ませてください。
この章では、サンプル集のルートに tutorial.conf という設定ファイルを新しく作ります。
設定ファイルを書く
Section titled “設定ファイルを書く”次の内容で tutorial.conf を作ってください。
name: tutorialoption: http_broker: start: true port: 8000plugins: process_factories: increment_process: path: "./target/debug" container_factories: example_container: path: "./target/debug" processes: example_container_increment: path: "./target/debug" example_container_get: path: "./target/debug"processes: - type_name: increment_process name: inc0 - type_name: increment_process name: inc1containers: - type_name: example_container name: counter0 processes: - type_name: example_container_increment name: increment0 - type_name: example_container_get name: get0name: tutorialoption: http_broker: start: true port: 8000plugins: process_factories: increment_process_python: language: python path: "./process" container_factories: example_container_python: language: python path: "./container" processes: example_container_python_increment: path: "./container" example_container_python_get: path: "./container"processes: - type_name: increment_process_python name: inc0 - type_name: increment_process_python name: inc1containers: - type_name: example_container_python name: counter0 processes: - type_name: example_container_python_increment name: increment0 - type_name: example_container_python_get name: get0name: tutorialoption: http_broker: start: true port: 8000plugins: process_factories: increment_process_cpp: language: "c++" path: "./build/plugins" container_factories: example_container_cpp: language: "c++" path: "./build/plugins" processes: example_container_cpp_increment: path: "./build/plugins" example_container_cpp_get: path: "./build/plugins"processes: - type_name: increment_process_cpp name: inc0 - type_name: increment_process_cpp name: inc1containers: - type_name: example_container_cpp name: counter0 processes: - type_name: example_container_cpp_increment name: increment0 - type_name: example_container_cpp_get name: get0設定ファイルは YAML で書きます。上から順に見ていきましょう。
name と option
Section titled “name と option”name: tutorialoption: http_broker: start: true port: 8000name はこのシステムの名前です。
option の http_broker は、これまで -d で立ち上げていた HTTP ブローカーの設定です。port で待ち受けるポートを変えられます。
plugins: 読み込む
Section titled “plugins: 読み込む”plugins には、どのファイルから型を読み込むかを書きます。第 1 章の --process、第 2 章の --container / --container_process に当たる部分です。
process_factoriesには Process の型を書きます。container_factoriesには Container の型を書き、その下のprocessesに、その Container に結びつく ContainerProcess の型を書きます。
キーには型名を書きます。juiz は path に書いたディレクトリから、型名に合ったファイルを探します。
型名 increment_process なら、./target/debug の中の libincrement_process.so(macOS では .dylib)が読み込まれます。
language を省略すると rust として扱われます。
型名 increment_process_python なら、./process の中の increment_process_python.py が読み込まれます。
language: python を必ず書いてください。ContainerProcess の言語は、親の Container と同じになります。
型名 increment_process_cpp なら、./build/plugins の中の libincrement_process_cpp.so(macOS では .dylib)が読み込まれます。
language: "c++" を必ず書いてください(コマンドラインの -l cpp とは書き方が違います)。ContainerProcess の言語は、親の Container と同じになります。
plugins に書くだけでは、まだ何も動きません。juiz が型(作り方)を覚えるだけです。
processes と containers: 作る
Section titled “processes と containers: 作る”processes と containers には、読み込んだ型からインスタンスを作ることを書きます。第 1 章・第 2 章の -1 に当たる部分です。
type_nameにはpluginsに書いた型名を、nameには作るインスタンスの名前を書きます。processesでは、同じ型increment_processからinc0とinc1の 2 つのインスタンスを作っています。containersでは、Containercounter0を作り、その下のprocessesで、counter0に結びつく ContainerProcessincrement0とget0を作っています。
-1 で作ったときは「型名 + 0」という名前に決まっていましたが、設定ファイルでは好きな名前を付けられます。
設定ファイルを -f で渡して起動します。どの言語でも同じコマンドです。
juiz -f tutorial.conf -dPython の場合は、第 1 章で作った venv を有効にしたターミナルで実行してください。
外から呼び出す
Section titled “外から呼び出す”juiz を起動したまま別のターミナルを開き、Process の一覧を見てみます。
juiz process list# => ["http://127.0.0.1:8000/process/inc0::increment_process", "http://127.0.0.1:8000/process/inc1::increment_process"]juiz container-process list# => ["core://core/container_process/increment0::example_container_increment:counter0", "core://core/container_process/get0::example_container_get:counter0"]juiz process list# => ["http://127.0.0.1:8000/process/inc0::increment_process_python", "http://127.0.0.1:8000/process/inc1::increment_process_python"]juiz container-process list# => ["core://core/container_process/increment0::example_container_python_increment:counter0", "core://core/container_process/get0::example_container_python_get:counter0"]juiz process list# => ["http://127.0.0.1:8000/process/inc0::increment_process_cpp", "http://127.0.0.1:8000/process/inc1::increment_process_cpp"]juiz container-process list# => ["core://core/container_process/increment0::example_container_cpp_increment:counter0", "core://core/container_process/get0::example_container_cpp_get:counter0"]表示される順番は実行ごとに変わることがあります。
同じ型 increment_process のインスタンスが inc0 と inc1 の 2 つ、ID の「インスタンス名」の部分だけが違う形で並んでいます。
それぞれを呼び出してみましょう。
juiz process call "http://127.0.0.1:8000/process/inc0::increment_process" '{"arg1": 3}' -p# => CapsulePtr((value:Value(4), option: []))juiz process call "http://127.0.0.1:8000/process/inc1::increment_process" '{"arg1": 10}' -p# => CapsulePtr((value:Value(11), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/increment0::example_container_increment:counter0" '{"arg1": 5}' -p# => CapsulePtr((value:Value(5), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_get:counter0" '{}' -p# => CapsulePtr((value:Value(5), option: []))juiz process call "http://127.0.0.1:8000/process/inc0::increment_process_python" '{"arg1": 3}' -p# => CapsulePtr((value:Value(4), option: []))juiz process call "http://127.0.0.1:8000/process/inc1::increment_process_python" '{"arg1": 10}' -p# => CapsulePtr((value:Value(11), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/increment0::example_container_python_increment:counter0" '{"arg1": 5}' -p# => CapsulePtr((value:Value(5), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_python_get:counter0" '{}' -p# => CapsulePtr((value:Value(5), option: []))juiz process call "http://127.0.0.1:8000/process/inc0::increment_process_cpp" '{"arg1": 3}' -p# => CapsulePtr((value:Value(4), option: []))juiz process call "http://127.0.0.1:8000/process/inc1::increment_process_cpp" '{"arg1": 10}' -p# => CapsulePtr((value:Value(11), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/increment0::example_container_cpp_increment:counter0" '{"arg1": 5}' -p# => CapsulePtr((value:Value(5), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_cpp_get:counter0" '{}' -p# => CapsulePtr((value:Value(5), option: []))第 1 章の Process と第 2 章の Container が、1 つの juiz の中で一緒に動いています。
inc0 と inc1 は同じ型から作られた別々のインスタンスですが、Process は状態を持たないので、どちらを呼んでも同じ引数なら同じ結果になります。
Container に初期値を渡す
Section titled “Container に初期値を渡す”containers の項目には、type_name と name のほかに、Container を作る関数に渡す値も書けます。
カウンタを 3 から始めるように、counter0 の項目に 1 行足してみましょう。
containers: - type_name: example_container name: counter0 initial_value: 3 processes:example_container 関数の引数 initial_value に 3 が渡されます。
containers: - type_name: example_container_python name: counter0 initial_value: 3 processes:example_container_python 関数の引数 initial_value に 3 が渡されます。
containers: - type_name: example_container_cpp name: counter0 value: 3 processes:create_container が受け取る CapsuleMap から、args.get_int("value") で 3 を取り出します。
第 2 章で使った example_container.conf に value: 10 と書かれていたのも、この仕組みです。
juiz を Ctrl+C で止めて起動し直し、get を呼び出すと 3 が返ってきます。
juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_get:counter0" '{}' -p# => CapsulePtr((value:Value(3), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_python_get:counter0" '{}' -p# => CapsulePtr((value:Value(3), option: []))juiz container-process call "http://127.0.0.1:8000/container_process/get0::example_container_cpp_get:counter0" '{}' -p# => CapsulePtr((value:Value(3), option: []))コードを書き換えずに、設定ファイルだけで振る舞いの出発点を変えられました。
Process の引数に初期値を渡す: p_apply
Section titled “Process の引数に初期値を渡す: p_apply”Container だけでなく、Process の引数にも設定ファイルで値を与えられます。
processes の項目と、containers の中の processes の項目に p_apply を書き、引数の名前と値を並べます。
inc0 の arg1 を 10 に、increment0 の arg1 を 5 にしてみましょう。
processes: - type_name: increment_process name: inc0 p_apply: arg1: 10 - type_name: increment_process name: inc1containers: - type_name: example_container name: counter0 initial_value: 3 processes: - type_name: example_container_increment name: increment0 p_apply: arg1: 5 - type_name: example_container_get name: get0processes: - type_name: increment_process_python name: inc0 p_apply: arg1: 10 - type_name: increment_process_python name: inc1containers: - type_name: example_container_python name: counter0 initial_value: 3 processes: - type_name: example_container_python_increment name: increment0 p_apply: arg1: 5 - type_name: example_container_python_get name: get0processes: - type_name: increment_process_cpp name: inc0 p_apply: arg1: 10 - type_name: increment_process_cpp name: inc1containers: - type_name: example_container_cpp name: counter0 value: 3 processes: - type_name: example_container_cpp_increment name: increment0 p_apply: arg1: 5 - type_name: example_container_cpp_get name: get0p_apply の値は、インスタンスを作った直後にその引数へ入り、初期値になります。
この値が使われるのは、引数を渡さずに Process を**実行(execute)**したときです。次の章で使う Execution Context は、この方法で Process を動かします。
これまで使ってきた call は、呼び出すたびに引数を全部渡すので、p_apply の値は使われません。
juiz を起動し直し、HTTP API の execute で引数を渡さずに実行してみましょう。
curl -X PATCH "http://127.0.0.1:8000/api/process/execute?identifier=core://core/process/inc0::increment_process" \ -H "Content-Type: application/json" -d '{}'# => 11curl -X PATCH "http://127.0.0.1:8000/api/container_process/execute?identifier=core://core/container_process/increment0::example_container_increment:counter0" \ -H "Content-Type: application/json" -d '{}'# => 8curl -X PATCH "http://127.0.0.1:8000/api/process/execute?identifier=core://core/process/inc0::increment_process_python" \ -H "Content-Type: application/json" -d '{}'# => 11curl -X PATCH "http://127.0.0.1:8000/api/container_process/execute?identifier=core://core/container_process/increment0::example_container_python_increment:counter0" \ -H "Content-Type: application/json" -d '{}'# => 8curl -X PATCH "http://127.0.0.1:8000/api/process/execute?identifier=core://core/process/inc0::increment_process_cpp" \ -H "Content-Type: application/json" -d '{}'# => 11curl -X PATCH "http://127.0.0.1:8000/api/container_process/execute?identifier=core://core/container_process/increment0::example_container_cpp_increment:counter0" \ -H "Content-Type: application/json" -d '{}'# => 8inc0 は arg1 の 10 に 1 を足して 11 を返します。p_apply を書いていない inc1 を同じように実行すると、引数の既定値 0 が使われて 1 が返ります。
increment0 は、初期値 3 のカウンタに 5 を足して 8 を返します。
p_apply に Process が持っていない引数の名前を書くと、juiz は起動時にエラーで止まります。
たとえば arg1 を arg10 と書き間違えると、次のようなエラーになります。
Error:setup_objects() failed in setup in system.rs
Caused by: 0: setup_processes(...) in setup_objects() in setup_objects.rs 1: p_apply(arg_name='arg10', value=10) 2: Can not find Process::Inlet(arg10)書き間違いに、動かしてから気づくのではなく、起動したときに気づけます。
やってみよう
Section titled “やってみよう”processesとcontainersを消してpluginsだけ残した設定ファイルで起動し、juiz process listを見てみましょう。空のリスト[]が返ります。読み込んだだけでは、インスタンスは作られないことがわかります。containersにもう 1 つ Container(たとえばcounter1)と、それに結びつくincrement/getを書き足してみましょう。counter0とcounter1は別々の値を持ちます。ContainerProcess の ID には Container の名前が入るので、increment0のような名前は Container ごとに同じでもかまいません。- サンプル集の
decrement_processをpluginsとprocessesに書き足して、1 を引く Process も一緒に動かしてみましょう。
- 設定ファイルには、型を読み込む
pluginsと、そこからインスタンスを作るprocesses/containersを分けて書きます。 - 1 つの型から、名前の違うインスタンスをいくつも作れます。インスタンスの名前は ID の一部になります。
- Container の初期値のような、インスタンスごとの設定も設定ファイルで渡せます。
p_applyで Process の引数に初期値を与えられます。この値は、引数を渡さずに実行したとき(Execution Context から動かしたときなど)に使われます。- 設定ファイルの項目は、ガイドの「設定ファイル」 にまとめてあります。
次の章では、設定ファイルに Process どうしのつながりと、Process を動かすタイミングを書き足します。Process をつなぐ: connect と Execution Context に進みましょう。