hakoniwa-core-pro は、箱庭シミュレーションフレームワーク hakoniwa-core-cpp を拡張し、 イベント駆動型のシミュレーションを実現するためのライブラリ群です。C/C++/Python で 記述されたアセットを組み合わせることで、ロボット制御やセンサシミュレーションなどの 開発・検証を行うことができます。
hakoniwa-core-pro は、以下のコンポーネントから構成されています。
graph TD
subgraph User Application
A[Asset: C/C++/Python]
end
subgraph hakoniwa-core-pro
B(hako-conductor)
C(hako-cmd)
D[libhako.a]
end
subgraph hakoniwa-core-cpp
E[hako-master]
end
A -- interacts with --> D
B -- controls --> E
C -- inspects/controls --> E
D -- communicates with --> E
- hako-master:
hakoniwa-core-cppのコアコンポーネント。シミュレーション全体の時間管理やアセット間のデータ同期を担います。 - libhako.a:
hakoniwa-core-proのコアライブラリ。データ受信イベントやRPCサービスなどの機能を提供し、アセットからのAPI呼び出しを処理します。 - hako-conductor: シミュレーションの実行を制御するプログラム。
hako-masterと連携し、シミュレーションの開始、停止、ステップ実行などを管理します。 - Asset: ユーザが作成するシミュレーション参加要素。
libhako.aが提供するAPIを利用して、他のアセットとのデータ送受信や、RPCサービスの利用が可能です。 - hako-cmd: シミュレーションの状態を外部から確認したり、操作したりするためのコマンドラインツールです。
新しいC向けAPIは include/hakoniwa_asset_polling.h に集約しています。
戻り値は 0=成功 / 非0=失敗 です(is_* 系は 1=true / 0=false)。
#include "hakoniwa_asset_polling.h"
int main(void)
{
if (hakoniwa_asset_init() != 0) {
return 1;
}
if (hakoniwa_asset_register_polling("asset") != 0) {
return 1;
}
for (;;) {
int event = hakoniwa_asset_get_event("asset");
if (event < 0) {
break;
}
/* handle event */
}
return 0;
}旧 include/hako_capi.h は互換性のため残していますが、将来的に削除予定です。
移行時は以下の置き換えを行ってください。
hako_*->hakoniwa_*にリネーム- 戻り値を
boolからintに変更(0=成功 / 非0=失敗) is_*系の戻り値は1/0で判定
hakoniwa-core-pro では、PDU チャンネルのデータ受信を検知する
"データ受信イベント" 機能を提供しています。アセットは
hako_asset_register_data_recv_event() を用いることで特定の論理
チャンネルに対する受信イベントを登録でき、データが書き込まれた
タイミングでコールバックが呼び出されます。コールバックを指定し
ない場合はフラグ方式となり、hako_asset_check_data_recv_event() で
受信の有無を確認できます。詳細な使い方は
examples/pdu_communication 以下のサンプルを参考にしてください。
受信イベントの登録は維持したまま、通知だけを抑止/再開する
pending/resume を提供しています。pending 中は recv_flag を保持し、
resume 後の最初の通知で 1 回だけイベントが上がります。
- callback API(event_id ベース)
hako_asset_set_data_recv_event_pending(recv_event_id)hako_asset_set_data_recv_event_resume(recv_event_id)
- polling API(robo_name + lchannel ベース)
hakoniwa_asset_set_data_recv_event_pending(robo_name, lchannel)hakoniwa_asset_set_data_recv_event_resume(robo_name, lchannel)
- Python binding(event_id ベース)
set_data_recv_event_pending(event_id)set_data_recv_event_resume(event_id)
- センサデータの非同期受信: カメラやLiDARなどのセンサデータを、データが到着したタイミングで即座に処理したい場合に利用します。これにより、ポーリングによる無駄なCPU消費を抑えることができます。
- アセット間の状態同期: あるアセットの状態が変化したことを、他のアセットに即座に通知し、連携した動作を実現します。
- 外部システムとの連携: シミュレーション外部のシステムからデータを受信し、それをトリガとしてシミュレーション内のアセットを動作させることができます。
-
hako_asset_register_data_recv_event(robo_name, lchannel, callback)- 説明: 指定したPDUチャンネルにデータ受信時のコールバック関数を登録します。
- 引数:
robo_name: 監視対象ロボット名。lchannel: 監視対象の論理チャンネルID。callback: データ受信時に呼び出されるコールバック関数へのポインタ。
- 戻り値: 成功すれば
HAKO_SUCCESS、失敗すればエラーコードを返します。
-
hako_asset_check_data_recv_event(robo_name, lchannel)- 説明: (コールバックを登録しない場合) 指定したPDUチャンネルでデータ受信があったかどうかを確認します(フラグ方式)。
- 引数:
robo_name: 監視対象ロボット名。lchannel: 確認対象の論理チャンネルID。
- 戻り値: データ受信があれば
true、なければfalseを返します。
hako_asset_simulation_time()- 説明: シミュレーションのワールド時間(usec)を返します。
hako_asset_current_time()- 説明: アセットの内部時間(usec)を返します(
hako_asset_instance.current_usec)。
- 説明: アセットの内部時間(usec)を返します(
- Python binding
simulation_time()asset_current_time()
hakoniwa-core-pro では、PDU を介したリクエスト/レスポンス通信を実現する
"RPC サービス" 機能を提供しています。サービス定義を
hako_asset_service_initialize() で読み込み、サーバは
hako_asset_service_server_create() によりサービスを登録します。
クライアントは hako_asset_service_client_create() を呼び出して接続し、
hako_asset_service_client_get_request_buffer() でリクエストを準備して
hako_asset_service_client_call_request() で送信します。サーバ側では
hako_asset_service_server_poll() でリクエスト到着を検知し、
hako_asset_service_server_get_request() でデータを取得したのち、
hako_asset_service_server_get_response_buffer() と
hako_asset_service_server_put_response() を用いて応答を返します。
クライアントは hako_asset_service_client_poll() で応答を確認し、
hako_asset_service_client_get_response() から結果を取得できます。
詳細な使い方は examples/service 以下のサンプルを参照してください。
- ロボットへの動作指令: 制御ノードからロボットアームや移動ロボットに対して、「アームをこの角度に動かせ」「この座標に移動しろ」といった具体的な動作を指令し、その完了を待ち合わせるような場合に利用します。
- シミュレーション環境からの情報取得: アセットがシミュレーション環境(例:物理エンジン)に対して、「現在の自己位置を取得したい」「障害物との距離を知りたい」といった情報を要求し、結果を取得します。
- パラメータ設定: シミュレーション実行中に、外部ツールからアセットのパラメータ(例:ゲイン、閾値など)を動的に変更する場合に利用します。
-
hako_asset_service_client_create(service_name)- 説明: RPCサービスのクライアントを作成し、サーバに接続します。
- 引数:
service_name: 接続するサービス名。 - 戻り値: 成功すればクライアントハンドル、失敗すれば
NULLを返します。
-
hako_asset_service_client_call_request(client, request, size)- 説明: サーバにリクエストを送信します。
- 引数:
client: クライアントハンドル。request: 送信するリクエストデータへのポインタ。size: リクエストデータのサイズ。
- 戻り値: 成功すれば
HAKO_SUCCESS、失敗すればエラーコードを返します。
-
hako_asset_service_client_poll(client)- 説明: サーバからのレスポンスが到着したかを確認します。
- 引数:
client: クライアントハンドル。 - 戻り値: レスポンスがあれば
true、なければfalseを返します。
-
hako_asset_service_server_create(service_name, pdu_size)- 説明: RPCサービスを登録し、サーバとして待機します。
- 引数:
service_name: 公開するサービス名。pdu_size: このサービスで送受信するPDUの最大サイズ。
- 戻り値: 成功すればサーバハンドル、失敗すれば
NULLを返します。
-
hako_asset_service_server_poll(server)- 説明: クライアントからのリクエストが到着したかを確認します。
- 引数:
server: サーバハンドル。 - 戻り値: リクエストがあれば
true、なければfalseを返します。
-
hako_asset_service_server_put_response(server, response, size)- 説明: 処理結果をクライアントに返します。
- 引数:
server: サーバハンドル。response: 返信するレスポンスデータへのポインタ。size: レスポンスデータのサイズ。
- 戻り値: 成功すれば
HAKO_SUCCESS、失敗すればエラーコードを返します。
sources/: コアライブラリおよびアセット用モジュールcore/: 静的ライブラリlibhako.aのソースコード。データ受信イベントやRPCサービスなどのコア機能を提供します。assets/: アセットが利用する共有ライブラリlibasset.soのソースコード。conductor/: シミュレーション実行を制御するhako-conductorのソースコード。command/: コマンドラインツールhako-cmdのソースコード。
examples/: サンプルプログラムtests/: Python 版バインディングのテストコードtests/cpp/: GTest ベースの C++ テストコード(root プロジェクト)
sources/core ディレクトリには、libhako.a 静的ライブラリを構成するコアなソースコードが含まれています。このライブラリは、hakoniwa-core-cpp の基本機能の上に、より高度なイベント駆動の仕組みとサービス指向の通信機能を提供します。
hakoniwa-core-pro では、共有メモリ上のメタデータ更新時に複数の排他手段を使います。fleet のように複数プロセスが同時起動する構成では、lock の用途を混ぜるとデッドロックや buffer overflow の原因になります。
master_lockは既存のflock.binを使う coarse-grained なプロセス間排他です。init.flock系は、共有メモリ create/load/reset の初期化帯域を守るための局所 lock です。- lock order は
master_lock -> init.flockとします。 init.flockの内側からmaster_lockを取る実装は禁止します。
initialize_service()はmaster_lockで直列化します。- 対象: service channel の
create_lchannel()群
- 対象: service channel の
- callback 系 asset 初期化では、
asset_register_polling()の後に行うcreate_pdu_lchannel()ループだけをmaster_lockで直列化します。asset_register_polling()自体は lock 外で実行します。
pro_init.lock/pdu_init.lockは当面残します。- 対象:
on_pdu_data_create/load()、PDU create/load/reset()の初期化帯域 - ここは既存
master_lockに単純置換すると、shared-memory lock とのネストで自己デッドロックする可能性があります。
- 対象:
asset_register_polling()をmaster_lockの内側で呼ばないalloc_asset()が内部でmaster_lockを使うため、再入で詰まる可能性があります。
init.flockの内側からmaster_lockを取得しないPDU create/load/reset()やon_pdu_data_create/load()の lock 変更は、master_lock -> init.flockの順序を壊さないことを前提に行う
pro_init.lock/pdu_init.lockを既存 flock に統合する場合は、lock 順序の再設計が必要です。- 必要なら
master_lockの recursive 化も検討対象ですが、別 issue として扱います。
-
HakoProData:hakoniwa-core-cppのHakoMasterDataを拡張し、共有メモリを介してサービスやイベントに関する情報を管理する中心的なクラスです。IHakoMasterExtensionインターフェースを実装し、Hakoniwa のマスターライフサイクル(PDUの生成、読み込み、リセットなど)と連携して動作します。
-
サービス (RPC) フレームワーク:
- アセット間の非同期なリクエスト/レスポンス型通信を実現するためのフレームワークです。
- インターフェース:
IHakoServiceClient: サービスを利用するクライアントが実装すべき純粋仮想ベースクラスです。IHakoServiceServer: サービスを提供するサーバーが実装すべき純粋仮想ベースクラスです。
- プロトコル実装:
HakoServiceClientProtocol:IHakoServiceClientをラップし、リクエスト送信、レスポンス受信、タイムアウト処理、状態管理(IDLE,DOING,CANCELING)などのクライアント側プロトコルを実装します。HakoServiceServerProtocol:IHakoServiceServerをラップし、リクエスト受信、レスポンス返信、状態管理などのサーバー側プロトコルを実装します。
- 通信プロトコル:
hako_service_protocol.hppにて、操作コード (REQUEST,CANCEL)、ステータス (DOING,DONE)、リザルトコード (OK,ERROR) が定義されており、これらを用いて通信を制御します。
-
データ受信イベント:
HakoProDataは、特定のPDUチャネルへのデータ書き込みを検知し、登録されたコールバック関数を呼び出すイベント機能を提供します。- イベント情報は
HakoRecvEventTableTypeという共有メモリ上のテーブルで管理されます。
./build.bashPowerShell から以下を実行します。
.\win-build.ps1中間成果物はデフォルトで build-win に生成されます。
POSIX 版と同様に、以下の環境変数でビルドパラメータを調整できます。
ASSET_NUMSERVICE_MAXRECV_EVENT_MAXSERVICE_CLIENT_MAXCHANNEL_MAXENABLE_HAKO_TIME_MEASURE_FLAGBUILD_C_FLAGS
ビルドディレクトリを削除したい場合は以下を実行します。
.\win-build.ps1 -CleanGTest テストを有効にしてビルドし、ctest を実行します。
cmake -S . -B cmake-build -DHAKO_ENABLE_GTEST=ON
cmake --build cmake-build
ctest --test-dir cmake-build --verboseデフォルトでは cmake-build 配下にビルド成果物が生成されます。初回のみ
git submodule update --init --recursive を実行してサブモジュールを取得してください。
ビルドが完了した後、以下のスクリプトを実行することで、Hakoniwaのライブラリと実行ファイルをシステムにインストールできます。
./install.bashこのスクリプトは、/usr/local/bin や /usr/local/lib などの標準的なディレクトリにファイルをコピーします。管理者権限が必要なため、実行中に sudo のパスワードを求められることがあります。
なお、Pythonのサンプルコードを実行する場合は、以下のコマンドを実行して、Pythonライブラリをインストールしてください。
pip install hakoniwa-pduWindows では PowerShell から以下を実行します。
.\win-build-install.ps1 -InstallPrefix .\installこれにより、指定した prefix 配下に以下のような構成でインストールされます。
include/hakoniwalibbinshare/hakoniwa/offsetetc/hakoniwalib/pkgconfiglib/cmake/hakoniwa-core
OutputDir も互換引数として利用できます。
.\win-build-install.ps1 -OutputDir .\installWindows 版も POSIX 版と同様に、ASSET_NUM などの環境変数を利用できます。
インストールされた Hakoniwa をシステムから削除するには、以下のスクリプトを実行します。
./uninstall.bashこのスクリプトは、install.bash によって作成されたディレクトリとファイルをすべて削除します。安全のため、実行前に削除対象のディレクトリ一覧を表示し、確認を求めます。
以下のスクリプトを実行すると、Hakoniwaが正しくインストールされているかを確認できます。
./check-install.bashこのツールは、必要なファイルやディレクトリがすべて揃っているかをチェックし、結果を報告します。不足している項目がある場合は、その一覧が表示されます。
Debianパッケージをビルドするには、ビルド依存関係を満たすパッケージが必要です。
debian/controlのBuild-Dependsに記載されているパッケージを、以下のコマンドなどを用いてインストールしてください。
sudo apt-get update
sudo apt-get install build-essential devscripts debhelper-compat cmake dh-exec help2man dh-sequence-python3 python3-devリポジトリのルートディレクトリで以下のコマンドを実行します。
debuild -us -uc -bビルドが成功すると、親ディレクトリ(一つ上の階層)に.debファイル群が生成されます。
ビルド後、サンプルを以下のように実行できます。
./run-example.bash ./cmake-build/examples/hello_world/hello_world詳細な手順は examples/hello_world/README.md など各サンプルの README を参照してください。
install 済みの成果物は、CMake package として利用できます。
find_package(hakoniwa-core CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE hakoniwa-core::hako hakoniwa-core::assets)pkg-config を使う場合は hakoniwa-core.pc もインストールされます。
| 分類 | 名前 | 説明 | 利用者 |
|---|---|---|---|
| ライブラリ | assets | 箱庭アセット用ライブラリ(callback) | C++ 開発者 |
| ライブラリ | conductor | 箱庭コンダクタ用ライブラリ | C++ 開発者 |
| ライブラリ | shakoc | 箱庭アセット用ライブラリ(polling) | Unity 開発者 |
| ライブラリ | hakopy | Python バインディング | Python 開発者 |
| コマンド | hako-cmd | 箱庭コマンドラインツール | C/C++/Python 開発者 |
ファイル名は、OSによって異なります。
- Windows: <ライブラリ名>.dll, <コマンド名>.exe
- Linux: <ライブラリ名>.so, <コマンド名>
- MacOs: <ライブラリ名>.dylib, <コマンド名>
| 分類 | リポジトリ内 | インストール先 | 説明 | 利用者 |
|---|---|---|---|---|
| ヘッダファイル | include | /usr/include/hakoniwa | 箱庭APIのヘッダファイル | C/C++ 開発者 |
| ヘッダファイル | hakoniwa-pdu-registry/pdu/types | /usr/include/hakoniwa/pdu | 箱庭PDUバイナリ変換APIのヘッダファイル | C/C++ 開発者 |
| 実行時参照ファイル | hakoniwa-pdu-registry/pdu/offset | /usr/share/hakoniwa/offset | 箱庭PDUバイナリ変換用オフセットファイル | C/C++ 開発者 |
| MMAPファイル | なし | /var/lib/hakoniwa/mmap | MMAPファイルを配置するディレクトリ | 箱庭ライブラリ利用者 |
| 設定ファイル | hakoniwa-core-cpp/cpp_core_config.json | /etc/hakoniwa/cpp_core_config.json | 箱庭コアの設定ファイル | 箱庭ライブラリ利用者 |
| ライブラリ | cmake-build/sources/assets/callback | /usr/local/lib/hakoniwa/ | 箱庭アセット用ライブラリ(callback) | C++ 開発者 |
| ライブラリ | cmake-build/sources/conductor | /usr/local/lib/hakoniwa/ | 箱庭コンダクタ用ライブラリ | C++ 開発者 |
| ライブラリ | cmake-build/sources/assets/bindings/python | /usr/local/lib/hakoniwa/ | Python バインディング | Python 開発者 |
| コマンド | cmake-build/sources/command/hako-cmd | /usr/local/bin/ | 箱庭コマンドラインツール | C/C++/Python 開発者 |
このプロジェクトは MIT License の下で公開されています。詳しくは LICENSE ファイルを参照してください。
[Upstreamバージョン] - [Debianリビジョン] ~ [PPAビルド番号]
例: 1.0.0-1~ppa1
- Upstreamバージョン(1.0.0) → ソフトそのものの機能や仕様が変わった時に上げる(コード変更)
- Debianリビジョン(-1) → パッケージの作り方や構成を変えた時に上げる(配置・依存・ビルド方法など)
- PPAビルド番号(~ppa1)
→ PPA内での世代番号。テスト配布や小修正時に上げる
~があることで、公式版が出ると自動でそちらに置き換わる
-
インストール先の変更
/usr/local/lib→/usr/lib/<multiarch>- 設定ファイルのパス変更
-
依存関係の追加・削除
Depends: libfoo1→Depends: libfoo2- 不要な依存を削除
-
パッケージの分割・統合
-devとランタイムパッケージの分離
-
ビルドオプションの変更
- 最適化レベル変更、特定アーキ用最適化
-
パッチ適用
- バグ修正、セキュリティパッチ
-
メタデータ修正
- 説明文、Maintainer、Homepageの更新
-
初期配布(PPAのみ)
1.0.0-0~ppa1から開始(公式化前はDebianリビジョン0)
-
PPAでの小修正
1.0.0-0~ppa2→1.0.0-0~ppa3
-
公式リリース時
1.0.0-1に昇格(PPAの数字は消える)
-
公式版のDebianリビジョン更新
- パッケージ構成を修正したら
1.0.0-2
- パッケージ構成を修正したら
-
パッケージ名
hakoniwa-core(統合) orhakoniwa-core+hakoniwa-core-dev(分割)
-
インストールするもの
.so(SONAMEリンク付き)- ヘッダ
- 設定ファイル
- コマンド
- 必要なら
hakopy
-
配置場所
/usr/lib/<multiarch>(ライブラリ)/usr/include/hakoniwa(ヘッダ)/etc/hakoniwa(設定)/usr/bin(コマンド)
-
初期バージョン
- 公式化前:
X.Y.Z-0~ppa1 - 公式化後:
X.Y.Z-1
- 公式化前:
💡 このルールを最初に決めておくと、apt公開・PPA配布・ローカルテストの全部に対応できる。