Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

外部公開する箱庭APIのあるべき姿をもう一度再検討する #25

Closed
tmori opened this issue Dec 30, 2023 · 20 comments
Closed

Comments

@tmori
Copy link
Contributor

tmori commented Dec 30, 2023

現状の箱庭APIは低レベルなものが多く、ユーザ視点でもう少し利用しやすい形にしたい。

その上で、箱庭APIとして採用する言語を再定義したい。
以下、候補案。

  1. C/C++(言語バインディング用)
  2. Rust
  3. C#
  4. Python
  5. Elixir
  6. Ruby

ちなみに、最近のお気に入りのAPIセットはこちら。

https://github.com/toppers/hakoniwa-core-cpp-client/blob/main/src/hakoc/src/hako_asset_runner.h

Python向けにはこちらも整備されていてるもの。

https://github.com/toppers/hakoniwa-python-simasset-plugin/tree/main

@s-hosoai
Copy link
Contributor

s-hosoai commented Dec 30, 2023

他言語バインディングが無いと残念なので,やっぱりC/C++ or Rustかなぁと思います.
その他の言語はその上のラッパーとして作る感じですね.C/C++は定番なもののビルド周りで若干つらい,Rustはいい感じのバインディングの仕組みを持っているそうですが,言語が厳しい・・,と言ったところでしょうか.
Rustにしたい気持ちはあるものの,御しきれる気があんまりしないんですよね.
あとは配布方法ですが,Creteを掲載できるってのも強いです.

@tmori
Copy link
Contributor Author

tmori commented Dec 30, 2023

他言語バインディングが無いと残念なので,やっぱりC/C++ or Rustかなぁと思います. その他の言語はその上のラッパーとして作る感じですね.C/C++は定番なもののビルド周りで若干つらい,Rustはいい感じのバインディングの仕組みを持っているそうですが,言語が厳しい・・,と言ったところでしょうか. Rustにしたい気持ちはあるものの,御しきれる気があんまりしないんですよね. あとは配布方法ですが,Creteを掲載できるってのも強いです.

コメントありがとうございます。そうですね。C/C++とRustが最有力ですね。
言語バインディングとしては、ひとまずC/C++で作業を進めるのが近道なので、自分はその方向で作業をしようかと思いました。

@tmori
Copy link
Contributor Author

tmori commented Dec 30, 2023

箱庭APIの検討内容

目的

ここでは、以下を検討します。

  1. 前提事項
  2. 箱庭アセットAPIの機能分類
  3. 各APIの機能概要
  4. エラー番号

前提事項

  • マルチスレッド対応すると機能が複雑になるので対応しない

箱庭アセットAPIの機能分類

箱庭アセットが箱庭を利用する上で必要な機能分類は以下のものがあります。

  1. ライフサイクル管理
  2. シミュレーション時間
  3. PDUデータアクセス

各APIの機能概要

ライフサイクル管理

シミュレーション自体は、動き始めたら、シミュレーション全体を停止させるまでアセットの増減はしない想定なので、これくらいしか考えていません。

  1. 箱庭アセットの初期化
  2. 箱庭アセットの登録
  3. シミュレーションイベント発生機能(開始、停止、リセット)
  4. シミュレーションイベント発生を検出する機能

シミュレーション時間

シミュレーション時間に関して、箱庭アセットとして必要となるAPIとしては以下があります。

  1. シミュレーション時間を進める
  2. シミュレーション時間を参照する

これに対して、以下のような要件もあると思われます。

  1. スリープ機能

期待したシミュレーション時間まで呼出コンテキストブロックする機能ですが、1のAPIがあれば箱庭アセット側で作成するという案もあります。箱庭APIとして用意すべきかどうかは要検討です。

PDUデータアクセス

PDUデータアクセスについては、以下の2つがあります。

  1. PDUデータ書き込み
  2. PDUデータ読み込み

最近、気づいたこととして、書き込みしたシミュレーション時間を取得できる機能が必要と思い始めました。
なので、以下を追加したい。

  1. PDUデータ生成時間取得API

この機能自体は、PDUデータ読み込みAPIとセットで取得できるものでなければなりません。
なお、この機能実現するには、PDUデータ構造の改修が必要なのでその検討も合わせて行う必要がある。

さらに、PDUデータアクセスについて、データロストを考慮して、過去データを取得できる機能が必要かもしれないと思ってはいますが、必要性がまだ把握しきれていません。

データロストが怖い場合は、箱庭アセット側でデータロストが発生しない周期で定期的にデータ受信をするプログラムを作れば良いためです。

また、そのプログラムは現実のアプリ側にも必要と思われるので、シミュレータとして用意すべきか?と悩みます。

エラー番号

エラー番号は、errno.h とマッピングさせたい。

@tmori
Copy link
Contributor Author

tmori commented Dec 30, 2023

APIシグネチャ

ここでは、かっちょいーAPI名を検討します。

名前空間

hako::assets

ライフサイクル管理

