diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..881bd3e --- /dev/null +++ b/404.html @@ -0,0 +1,1557 @@ + + + +
+ + + + + + + + + + + + + + +graph TD
+ ENTRY_POINT(ENTRY_POINT) -.-> FORCED_PASS_C{味方セットプレー?}
+subgraph セットプレー
+ FORCED_PASS_C -- YES --> FORCED_PASS
+end
+
+%%subgraph 敵ボール対処
+%% STEAL_BALL_C
+%%end
+
+subgraph シュートチャンスは逃さない
+
+end
+
+subgraph 敵ボール対処
+ FORCED_PASS_C -- NO --> CUT_THEIR_PASS_C{動いている敵ボール?}
+ CUT_THEIR_PASS_C -- NO --> STEAL_BALL_C{止まっている敵ボール & ボールに敵が近い?}
+ CUT_THEIR_PASS_C -- YES --> CUT_THEIR_PASS
+end
+
+subgraph シュートチャンスは逃さない
+ STEAL_BALL_C -- NO --> REDIRECT_GOAL_KICK_C{ボールが遠い&ゴールが見えている}
+ REDIRECT_GOAL_KICK_C -- NO --> GOAL_KICK_C{ボールが近い&ゴールが見えている}
+ REDIRECT_GOAL_KICK_C -- YES --> REDIRECT_GOAL_KICK
+ GOAL_KICK_C -- YES --> GOAL_KICK
+end
+
+subgraph 敵ボール対処
+ STEAL_BALL_C -- YES --> STEAL_BALL
+end
+
+subgraph 状況改善
+ GOAL_KICK_C -- NO --> CLEARING_KICK_C{やばい状況?(未実装)}
+ CLEARING_KICK_C -- NO --> STANDARD_PASS_C{パスできそうな相手がいる?}
+ CLEARING_KICK_C -- YES --> CLEARING_KICK
+ STANDARD_PASS_C -- YES --> STANDARD_PASS
+ STANDARD_PASS_C -- NO --> LOW_CHANCE_GOAL_KICK_C{低確率でもシュートできそう(相手コート限定)?}
+ LOW_CHANCE_GOAL_KICK_C -- NO --> MOVE_BALL_TO_OPPONENT_HALF_C{自コートでボールを持っている?}
+ LOW_CHANCE_GOAL_KICK_C -- YES --> LOW_CHANCE_GOAL_KICK
+ MOVE_BALL_TO_OPPONENT_HALF_C -- YES --> MOVE_BALL_TO_OPPONENT_HALF
+ MOVE_BALL_TO_OPPONENT_HALF_C -- NO --> RECEIVE_BALL
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ https://github.com/ibis-ssl/crane/pull/303
+ボールへの外力発生イベントを検出する。
+イベントは以下の評価値が閾値を超えたときに発生するものとする。
これによって、ボールの速度ベクトルに変化があった場合にイベントが発生する。
+前フレームの速度で割っているのは、ボールの速度が速い場合には些細な地面の凹凸でボールの動きが変わりやすかったり、単純にVisionのブレが大きいのを吸収することを防ぐ正規化である。
+また、分母に0.1を足しているのは、ボール速度が0に近づくにつれて評価値が不当に大きくなるのを防ぐためである。
この評価値を用いて、ロボットによるボールへのキックや衝突、またボールの壁への衝突などのイベントを検出する。
+ボールの状態を以下の3つに分類する。
+この状態を計算するためにまず、「敵所持フラグ」「味方所持フラグ」の2つのフラグを計算する
+以下の条件を満たすとき、「敵所持フラグ」は真となる。
+3は単にロボットがボールにぶつかっただけで所有権が移るのを防ぐための条件である。
+ロボット中心から見たボールの方向と、ロボットのキッカーの方向の差が一定角度以下のとき、ボールはキッカーに接触したと判定する。
+プルリクエストでは0.4rad、つまりキッカーの左右に23度ずつの範囲を接触範囲としている。
「味方所持フラグ」は真となる条件は2通りある。
+敵所持フラグと同様の条件を味方ロボットが満たしたとき、「味方所持フラグ」は真となる。
+以下の条件を満たすとき、「味方所持フラグ」は真となる。
+遷移テーブルで「-」は遷移無しを表す。
++ | 敵所持フラグ(真) | +敵所持フラグ(偽) | +
---|---|---|
味方所持フラグ(真) | +- | +味方所持 | +
味方所持フラグ(偽) | +敵所持 | +- | +
+ | 敵所持フラグ(真) | +敵所持フラグ(偽) | +
---|---|---|
味方所持フラグ(真) | +どちらでもない | +味方所持 | +
味方所持フラグ(偽) | +- | +どちらでもない | +
+ | 敵所持フラグ(真) | +敵所持フラグ(偽) | +
---|---|---|
味方所持フラグ(真) | +どちらでもない | +- | +
味方所持フラグ(偽) | +敵所持 | +どちらでもない | +
graph TD
+ LP[Local Planner]
+ PS[Play Switcher]
+ GA[Game Analyzer]
+
+ subgraph interface
+ VC[Vision Component]
+ GrC[GrSim Component]
+ GCC[Game Controller Component]
+ Receiver[Robot Receiver]
+ end
+
+ SC[Session Controller]
+ SS[Sim Sender]
+
+ VT[Vision Tracker]
+ WP[World Model Publisher]
+
+ subgraph software
+ GrSim[GrSim]
+ GC[Game Controller]
+ end
+
+ WP -- /world_model --> SC
+ WP -- /world_model --> GA
+ GA -- /game_analysis --> SC
+
+
+ GrC -. UDP .-> GrSim
+
+ GrSim -. UDP .-> VC
+ VC -- /geometry --> WP
+
+ GrSim -. UDP .-> VC
+
+
+ VC -- /detection --> VT
+ VT -- /detection_tracked --> WP
+
+ GC -. UDP .-> GCC
+ GCC -- /referee --> PS
+ PS -- /play_situation --> SC
+ SC -- /control_targets --> LP
+ LP -- /robot_commands --> SS
+ SS -- /commands --> GrC
+
+ Receiver -- /feedback --> WP
+graph TD
+
+ subgraph robot
+ Robots[Robots]
+ end
+
+ subgraph AI Computer
+ LP[Local Planner]
+ PS[Play Switcher]
+
+ VC[Vision Component]
+ GCC[Game Controller Component]
+ Receiver[Robot Receiver]
+
+ SC[Session Controller]
+ SS[Real Sender]
+
+ VT[Vision Tracker]
+ WP[World Model Publisher]
+ end
+
+ subgraph software
+ Vision[SSL Vision]
+ GC[Game Controller]
+ end
+
+ WP -- /world_model --> SC
+ WP -- /world_model --> PS
+ WP -- /world_model --> LP
+
+
+
+ Robots -. UDP .-> Receiver
+ VC -- /geometry --> WP
+
+ Vision -. UDP .-> VC
+
+
+ VC -- /detection --> VT
+ VT -- /detection_tracked --> WP
+
+ GC -. UDP .-> GCC
+ GCC -- /referee --> PS
+ PS -- /play_situation --> SC
+ PS -- /play_situation --> WP
+ SC -- /control_targets --> LP
+ LP -- /robot_commands --> SS
+ SS -. UDP .-> Robots
+
+ Receiver -- /feedback --> WP
+graph TD
+ subgraph interface
+ VisionNode[Vision Component]
+ Sender[Real Sender]
+ Receiver[Robot Receiver]
+ end
+
+ VT[Vision Tracker]
+ WP[World Model Publisher]
+ Main[Simple AI]
+ LP[Local Planner]
+
+ subgraph RealWorld
+ Robot[Actual Robot CM4]
+ SSLVision[SSL Vision]
+ end
+
+ SSLVision -. UDP .-> VisionNode
+ VisionNode -- /detection --> VT
+ VT -- /detection_tracked --> WP
+ VisionNode -- /geometry --> WP
+
+ WP -- /world_model --> Main
+ Main -- /control_targets --> LP
+ LP -- /robot_commands --> Sender
+
+ Sender -. UDP .-> Robot
+
+ Robot -. UDP .-> Receiver
+ Receiver -- /feedback --> WP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ docker compose v2のインストール
+sudo mkdir -p /usr/local/lib/docker/cli-plugins
+sudo curl -SL https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
+sudo chmod a+x /usr/local/lib/docker/cli-plugins/docker-compose
+
※docker-compose v1系はv1.2.5以降だとエラーが出て起動できないはず
+起動
+https://github.com/ibis-ssl/grSim
+オリジナルから以下の変更を加えた
+AI components for RoboCup Small Size League.
+ + + + + + + + + + + + + + + + + + + + +色と位置の関係についてはルールには明記されていない.
+しかし,grSimでは,xがマイナスの方が青,プラスの方が黄色となっている.
「味方の〇〇 => 座標」を解決したい
+ある情報は以下の通り
+やるべきこと:WorldModel
クラスで解決済みの情報を提供するAPIを追加する
キーパーしか入ってはいけないあのエリア,GoalAreaと表記してしまっていた部分があったが実はDefenseAreaであった.
+https://robocup-ssl.github.io/ssl-rules/sslrules.html#_defense_area
+修正した
+前回調べたら,メインループが300Hzもの超高速で回っていることが判明したので修正していく +原因はおそらく,WorldModelの更新がVisionの一部でも更新されたらPublishされており, +それをトリガーにしてメインループが全て駆動していることが原因だと思われる
+⇒ WorldModelの更新周期を60Hzに固定しよう!
+⇒ そもそもWorldModelの更新周期は100Hzだった まぁ早すぎるので60Hzにした
+local_plannerは/control_targets
駆動.
+それを出しているプランナー群はworld_model
駆動...
あれ,world_model駆動だおかしいな...
+もしかして,前回測定時にはworld_model_publisher
が3つ同時起動していた可能性がある?!?!
play_switcher.launch
へのGUI追加ログ
+[crane_play_switcher]: last 4, THEIR_KICKOFF_PREPARATION : 2.025060
+[crane_play_switcher]: last 4, THEIR_KICKOFF_PREPARATION : 2.049855
+[crane_play_switcher]: コマンド変化!
+[crane_play_switcher]: THEIR_KICKOFF_START
+[crane_play_switcher]: inplay cmd : 22
+[crane_play_switcher]: CMD : 2
+[crane_play_switcher]: last 2, THEIR_KICKOFF_START : 0.000022
+[crane_play_switcher]: コマンド変化!
+[crane_play_switcher]:
+[crane_play_switcher]: inplay cmd : 0
+[crane_play_switcher]: CMD : 2
+[crane_play_switcher]: last 2, : 0.000019
+[crane_play_switcher]: last 2, : 0.024619
+
COMMAND_PREPARE_KICKOFF_YELLOW
が来て2秒後に NORMAL_START
が来ている
+その後,
参考情報
+RAWコマンドの移り変わりとその解釈
+⇒色々あって結局デバッグしやすいLOGを整えたら直った気がする +こんな感じ
+[crane_play_switcher]: ---
+[crane_play_switcher]: RAW_CMD : COMMAND_STOP
+[crane_play_switcher]: INPLAY_CMD : STOP
+[crane_play_switcher]: REASON : RAWコマンド変化:コマンド転送
+[crane_play_switcher]: PREV_CMD_TIME: 12.505770
+[crane_play_switcher]: ---
+[crane_play_switcher]: RAW_CMD : COMMAND_PREPARE_KICKOFF_YELLOW
+[crane_play_switcher]: INPLAY_CMD : THEIR_KICKOFF_PREPARATION
+[crane_play_switcher]: REASON : RAWコマンド変化:コマンド転送
+[crane_play_switcher]: PREV_CMD_TIME: 15.174960
+[crane_play_switcher]: ---
+[crane_play_switcher]: RAW_CMD : COMMAND_NORMAL_START
+[crane_play_switcher]: INPLAY_CMD :
+[crane_play_switcher]: REASON : RAWコマンド変化&NORMAL_START:KICKOFF/PENALTYはPREPARATIONからSTARTに移行
+[crane_play_switcher]: PREV_CMD_TIME: 19.425025
+[crane_play_switcher]: ---
+[crane_play_switcher]: RAW_CMD : COMMAND_NORMAL_START
+[crane_play_switcher]: INPLAY_CMD : INPLAY
+[crane_play_switcher]: REASON : INPLAY判定:キックオフから10秒経過
+[crane_play_switcher]: PREV_CMD_TIME: 10.024822
+
PlaySituation.msg
にcommand_updated
を追加した.
INPLAYのコマンド更新時にcommand_updated
をtrue
にする処理を実装した
PlaySituationを受け取って行う処理の実装
+session_controller
の実装session_controller
で使う上で足りないプランナのリストアップPlaySituationを受け取って行う処理の実装
+session_controller
の実装session_controller
で使う上で足りないプランナのリストアップsession_controller
での実装箇所確認¶topic : /play_situation
+from : play_switcher
+msg type : crane_msgs/PlaySituation.msg
msg content :
+uint32 stage
+uint32 command
+string referee_text
+
+crane_msgs/InPlaySituation inplay_situation
+ bool ball_possession_ours
+ bool ball_possession_theirs
+ uint8 nearest_to_ball_robot_id_ours
+ uint8 nearest_to_ball_robot_id_theirs
+
+geometry_msgs/Point placement_position
+
+crane_msgs/WorldModel world_model
+
+bool command_updated
+
world_modelの受取は必要なものが各自行う
+crane_msgs/PlaySituation.msg
からボール保持判定の削除game analyzer
から出力するためのボール保持判定のメッセージ検討crane_msgs/PlaySituation.msg
からupdateフラグを削除crane_msgs/PlaySituation.msg
からworld{_modelを削除session_controller
の実装¶/game_analysis
/play_situation
メンバ変数の末尾にアンダースコアを付けるのはやめにした
+session_controller
の実装session_controller
の実装session_controller
をイベント駆動にする¶/play_situation
)/game_analysis
)request
関数を呼び出すのでそれで代用しても良さそう?play_situation/
をつけるとりあえずこんな感じ
+ +読み込みはyaml-cppを使う +今後の改良ポイントとしては,
+https://github.com/Rione/ssl-RACOON-AI-beta/tree/competition
+攻撃時はとりあえずシュートするプログラムシンプルなプログラムでびっくり(INDIRECTを除く)
+ファーストバージョンはこれくらいで良いのかも
詳細はこちらに書いた
+---
+name: SIMPLE_ATTACK
+description: SIMPLE ATTACK
+sessions:
+ - name: "goalie"
+ capacity: 1
+ - name: "shooter"
+ capacity: 1
+ - name: defender
+ capacity: 4
+ - name: waiter
+ capacity: 20
+
よく考えれば,シュート出来そうになかったらパスするだけなのでこれがパスは後から組み込みで全然良いなぁ
+ + + + + + + + + + + + + + + + + + + + +session_controller
を初期化するこれもまた設定ファイルを作った方が良い
+play_situation/
以下にまとめるevent_config.yaml
まだまだ設定とそれに伴う実装が足りてないけど,枠組みとしてはいい感じ
+[play_switcher_node-10] [INFO] [1683989045.103454434] [crane_play_switcher]: ---
+[play_switcher_node-10] [INFO] [1683989045.103487097] [crane_play_switcher]: RAW_CMD : 1 (COMMAND_STOP)
+[play_switcher_node-10] [INFO] [1683989045.103501253] [crane_play_switcher]: INPLAY_CMD : 1 (STOP)
+[play_switcher_node-10] [INFO] [1683989045.103513245] [crane_play_switcher]: REASON : RAWコマンド変化:コマンド転送
+[play_switcher_node-10] [INFO] [1683989045.103526384] [crane_play_switcher]: PREV_CMD_TIME: 5.388861
+[crane_session_controller_node-5] [ERROR] [1683989045.103671870] [session_controller]: イベント「STOP」に対応するセッションの設定が見つかりませんでした
+[play_switcher_node-10] [INFO] [1683989048.678499392] [crane_play_switcher]: ---
+[play_switcher_node-10] [INFO] [1683989048.678535396] [crane_play_switcher]: RAW_CMD : 0 (COMMAND_HALT)
+[play_switcher_node-10] [INFO] [1683989048.678548954] [crane_play_switcher]: INPLAY_CMD : 0 (HALT)
+[play_switcher_node-10] [INFO] [1683989048.678557748] [crane_play_switcher]: REASON : RAWコマンド変化:コマンド転送
+[play_switcher_node-10] [INFO] [1683989048.678567988] [crane_play_switcher]: PREV_CMD_TIME: 8.963902
+[crane_session_controller_node-5] [INFO] [1683989048.678675503] [session_controller]: イベント「HALT」に対応するセッション「HALT」の設定に従ってロボットを割り当てます
+[crane_session_controller_node-5] [INFO] [1683989048.678703304] [session_controller]: request : HALT
+[crane_session_controller_node-5] [INFO] [1683989048.678712896] [session_controller]: selectable_robot_ids : 0 1 2 3 4 5 6 7 8 9 10
+
役割:ボールへ突撃する役
+インダイレクトのときは別のプランナで...と分けたくなるのを我慢していったんここへ押し込める
+シチュエーション | +動作 | +
---|---|
STOP | +ボールの一番近くで待機 | +
INPLAY | +ボールに突進してシュートする,ダメそうなら近くの味方にパスを出す | +
KICKOFF_PREPARATION | +ボールの一番近くで待機 | +
KICKOFF_START | +近くの味方にパスする | +
INDIRECT_FREE | +近くの味方にパスを出す | +
DIRECT_FREE | +近くの味方にパスを出す | +
PENALTY_PREPARATION | +ボールの一番近くで待機 | +
PENALTY_START | +シュートする | +
ボールに一番近いロボットを割り当て
+代表的な割当ポリシーは名前付きでいくつかプリセット実装をしても置いて良いかも
+動作確認@ハンス宅のための作業
+Rootsのと雷さんの助けもあり,無事に動作確認できた +https://twitter.com/ShotaAk/status/1662225994735050752
+そもそも,local_plannerには色々な処理が混在しているので関数で分割する +やっぱり座標変換はsenderでやるべきかも +SimとRealの共通処理を設けるべきな気がしてきた
+リソース:Crow 1台,Orin 1台
+RobotCommandの更新に追従できていなかったので修正
+ちゃんと色どおりのものが動いた
+そもそも,チームカラー情報はレフェリーからくる
+なので,/referee
をWorldModelPublisherが受信してチーム情報を更新する
+レフェリー関連を起動しないときもあるので初期値はros paramで設定できるようにする
/referee
を読んでチームカラーを設定できるように見事にその場で青チームのゴール位置をハードコートしていたので修正
+色々修正したらようやく直った
+ros2 paramで対応 +parameterのコールバック初めて書いた
+ボールの後ろに回り込んでひたすら相手ゴールにシュートするプランナを作った. +後ろへの回り込み判定はボールを中心に相手ゴールとの方向に対して後ろにいるかどうかを内積で判定した.
+蹴ったかどうかの判定が非常に難しいので,ロボットからのフィードバックがほしい. +オカダがUDPに既に投げてくれているので,あとはそれを拾ってROS 2に持ってくるだけではある
+ボールの後ろに回り込んでひたすら相手ゴールにシュートするプランナを作った. +後ろへの回り込み判定はボールを中心に相手ゴールとの方向に対して後ろにいるかどうかを内積で判定した.
+蹴ったかどうかの判定が非常に難しいので,ロボットからのフィードバックがほしい. +オカダがUDPに既に投げてくれているので,あとはそれを拾ってROS 2に持ってくるだけではある
+蹴ったかどうかの判定が非常に難しいので,ロボットからのフィードバックがほしい. +オカダがUDPに既に投げてくれているので,あとはそれを拾ってROS 2に持ってくるだけではある
+ + + + + + + + + + + + + + + + + + + + + +骨組み
+ +蹴ったかどうかの判定が非常に難しいので,ロボットからのフィードバックがほしい. +オカダがUDPに既に投げてくれているので,あとはそれを拾ってROS 2に持ってくるだけではある
+ + + + + + + + + + + + + + + + + + + + + +骨組み
+ +蹴ったかどうかの判定が非常に難しいので,ロボットからのフィードバックがほしい. +オカダがUDPに既に投げてくれているので,あとはそれを拾ってROS 2に持ってくるだけではある
+ + + + + + + + + + + + + + + + + + + + + +通信内容の見直し
+Skillを中心としたシステムへの移行目処が立った,というかxx_plannerの中身は一部Skillで置き換えている. +これは,Skillの試用を目的とする暫定的な処置であるが,良さげであったので,このままSkillを中心としたシステムを組むことにした.
+-[x] plugin_baseをRole用に書き換え -[x] サービス通信をなくす -[x] session_planner側作業 -[x] SessionModuleをplugin_baseに置き換え
+生成した回避点が、既に通り過ぎたものを含んでいる。 +こうなると、途中で戻ったり立ち往生したりしてしまう。
+現在は、ロボット側から回避点をたどってゴールに到着できるか判断しているが、 +ゴール側からたどるとうまく行くかも?
+ + + + + + + + + + + + + + + + + + + + +すべての機能をSkill化するのはあり。
+マクロを駆使して、RobotCommandをSkill化した。 +しかし、パラメータをうまく渡せないので、うまく噛み合わない。
+Skillのパラメータを共通インタフェースを渡せるようにすると型の問題などが面倒なので、 +各個スキルクラスでパラメータのセッターを独自定義することにしたんだった。 +このときは、Skillクラスをプログラム上で呼び出すことしか考えていなかったので、 +特に共通インタフェースを無理して作るインセンティブもなく、むしろ各々のスキルクラスで便利なように独自定義できることが強みだと思っていた。
+SimpleAIなど、共通インタフェースを使ってパラメータを渡したい場合が出てきた今、そうも言っていられない。 +ということで、共通インタフェースを作ることにした。
+SimpleAIでは、vector
将来を見据えると、複数の型を扱える共通インタフェースがほしい
+std::vector
昨日は、インタフェースを設計して、SkillBaseクラスに対して設置するところまで行った。 +今日は、既存のSkillの対応と、SimpleAIでの対応を行う。
+既存のUIだと無理なので、パラメータテーブルを使ってたくさんのパラメータを設定できるようにする。
+ + + + + + + + + + + + + + + + + + + + +Boost.Geometryの拡張機能。最近傍点を求めるために使っている。 +ビルドにはインターネット接続が必要。
+matplotlibのC++ラッパー。無印のmatplotlib-cppとは別物で高機能。 +今は使っていないが、軽いデバッグに便利
+https://github.com/SSL-Roots/consai_ros2
+SSL公式のprotoメッセージをROS2で使えるようにしたもの。 +GameEvent関連は移植されていない。
+EKFでVisionデータをフィルタリングして、使いやすいようにするパッケージ
+SSL関連のデータをすべて集めたトピックである/world_model
を配信するパッケージ
+これをすることで、他のノードは/world_model
だけを購読すればよくなる
world_model_wrapperは、world_modelの情報を使って、よく使う幾何学計算をまとめたもの
+基礎的な幾何学計算などを集めたパッケージ
+実際の動きに組み込むためには、Plannerを作る必要がある。
+crane_planner_plugins/planners.hppに文字列とPlannerのペアを登録する
+https://github.com/ibis-ssl/crane/issues/130
+まずは現状分析
+graph TD
+ LP["`Callback
+ **Local Planner**
+ Immediately`"]
+ PS[Play Switcher]
+ GA[Game Analyzer]
+
+ subgraph interface
+ VC["`100Hz
+ **Vision Component**
+ Immediately`"]
+ GrC[GrSim Component]
+ GCC[Game Controller Component]
+ Receiver[Robot Receiver]
+ end
+
+ SC["`WorldModel Callback
+ **Session Controller**
+ Immediately`"]
+ SS[Sim Sender]
+
+ VT["`100Hz
+ **Vision Tracker**
+ Immediately`"]
+ WP["`Callback
+ **World Model Publisher**
+ 30Hz`"]
+
+ subgraph software
+ GrSim[GrSim]
+ GC[Game Controller]
+ end
+
+ WP -- /world_model --> SC
+ WP -- /world_model --> GA
+ GA -- /game_analysis --> SC
+
+
+ GrC -. UDP .-> GrSim
+
+ GrSim -. UDP .-> GrC
+ GrC -- /geometry --> WP
+
+ GrSim -. UDP .-> VC
+
+
+ VC -- /detection --> VT
+ VT -- /detection_tracked --> WP
+
+ GC -. UDP .-> GCC
+ GCC -- /referee --> PS
+ PS -- /play_situation --> SC
+ SC -- /control_targets --> LP
+ LP -- /robot_commands --> SS
+ SS -- /commands --> GrC
+
+ Receiver -- /feedback --> WP
+netstat -g
でマルチキャストグループとインタフェースの対応を確認netstat -g
でマルチキャストグループとインタフェースの対応を確認ロボットのアドレスに対して静的ルーティングを設定する
+/etc/netplan/01-network-manager-all.yaml
network:
+ version: 2
+ renderer: networkd
+ ethernets:
+ enp3s0:
+ addresses:
+ - 192.168.1.2/24
+ gateway4: 192.168.1.1
+ routes:
+ - to: 192.168.2.0/24
+ via: 192.168.1.1
+ - to: 192.168.3.0/24
+ via: 192.168.1.1
+
graph TD
+ subgraph official
+ GameController[Game Controller]
+ AutoRef[Auto Ref]
+ Vision[SSL Vision]
+ end
+
+ OfficialHub[大会用スイッチングハブ]
+
+ subgraph AIPC
+ OfficialInterface[大会サーバー用Interface]
+ ibisInterface[ロボット用Interface]
+ crane[crane]
+ sender[real_sender]
+ receiver[robot_receiver]
+ end
+
+ SwitchingHub[スイッチングハブ]
+ Router[ルーター]
+
+ Robots[ロボット]
+ PC[開発PC]
+
+ Net[インターネット]
+
+ GameController -- UDP Multicast --> OfficialHub
+ AutoRef -- UDP Multicast --> OfficialHub
+ Vision -- UDP Multicast --> OfficialHub
+
+ OfficialHub -- UDP Multicast --> SwitchingHub
+ SwitchingHub -- UDP Multicast --> OfficialInterface
+ OfficialInterface -- UDP Multicast --> crane
+ crane -- ROS --> sender
+ sender -- UPD to 192.168.20.1xx --> ibisInterface
+
+ ibisInterface -- UPD to 192.168.20.1xx --> SwitchingHub
+ SwitchingHub -- UPD to 192.168.20.1xx --> Router
+ Router -- AICommand --> Robots
+ Robots -- RobotFeedback --> Router
+ Router -- UPD to 192.168.20.1xx --> SwitchingHub
+ SwitchingHub -- RobotFeedback UPD Multicast --> ibisInterface
+ ibisInterface -- RobotFeedback UPD Multicast --> receiver
+ receiver -- ROS --> crane
+
+ssl-vision
のデフォルトポートgrSim
のデフォルトポートRefereeなどから直接示されない,ゲームの状況を解析するノード.
+ゲームの状況を解析し,ゲームの状況を示すメッセージを毎フレームpublishする.
+重い処理を含む解析は数フレームに1度のみ行い,それ以外のフレームでは前回の結果をpublishする.
両チームのボールに最も近いロボットを抽出し,ボールとの距離がしきい値以下ならばボール所持と判定する.
+味方チームの戦略から,パス中などもボール所持判定にできるようにする. +そのためには,パスの成否判定の実装が必要である
+未実装
+refereeからの信号を受け取って,解析した情報を流すノード
+refereeからは毎フレーム情報が流れてくるが,PlaySwitcherからの出力時は情報に更新があった時のみ
Blue / Yellowのイベントを解釈して,敵味方のイベントに変換する
+前のイベントに応じてNORMAL_STARTの解釈を行う
+参考:5.3.1 Normal Start | Official Rule
+前のイベント | +NORMAL_START の解釈 |
+
---|---|
KICKOFF_PREPARATION |
+KICKOFF_START |
+
PENALTY_PREPARATION |
+PENALTY_START |
+
INPLAYのイベントはRefereeからは送信されてこないのでPlaySwitcherで判定する
+参考:5.4. Ball In And Out Of Play | Official Rule
+FORCE_START
発動時KICKOFF_START
PENALTY_START
DIRECT_FREE
INDIRECT_FREE
ボールの所有権をもつロボットが、ボールを操作して行う行動をアクションとする。 +ボールは1つなので、複数台のロボットが同時にボールの所有権を持つことはなく、一連のオフェンスはアクションの列として表現される。
+アクションの本体は、ロボットがボールを操作する瞬間の集合である。 +例えば、パスやシュートならば、ボールを蹴る瞬間であり、ドリブルならばドリブルしている間である。
+ただし、これだけだとオフェンス中にどのアクションにも属さない状態が生じるので、前のアクションの本体が終了したとき、次のアクション +が始まるものとする。(これらの時間範囲はアクションに含まれるだけであって、アクションの本体であるわけではない) +例えば、パスの場合ではボールが前のロボットからキックされて自分の方に転がり始めた瞬間からパスアクションが始まり、次のロボットへボールを蹴り出した瞬間にパスアクションが終了する。 +ここで、キックに失敗したときは上位レイヤーで認知され、アクション列が作り直される。
+また、アクションではアクション本体以外のステージも持つ。
+パスを受ける地点から離れすぎない範囲で、マークを振り切るための動きを行う。
+パスを受け取る地点へ移動する
+パスを受け取る地点へ移動し、ボールを受け取って次のターゲットへキックする
+特になし
+正直このアクションは必要かどうかは微妙 +パスアクションの特殊化として扱うべきかもしれない
+stateDiagram-v2
+ Protect --> ApproachBallLine: ballMoves
+ Protect --> Kick : switchToKick
+
+ Dribble --> DribbleKick: switchToDribbleKick
+ Dribble --> Kick: switchToKick
+ Dribble --> Protect: FAILURE
+
+ ApproachBallLine --> Receive: SUCCESS
+ ApproachBallLine --> approachAndStopBall: FAILURE
+ ApproachBallLine --> approachAndStopBall: closeToBall
+
+ approachAndStopBall --> Protect: SUCCESS
+ approachAndStopBall --> Protect: FAILURE
+
+ Kick --> Receive: SUCCESS
+ Kick --> Protect: FAILURE / INVALID
+ Kick --> FreeKick: waitForKick
+ Kick --> FreeKick: useSingleTouch
+
+ FreeKick --> ApproachBallLine: SUCCESS
+ FreeKick --> Protect: FAILURE
+
+ Receive --> Protect: SUCCESS
+ Receive --> Protect: FAILURE
+ Receive --> Redirect: SwitchToRedirect
+
+ Redirect --> ApproachBallLine: SUCCESS
+ Redirect --> Protect: FAILURE
+ Redirect --> Receive: switchToReceive
+
+ DribbleKick --> Protect: dribblingKickIsBlocked
+ DribbleKick --> Protect: FAILUR
+stateDiagram-v2
+ Stop --> Defend: !stoped
+
+ PreparePenalty --> Defend: !isPreparePenalty
+
+ MoveToPenaltyArea --> Defend: SUCCESS
+ MoveToPenaltyArea --> Defend: isKeeperWellInsidePenaltyArea
+ MoveToPenaltyArea --> Stop: isStopped
+ MoveToPenaltyArea --> PreparePenalty: isPreparePenalty
+
+ Defend --> Pass: ballCanBePassedOutOfPenaltyArea
+ Defend --> Rambo: canGoOut
+ Defend --> GetBallContact: isBallBetweenGoalyAndGoal
+ Defend --> MoveToPenaltyArea: isOutsidePenaltyArea
+ Defend --> Stop: isStopped
+ Defend --> PreparePenalty: isPreparePenalty
+ Defend --> Intercept: canInterceptSafely
+
+ Pass --> Defend: isBallMoving
+ Pass --> MoveInFrontOfBall: ballPlacementRequired
+ Pass --> Stop: isStopped
+ Pass --> PreparePenalty: isPreparePenalty
+
+ Intercept --> Defend: hasInterceptionFailed
+ Intercept --> Pass: ballPlacementRequired
+ Intercept --> Stop: isStopped
+ Intercept --> PreparePenalty: isPreparePenalty
+
+ Rambo --> Defend: isBallInPenaltyArea(0) || isGoalKick()
+ Rambo --> Stop: isStopped
+ Rambo --> PreparePenalty: isPreparePenalty
+
+ MoveInFrontOfBall --> Defend: isBallMoving
+ MoveInFrontOfBall --> Defend: ballPlaced
+ MoveInFrontOfBall --> GetBallContact: SUCCESS
+ MoveInFrontOfBall --> Stop: isStopped
+ MoveInFrontOfBall --> PreparePenalty: isPreparePenalty
+
+ GetBallContact --> MoveWithBall: SUCCESS
+ GetBallContact --> MoveInFrontOfBall: FAILURE
+ GetBallContact --> Stop: isStopped
+ GetBallContact --> PreparePenalty: isPreparePenalty
+
+ MoveWithBall --> Defend: SUCCESS
+ MoveWithBall --> MoveInFrontOfBall: FAILURE
+ MoveWithBall --> Stop: isStopped
+ MoveWithBall --> PreparePenalty: isPreparePenalty
+
+stateDiagram-v2
+ Receive --> Prepare: SUCCESS
+ Receive --> StopBall: FAILURE
+ Prepare --> DropBall: ballIsPlaced
+ Prepare --> GetBallContact: success
+ Prepare --> Receive: ballMoving
+ Prepare --> Pass: ballNeedsToBePassed
+ Prepare --> GetBallContact: skipPrepare
+ StopBall --> Prepare: SUCCESS
+ StopBall --> Prepare: FAILURE
+ GetBallContact --> MoveWithBall: SUCCESS
+ GetBallContact --> DropBall: FAILURE
+ MoveWithBall --> DropBall: SUCCESS
+ MoveWithBall --> Receive: FAILURE
+ Pass --> ClearBall: FAILURE
+ Pass --> ClearBall: SUCCESS
+ Pass --> ClearBall: pass mode is NONE
+ DropBall --> ClearBall: FAILURE
+ DropBall --> ClearBall: SUCCESS
+TDP2018に解説されている。
+※viability: 実行可能性
+calcAction
+build関数はOffensiveActionTypeのラインナップをサポート
+ +フリーキックのような、必ずパスしなければいけない状況で使われる。
+ +ドリブルしながらゴールを狙うアクション
+ボールをゴール中心から離れる方向にチップキックする
+次にボールがキックされる点。
+ボールが動いていないときは、ボールの場所であり、動いているときは以下のいずれかが発生したときである。
+impact time: ボールがKickOriginに到着するまでの時間
+ + + + + + + + + + + + + + + + + + + + +v1ではボールを中心に円筒座標系でサンプリングしていたが,v2ではロボットを中心にサンプリングしている
+https://github.com/Rione/ssl-RACOON-AI-beta
+https://github.com/Rione/ssl-RACOON-AI-beta/tree/competition/racoon_ai/strategy/role
+https://github.com/Rione/ssl-RACOON-AI-beta/blob/competition/racoon_ai/strategy/role/role.py#L138
+https://github.com/Rione/ssl-RACOON-AI-beta/blob/competition/racoon_ai/strategy/role/subrole.py#L53
+※enemy_attackerは敵チームのボールに一番近いロボット
+https://tdp.roboteamtwente.nl/tdps/144?ref=year
+ゴールキーパーのような、ゴール地点で速度ゼロにならなくても場所と時間さえあっていればOKというケースに対応して有効守備範囲を広げている。
+https://tdp.roboteamtwente.nl/tdps/241?ref=year
+シミュレータを組み込んでのテスト
+https://tdp.roboteamtwente.nl/tdps/89?ref=year
+v2016からv2019までのアップデート
+ここに書いてあることはTDP2016が詳しい
+TBD
+TBD
+従来、パスターゲットの評価値は一つしかなかったが、いかに分割した。
+TBD
+ドリブラの自由度を増やして、ボールの衝撃吸収とボールのドリブル性能の両立を図った。
+robocup_ssl_comm
¶HALT
などのRefBoxコマンド¶consai_vision_tracker
¶Visionの情報からボール・ロボットの位置を推定する
+consai_visualizer
¶特に手を加えていない
+crane_sender
¶crane_world_model_publisher
¶craneでは、セッションという単位でロボットの動作を管理する
+セッションでは,複数のロボットがそれぞれの役割・目的が与えられる
+このとき,ロボットには役割に応じて用意してある専用のプランナが割り当てられる
+※このプランナ郡は crane_planner_plugins
にある
+例えば,ある攻撃状態でパス中のセッションは以下のようになる
これらはファールなどでロボットの数が可変になる中でもうまく割り当てを行う必要があるため,割当プランナが存在する
+セッションには,優先順位・最大ロボット使用台数と共にプランナが登録される.
+session_controller
は今使えるロボットをこの優先順位に従ってロボットを配置する.
+session_controller
は,優先順位が高いプランナから順に,今空いているロボットの情報を送信し,プランナにとって最も都合の良いロボットを選択してもらう.
+これを使えるロボットがなくなるまで繰り返してロボットの割当を行う.
crane_planner_base
¶crane_planner_plugins
¶crane_session_controller
¶特にここではファールカウンターを増やすものについて
+https://robocup-ssl.github.io/ssl-rules/sslrules.html#_keeper_held_ball
+ボールをデフェンスエリアで保持しすぎるとだめ。
+divAは5秒、divBは10まで
+STOPのちフリーキック
ゴールキーパーはボールが止まり次第、ボールを排出するプログラムになっている
+デフェンスエリアギリギリにボールがあり、近くにロボットが迫っている場合には排出できないかも。
+また、このような状況ではそもそもボールに触れなくなるような挙動もあったかも知れないので要対応。
https://robocup-ssl.github.io/ssl-rules/sslrules.html#_boundary_crossing
+フィールドの外にボールを蹴っちゃだめ。
+ここで言うフィールドの外とは、ラインの外ではなく木枠の外のこと。
+STOPのちフリーキック
特に対応はしていないが、基本的にチップキックは味方の方向にパスするとき、かつそのパスライン上に敵ロボットが存在する場合に限るので基本的には問題ないと考えている。
+コート端にいる味方にむけてチップキックパスをしたら発生するかも。
+ただ、かなり可能性は低いので対応は現時点で考えていない。
https://robocup-ssl.github.io/ssl-rules/sslrules.html#_excessive_dribbling
+いわゆるオーバードリブルと呼ばれるもの。
+1m以上ドリブルすると発生するが、一度でもボールがロボットから離れるとリセットされる。
+インプレイ時のみの違反なので、ボールプレイスメントで行う分には問題ない。
+STOPのちフリーキック
JapanOpen2024ではボールプレイスメント以外でドリブルを使う予定はないため問題ないはず。
+もしかすると、ペナルティキックのときに相手ゴール近くまでボールを運ぶときに使うかも知れない。
+参考:https://github.com/ibis-ssl/crane/issues/246
そもそもドリブルしなければ問題なし。
+相手ディフェンスエリアでボールに触れると発生する。
+(逆に言えば、侵入だけなら大きくは咎められない?)
+ロボットの一部でもエリアに侵入していれば適用されるため、注意が必要。
コストマップ上で立入禁止エリアに設定してあるので、基本的には発生しないはずである。
+高速でデフェンスエリア付近のボールに接近した場合、勢い余ってディフェンスエリアに侵入してしまうことが考えられる。
+実際に発生した場合、速度上限を下げたり立入禁止エリアにマージンを設けることで対処予定。
+デフェンスエリアの立ち入り禁止は敵味方を区別していないため、デフェンスエリアに立ち入り許可のあるゴールキーパーが相手ゴールまでキーパーダッシュすれば立ち入る可能性があるが、今の所は味方ディフェンスエリアから出るようなプログラムはない。
https://robocup-ssl.github.io/ssl-rules/sslrules.html#_ball_speed
+ボールが速すぎると発生する。
+具体的には6.5m/sになると発生する。
ただし、そもそも6m/s程度になるとVisionロストするとの情報もある。
+ストレートキックは50%程度、チップキックは80%程度のパワーを上限に蹴っている。
+これで特に問題はないはず。
ミスって設定していたら発生する。
+よりローカルプランなやセンダーなどの下流で制限するようにしてもいいかも?
https://robocup-ssl.github.io/ssl-rules/sslrules.html#_crashing
+ロボットの衝突時に相対速度が1.5m/sを超えるとより早いロボット側のチームに発生する。
+相対速度のより詳しい計算はルールブック参照。
+速度差が0.3m/s未満だと両成敗になる。
一応、デフォルトでロボットとその周辺のマージンを取って立ち入り禁止エリアを設定しているので基本発生しないはず。
+ロボットとの距離と相対速度で速度を制限することで追加対応予定。
+https://github.com/ibis-ssl/crane/issues/296
マージンが薄いので速度がでると容易に衝突してしまうかも。
+また、お互いが移動している場合には立入禁止エリアがあまり役に立たない。
+また、ディフェンダーやアタッカーなど敵ロボットに忖度していては仕事にならないロボットは立ち入り禁止設定を解除しているので、ぶつかりやすい。
https://robocup-ssl.github.io/ssl-rules/sslrules.html#_robot_too_close_to_opponent_defense_area
+STOP中やフリーキック中に相手ディフェンスエリア+マージン0.2mの中に侵入すると発生する。
+脱出時間として、判定には2秒の猶予があるらしい。
現状これに特化したプログラムはないが、基本的にはディフェンスエリアに入るようなプログラムはないはず。
+特に対策しているわけではないので、特定の状況で発生するかも。
+例えば、マークしている敵ロボットがディフェンスエリアに逃げ込んだ場合など
https://robocup-ssl.github.io/ssl-rules/sslrules.html#_robot_stop_speed
+STOP中に1.5m/sを超える速度で移動すると発生する。
+STOPになってから2秒間は猶予時間がある。
現状、STOP中には最大速1.0m/sのフォーメーションが割り当てられている。
+ただし、今後はSTOP中により意味ある動きをするプログラムに書き換えるため、
+それに伴ってローカルプランナなどで一括速度制限をかける予定である。 (#297)
#297で完全対応予定
+https://robocup-ssl.github.io/ssl-rules/sslrules.html#_defender_too_close_to_ball
+敵キックオフやフリーキックの間、ボールから0.5m以上離れていないと発生する。
+特に対応できていない。
+#283で対応予定。
#283で完全対応予定。
+https://robocup-ssl.github.io/ssl-rules/sslrules.html#_ball_placement_interference
+ボールプレイスメント中にボールとターゲットで構成される線分への距離が0.5m以内にロボットがいると発生する。
+立入禁止エリアを設定しているので基本的には発生しないはず。
+これに侵入するように設定しているのは、自チームのボールプレイスメント時のボールハンドラのみである。
ロボットの目標地点が禁止エリア内にある場合、ロボットは多少ゆらゆらすることがある。
+もう少しマージンを取るようにしてもいいかもしれない。
+また、ボールプレイスメントエリアの配置によってはうまく機能しないかもしれない。
+(壁際でエリアに追い詰められた場合など)
https://robocup-ssl.github.io/ssl-rules/sslrules.html#_pushing
+ロボットが押し合って、相手のロボットを動かすと発生する。
+押し勝っていると思われるチームに発生する。
+STOPのちフリーキック、AutoRefによる判定はない。
特に対応できていない。
+ボールの中心に移動し続けるようなプログラムが何箇所かあり、それが原因で発生する可能性がある。
+https://robocup-ssl.github.io/ssl-rules/sslrules.html#_ball_holding
+ホールディングと呼ばれるもの。
+ボールをロボットで囲み、敵のアプローチを防ぐような行為を行うことで発生する。
+STOPのちフリーキック、AutoRefによる判定はない。
特に対応はしていない。
+故意に固まるようなプログラムはないが、特にデフェンス時に似た状況に陥りやすいかもしれない。
+https://robocup-ssl.github.io/ssl-rules/sslrules.html#_tipping_over_or_dropping_parts
+ロボットが部品を落としたり、倒れたりすると発生する。
+違反ロボットは交代する必要がある。
ネジ締めなどをしっかりする。
+また、かなり低重心なので転倒はするほうが難しい。
ネジの緩みなどで発生する可能性がある。
+ + + + + + + + + + + + + + + + + + + + +Velocity Obstacle(VO)という考え方をベースに速度空間で計算を行って障害物回避を行うローカルプランナー。
+SSLでは単に障害物を回避するだけではなく、ルールによる禁止エリアへの侵入を防ぐ必要がある。 +アルゴリズムに則った実装を行うならば、禁止エリアへ向かう速度を選択しないような速度空間における線形制約を追加する必要がある。
+しかし、RVO2ライブラリの中に手を加える必要があったり、この操作をわざわざ速度空間で行う必要性もない。 +そこで、ここではRVO2に受け渡す前に禁止エリア内に目標位置がある場合は、禁止エリア外に設定し直すなどの前処理を行うことで対応する。 +この処理の便利なところは、目標位置が必ず禁止エリア外になるため、ロボットが既に禁止エリア内にいる場合でも、目標位置を設定するだけで自動的に禁止エリアから退避できるところである。
+ボールプレイスメントエリアの退避は以下のような特殊性をもつ。
+よって、ボールプレイスメントエリアの回避は専用のPlanner作成するのが良い。 +幸い、ボールプレイスメント中はエリアを避けることしか考えなくて良いので、非常にシンプルなPlannerを書くことができる。 +(厳密には、ボールプレイスメント後の敵のフリーキックのことを考える必要はあるが...)
+目標位置、現在位置がペナルティエリアにはいったときに適用する。
+目標位置・現在位置共にペナルティエリアに入っていない場合でも、経路がペナルティエリアを通過する場合がある。
+Ubuntu 22.04での環境構築手順を記載します。
+sudo apt install curl gnupg lsb-release
+sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
+echo "deb [arch=x86_64 signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
+sudo apt update
+sudo apt install ros-jazzy-desktop-full
+
mkdir -p ibis_ws/src
+cd ibis_ws/src
+git clone git@github.com:ibis-ssl/crane.git
+cd ibis_ws
+source /opt/ros/jazzy/setup.bash
+vcs import src < src/crane/dependency.repos
+rosdep install -riy --from-paths src
+colcon build --symlink-install
+source install/local_setup.bash
+
公式のGrSimの出力はSSL-Visionと一部異なるため、修正済みのibis-sslバージョンを使用してください。
+ +docker-composeコマンドで以下が立ち上がります
+詳しくはこちら
+ + + + + + + + + + + + + + + + + + + + +graph TD
+ subgraph interface
+ VisionNode[Vision Component]
+ Sender[Real Sender]
+ Receiver[Robot Receiver]
+ end
+
+ VT[Vision Tracker]
+ WP[World Model Publisher]
+ Main[Simple AI]
+ LP[Local Planner]
+
+ subgraph RealWorld
+ Robot[Actual Robot CM4]
+ SSLVision[SSL Vision]
+ end
+
+ SSLVision -. UDP .-> VisionNode
+ VisionNode -- /detection --> VT
+ VT -- /detection_tracked --> WP
+ VisionNode -- /geometry --> WP
+
+ WP -- /world_model --> Main
+ Main -- /control_targets --> LP
+ LP -- /robot_commands --> Sender
+
+ Sender -. UDP .-> Robot
+
+ Robot -. UDP .-> Receiver
+ Receiver -- /feedback --> WP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Skillとは、単一のロボットの動作を表す単位である。
+スキルクラスは、crane_robot_skills
パッケージに実装する。
+crane_robot_skills
パッケージは多くの被依存パッケージを持つため、ヘッダファイルを変更するとコンパイル時間が増大してしまう。
+そのため、実装はなるべくcppファイルに書くようにすると良い。
world_modelなどの情報を受けとり、ロボットコマンドを出力することで、ロボットの動きを制御する。
+また、consai_visualizer
向けに可視化情報を出力することもできる。
スキルクラスは、ベースクラスを継承して実装するが、用途に合わせてベースクラスは2種類存在する。
+使用するロボットコマンドの制御モードは複数あるため、ベースクラスのテンプレート引数で使用する制御モードのロボットコマンドを指定する必要がある。
+ +現状、以下のロボットコマンドが存在する。
+標準のベースクラス。
+最低限update関数の実装が必要である。
+オプションとしてprint関数を実装することもできる。
Status update() override
+{
+ // メンバーのcommandを使ってロボットを動かす
+ Point pos{0,0};
+ command.setTargetPosition(pos);
+ // visualizerを使って可視化情報を出力する
+ visualizer->addCircle(pos, 0.1, 1, "white", "");
+ // スキルの状態を返す(SUCCESS/FAILUREになると終了)
+ return Status::RUNNING;
+}
+
状態遷移を行う動きを作りたい場合に使える、ステートマシンを組み込んだベースクラス。
+update関数の実装の代わりに、コンストラクタでステートごとのupdate関数と状態遷移条件の設定を行う。
// enum classでステートを定義する
+enum class TestState
+{
+ STATE_1,
+ STATE_2,
+};
+
+// テンプレートでロボットコマンドの型とステートの型を指定する
+class TestSkill : public SkillBaseWithState<TestState, RobotCommandWrapperPosition>
+{
+public:
+ TestSkill(RobotCommandWrapperBase::SharedPtr & base)
+ // スキルの名前、初期ステートを指定する
+ : SkillBaseWithState<TestState, RobotCommandWrapperPosition>("Test", base, TestState::STATE_1)
+ {
+ // ステートごとのupdate関数を登録する
+ addStateFunction(TestState::STATE_1,
+ [this]() -> Status {
+ // STATE_1の処理
+ return Status::RUNNING;
+ });
+
+ addStateFunction(TestState::STATE_2,
+ [this]() -> Status {
+ // STATE_2の処理
+ return Status::RUNNING;
+ });
+
+ // ステート遷移条件を登録する
+ // 遷移条件は毎フレーム評価され、条件がTRUEになると遷移する。
+ // 登録順に評価されるので、最初にTRUEになった条件で遷移することに注意。
+ // (優先度が高い遷移条件から順番に設定すると良い)
+ addTransition(TestState::STATE_1, TestState::STATE_2, [this]() -> bool {
+ // STATE_1からSTATE_2への遷移条件
+ return true; // この場合、必ず遷移する
+ });
+ }
+};
+
SimpleAIやスキルを使用するクラスなどで、スキルのパラメータを自由に設定できる。 +SimpleAIの画面で自由に設定できるので、デバッグや調整が容易になる。
+現在、以下の型が使用可能である。
+スキルクラスのコンストラクタで、パラメータを受け取る変数を宣言し、デフォルト値を設定する。
+{
+ // パラメータの名前とデフォルト値を設定する
+ // パラメータの名前は重複不可(重複した場合、上書きされる)
+ // パラメータの型は自動で判別される
+ setParameter("test_int_param", 0);
+ // C++のバグで、stdL::stringの設定をする場合は明示的に型を指定する必要がある。
+ // (指定しないとboolになってしまう)
+ setParameter("test_string_param", std::string("test"));
+ // 日本語の文字列も設定可能
+ setParameter("テスト", std::string("テスト"));
+}
+
setParameter関数を使って、パラメータを上書きできる。 +宣言したときの型と異なる型で上書きすると、エラーが発生する(はず)。
+ +getParameter関数を使って、パラメータを取得することができる。
+// テンプレートで型を指定する
+// パラメータが存在しなかったり、型が異なる場合は、例外が発生する
+int test_int_param = getParameter<int>("test_int_param");
+
スキルの内部変数をコンテキストとして登録することで、SimpleAIで内部変数の値を表示できるようになるので、 +デバッグが容易になる。
+SimpleAI上では、コンテキストの値を表示できるが、コンテキストの値を変更することはできない。
+現在、以下の型が使用可能である。
+class TestSkill{
+private:
+ // コンテキスト用のメンバ変数を宣言する
+ // 参照型である必要がある
+ int & context_int;
+public:
+ TestSkill(RobotCommandWrapperBase::SharedPtr & base)
+ // コンテキスト用のメンバ変数を初期化する
+ // SimpleAI上で表示する名前を指定する
+ : context_int(getContextReference<Point>("context_int"))
+ {}
+
+ Status update() override
+ {
+ // コンテキストの値を変更する(普通の変数同様に読み書きしてOK)
+ context_int = 1;
+ return Status::RUNNING;
+ }
+};
+
実装したスキルをSimpleAIで使えるようにするには、いくつかの手順が必要である。
+SimpleAIでスキルを一括インクルードするためのヘッダファイルに作成したスキルのヘッダファイルを追加する。 +https://github.com/ibis-ssl/crane/blob/develop/crane_robot_skills/include/crane_robot_skills/skills.hpp
+https://github.com/ibis-ssl/crane/blob/develop/crane_simple_ai/src/crane_commander.cpp#L38
+setUpSkillDictionary関数でスキルを登録する。
+ +作ったスキルすべてを登録すると、SimpleAIのスキル選択プルダウンの表示が大変なことになるので、あまり使わないスキルはコメントアウトしてある。
+スキルは直接セッションで動かせないため、スキル用のPlannerを作る必要がある。 +Skill単体のPlannerはskill_planner.hppに実装することが多い。
+ +crane_planner_plugins/planners.hppに文字列とPlannerのペアを登録する
+ + } else if (planner_name == "test_skill") {
+ return std::make_shared<TestSkillPlanner>(ts...);
+ }
+
セッションファイルで登録した文字列を使ってPlannerを呼び出す。
+name: test
+description: TestSkillのためのセッション
+sessions:
+ - name: test_skill
+ capacity: 1
+ - name: waiter
+ capacity: 20
+
セッションファイルは以下のディレクトリにある +https://github.com/ibis-ssl/crane/tree/develop/session/crane_session_controller/config/play_situation
+ + + + + + + + + + + + + + + + + + + + +ROS 2インストールしたら自動的に使えるようになるフォーマッタ。
+各階層に配置している.clang-format
もほぼ同じ設定になっているので適宜開発時に使うと良い。
コミット前に自動でフォーマットをかけるツール。
+ + +設定ファイルはこれ
+https://github.com/ibis-ssl/crane/blob/develop/.pre-commit-config.yaml
https://github.com/RoboCup-SSL/ssl-go-tools
+sudo apt install -y golang-go
+git clone https://github.com/RoboCup-SSL/ssl-go-tools.git
+cd ssl-go-tools
+make all
+sudo make install
+echo "export PATH="$(go env GOPATH)/bin:$PATH" >> ~/.bashrc
+
Referee信号を読み取って自動で試合ログを記録するツール。
+ +Usage of ssl-auto-recorder:
+ -http-port string
+ HTTP port for serving log files (default "8084")
+ -http-serve
+ Serve log files via HTTP (default true)
+ -output-folder string
+ Output folder where completed logs are copied to (default "logs")
+ -referee-address string
+ Multicast address for referee 2013 (default "224.5.23.1:10003")
+ -referee-enabled
+ Record referee packages (default true)
+ -vision-address string
+ Multicast address for vision 2014 (default "224.5.23.2:10006")
+ -vision-enabled
+ Record vision packages (default true)
+ -vision-legacy-address string
+ Multicast address for vision 2010 (legacy) (default "224.5.23.2:10005")
+ -vision-legacy-enabled
+ Record legacy vision packages (default true)
+ -vision-tracker-address string
+ Multicast address for vision tracker 2020 (default "224.5.23.2:10010")
+ -vision-tracker-enabled
+ Record vision tracker packages (default true)
+
git clone git@github.com:RoboCup-SSL/ssl-vision.git
+cd ssl-vision
+mkdir build
+cd build
+cmake .. -DUSE_V4L=true
+make -j
+cd ..
+./bin/vision
+
リポジトリのルートディレクトリで以下のコマンドを実行する.
+ +Thread0の「ImageCapture/Video 4 Linux/CaptureSettings」で以下を設定
+Thread0の「ImageCapture/CaptureControl」の「start capture」
+「Global/FieldConfiguration」を設定する +特に以下を設定
+※ロボットがオフセットしているように感じたら...
+右側の「Auto Color Calibration」タブを使って設定する
+「Thread0/Visualization/camera calibration」をTrueにする
+各スレッドの「Camera Calibrator/Calibration Parameters(list)」以下でコントロールポイントの設定ができる。
+それぞれのコントロールポイントのフィールドのxyの座標をmm単位で設定した後、カメラ画像上の点と対応付ける。
+座標を直に設定してもよいが、右の「Camera Calibration」タブを開いた状態にすると、コントロールポイントをドラッグして移動することができる。
コントロールポイントを設定したら、キャリブレーションを実行する。 +まず、右の「Camera Calibration」タブを開いて一番下の「Initial Camera Parameters」にある「Camera Height(in mm)」にカメラの高さを設定する。 +次に、「Do initial calibration」「Do full calibration」の順にボタンを押してキャリブレーションを実行する。
+色が設定できると、「blob」と呼ばれる画像上の同色の塊が認識されるようになる。 +認識されている様子は各スレッドの「Visualization/blobs」にチェックを入れることで確認できる。 +SSL-Visionでは、このblobに対してパターン認識を行い、ロボットやボールを認識する。
+各スレッドの「Blob Finding」にて認識するblobの最小面積(単位:ピクセル)「min_blob_area」や最大認識数「max regions」などを設定できる。
+「min_blob_area」は認識物体の中で一番小さいボールが消えない程度に設定するとよいだろう。
+「Global/Robot Detection/Pattern」の「Center Marker」や「Other Markers」でマーカーの認識調整が行える。 +ここでは認識されるマーカーの(画像上の)最小・最大の幅・高さ・面積のフィルターを設定できる。
+「Global/Robot Detection/Pattern/Pattern Fitting」でパターンマッチングの設定が行える。 +マッチングスコアの重みを調整することができる。 +blobが認識できているのに、ロボットが認識されない場合は、「Max Error」を大きくしてみて見るのも良いだろう。
+ + + + + + + + + + + + + + + + + + + + +