機能名 API名
箱庭アセットの初期化 init()
箱庭アセットの登録 register()
シミュレーションイベント発生機能 event_{start, stop, reset}
シミュレーションイベント発生を検出する機能 API用意せず各APIの戻り値で検出できるようにする

シミュレーション時間

機能名 API名
シミュレーション時間を進める step()
シミュレーション時間を参照する get_world_time_usec()
スリープ機能 usleep()

PDUデータアクセス

機能名 API名
PDUデータ書き込み pdu_read()
PDUデータ読み込み pdu_write()

@tmori
Copy link
Contributor Author

tmori commented Dec 31, 2023

PDUチャネルの配信と購読について(メモ)

PDUデータは、ROSのトピックと同様に配信者と購読者が存在します。
配信者は、PDUチャネルを作成する必要があります。
購読者は、購読したいPDUのチャネル番号を指定することでデータ読み込みできます。

これら一連の初期設定は、APIで公開するよりは、初期化関数の引数として購読・配信のPDUデータをJSONで渡すことで、初期化関数が自動設定できるようにします。

そう考えると、箱庭アセット登録も初期化関数に含めてしまえば良いような気がしてきた。

@tmori
Copy link
Contributor Author

tmori commented Dec 31, 2023

PDUデータ構造見直し

PDUのメタデータは以下で管理している。

https://github.com/toppers/hakoniwa-core-cpp/blob/d5163a63fad2393dd63ad09a85368b48de275adc/src/hako/data/hako_base_data.hpp#L86C12-L86C12

ここに以下のデータを追加する。

  • 更新時間(uint64)
  • 更新回数(uint64)

UDP/MQTT通信データはいかになりそう。

オフセット 項目
0 PDUデータ
PDUデータサイズ メタデータ

@mitsut
Copy link
Member

mitsut commented Jan 3, 2024

用語の整理(確認) -PDU

ドキュメント化するにあたって、用語の整理をしていきたいです。PDUに関しては以下の言葉がでています。

  • PDUデータ
    • アセットと箱庭コアで受け渡しを行うデータユニット
    • char *pdu_data などで表記(8bitの配列)
  • PDUパケット
    • 間違ってました。PDUを伝送する場合のプロトコルによりますね。
    • 例:UDPパケット、MQTTパケット、ROS topicなど
    • これらを総称してPDUパケットと呼んでもいいかもですが、今のところ不要
  • PDUチャネル
    • PDUデータを管理するためのチャネル

@tmori
Copy link
Contributor Author

tmori commented Jan 3, 2024

PDUデータは、おそらく共有メモリないのデータだと思います。
PDUパケットは、それをUDPなどに乗せたもの。
PDUチャネルは、PDUを共有メモリ内で管理するためのIDですね。

@tmori
Copy link
Contributor Author

tmori commented Jan 4, 2024

こちらでAPI仕様を書き始めました。随時コメント受け付けます!

https://github.com/toppers/hakoniwa-core-cpp-client/tree/rapi

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

これの出口、UnrealEngineにすると面白いかもしれない。

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

@s-hosoai さんからのコメント

以下疑問点です.
[UC-HAKO-ASSET-1]
・使用例の中のmy_asset_callbackとhako_asset_registerの引数の型が異なってませんか?
[UC-HAKO-ASSET-3]
・アセットAPIとPDU周りのAPIはレイヤが異なるように思います.アセットを管理する機構とアセットの中で利用するAPIは切り離した方が分かりやすいように思います.
(コールバックの中で使えるAPIとそうでないものが,そのまま切り分けポイントになる?)
・各コールバック関数のvoid* contextには何が入ってきますか?またstruct内では単にvoidになっているように思います.
・各コールバックで何をしないといけないか,特に初期化処理に必須の項目があれば返り値として何かしら持たせて明示してもいいかもです.
[UC-HAKO-ASSET-7]
・sleep_time_usleepの利用者は誰でしょう?アセット内では利用しなさそうですし,シミュレーション自体の開発者向けでしょうか.
おそらく以下で区分けできると思います.
シミュレータ開発者向け
・hako_asset_execute
・hako_asset_usleep
アセット作成者向け
・hako_asset_register
・hako_asset_callbacks_tの各コールバック
・hako_asset_pdu_read
・hako_asset_pdu_write
・hako_asset_simulation_time

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

・使用例の中のmy_asset_callbackとhako_asset_registerの引数の型が異なってませんか?

失礼しました。修正しました。

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

・各コールバック関数のvoid* contextには何が入ってきますか?またstruct内では単にvoidになっているように思います.

現時点では、contextのような引数の想定は入れておりません。
理由としては、

  1. シングルスレッド前提であること
  2. コンテキスト管理はアセット側でやってもらう想定であること
  3. アセットの処理としては、PDUの読み書きと制御処理くらいしかないと思われること

contextとして何か必要そうなものあれば、教えていただけますか。

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

・各コールバックで何をしないといけないか,

各コールバックで何をしないといけないかという点は、説明として追記するようにしたいと思います。

特に初期化処理に必須の項目があれば返り値として何かしら持たせて明示してもいいかもです.

ごめんなさい、こちらのイメージができませんでした。
コールバックの返り値を追加するという意味ですかね?
現状は、箱庭アセットシミュレーション側からコールかけるだけというシンプルな想定でしたが、戻り値で何かエラーが返った場合、シミュレーション側として何をする感じでしょうか。

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

・sleep_time_usleepの利用者は誰でしょう?アセット内では利用しなさそうですし,シミュレーション自体の開発者向けでしょうか.

こちらは、アプリケーション側ですね。
箱庭アセットコールバック内で、自分でスリープしたいケースがあることを想定して用意しました。

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

・アセットAPIとPDU周りのAPIはレイヤが異なるように思います.アセットを管理する機構とアセットの中で利用するAPIは切り離した方が分かりやすいように思います.

おっしゃる通りですね。ちょっと説明の仕方を考えます。

@tmori
Copy link
Contributor Author

tmori commented Jan 9, 2024

・アセットAPIとPDU周りのAPIはレイヤが異なるように思います.アセットを管理する機構とアセットの中で利用するAPIは切り離した方が分かりやすいように思います.
(コールバックの中で使えるAPIとそうでないものが,そのまま切り分けポイントになる?)

APIの説明の前に、ユースケースのカテゴリ説明を追加しました。これに合わせて、ユースケースのID体系も変えてみました。

全体的に直しましたので、再度、ご確認をお願いできますとありがたいです。

https://github.com/toppers/hakoniwa-core-cpp-client/blob/rapi/README.md

@s-hosoai
Copy link
Contributor

contextとして何か必要そうなものあれば、教えていただけますか。
contextというと一切合切を含んだ何かというイメージになっちゃいますが,コールバックで受け取りたい(イミュータブルな)何かしらの情報のイメージです.
私としても無くてもいいと思ってますが,以下,こんな候補があるかもねってレベルです.

  • initialize : 次項と関連するかもですが,アセット初期化時に参照したい情報を
  • step : 箱庭のstepの刻みがどうなってたかうろ覚えですが,よくあるシミュレータだと前回からのdelta step値とかが渡ってきたりします.
  • reset : full reset, soft resetなど.今後分けたくなったら・・?分けるなら別コールバックにした方がいい気もしますが.

特に初期化処理に必須の項目があれば返り値として何かしら持たせて明示してもいいかもです.
初期化時にアセットからCoreに伝えたい項目があるかと思ってたのですが,凡その情報はregisterの段階で終わってそうですね.

箱庭アセットコールバック内で、自分でスリープしたいケース
スリープするのはhako_asset_usleepを呼び出したアセットだけでしょうか? このAPIだけ主体が必要となり,アセットのハンドルなどを指定しないといけないような気がします.sleep機能は欲しいですが実現するのが結構複雑になりませんかね・・?

hako_asset_executeの主体も分からなくなってきました.コア機能からアセット or アセットからコア機能への実行依頼のどちらでしょうか?いずれも,どのアセットへの依頼か,どのアセットからの依頼なのか把握する必要があると思うのですが,どのように管理しているのでしょうか?
そもそも私自身がアセットとコア機能(というかメインループ?)の区分けが把握できてない気がしてきました・・.

@tmori
Copy link
Contributor Author

tmori commented Jan 10, 2024

回答ありがとうございます!

contextの扱いについて

現状、必要性はなさそうですが、今後の拡張性を考慮して、void*のメンバを一個入れておきますか。
(後で引数追加するのは面倒ですしね)

コールバックの返り値について

こちらは、register段階で終わるような気がしていて、戻り値は無しでも良いような気がしております。
戻り値がある場合、シミュレーション実行体がどのような動きをすべきかの具体例がないと、コーディングできないなーっと悩んでおります。。

なので、戻り値は返せるように設計だけしておいて、現状はシミュレータ側は無視する作りにしますかね。

sleepの扱いについて

おっしゃるとおり、結構、これの実装は難しいのです...。
ただ、実機で動いているプログラムをそのまま箱庭に移植して持ってくるようなケースを考えると、
sleep APIはないと破綻するケースがあるような気がしております。。

周期タスクで実装されているケースなら問題ないんですけどねぇ。

@tmori
Copy link
Contributor Author

tmori commented Jan 10, 2024

hako_asset_executeの主体も分からなくなってきました.コア機能からアセット or アセットからコア機能への実行依頼のどちらでしょうか?いずれも,どのアセットへの依頼か,どのアセットからの依頼なのか把握する必要があると思うのですが,どのように管理しているのでしょうか?
そもそも私自身がアセットとコア機能(というかメインループ?)の区分けが把握できてない気がしてきました・・.

ここは、実際にサンプルコードをお見せした方が早いと思いますね。

イメージとしては、こんな感じですね。

hako_asset_register(&callbackなどなど)

while (true) {
   hako_asset_execute(1); //1step時間を進める
}

@tmori tmori closed this as completed Jan 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants