From 0163b754703a41fb0178a7eb769314c2fa02cec3 Mon Sep 17 00:00:00 2001 From: <> Date: Sun, 1 Dec 2024 06:14:06 +0000 Subject: [PATCH] Deployed 7c4a637 with MkDocs version: 1.6.1 --- .nojekyll | 0 404.html | 1557 ++++ ai/attacker/index.html | 1674 ++++ ai/ball_possession/index.html | 2009 +++++ ai/coordinates/index.html | 1698 +++++ ai/diagram/index.html | 1841 +++++ ai/docker/index.html | 1781 +++++ ai/grSim/index.html | 1628 ++++ ai/index.html | 1620 ++++ ai/logs/2023-04-16/index.html | 1768 +++++ ai/logs/2023-05-03/index.html | 1876 +++++ ai/logs/2023-05-06/index.html | 2027 +++++ ai/logs/2023-05-07/index.html | 1979 +++++ ai/logs/2023-05-13/index.html | 1781 +++++ ai/logs/2023-05-14/index.html | 1823 +++++ ai/logs/2023-05-27/index.html | 1844 +++++ ai/logs/2023-05-28/index.html | 1832 +++++ ai/logs/2023-05-30/index.html | 1939 +++++ ai/logs/2023-06-06/index.html | 1811 +++++ ai/logs/2023-06-07/index.html | 1766 +++++ ai/logs/2023-06-12/index.html | 1755 +++++ ai/logs/2023-06-17/index.html | 1896 +++++ ai/logs/2023-06-18/index.html | 1903 +++++ ai/logs/2023-06-21/index.html | 1884 +++++ ai/logs/2023-06-22/index.html | 1894 +++++ ai/logs/2023-07-01/index.html | 1894 +++++ ai/logs/2023-07-23/index.html | 1828 +++++ ai/logs/2023-11-04/index.html | 1766 +++++ ai/logs/2023-11-10/index.html | 1722 +++++ ai/logs/2024-01-28/index.html | 1736 +++++ ai/logs/2024-01-30/index.html | 1955 +++++ ai/logs/2024-01-31/index.html | 1769 +++++ ai/logs/2024-08-16/index.html | 2048 +++++ ai/logs/laytency/index.html | 1754 +++++ ai/match/index.html | 1714 +++++ ai/network/index.html | 1834 +++++ ai/nodes/game_analyzer/index.html | 1754 +++++ ai/nodes/play_switcher/index.html | 1840 +++++ ai/offense/index.html | 1991 +++++ ai/other_team/Sumatra/index.html | 2196 ++++++ ai/other_team/ZJUNLict/index.html | 1710 +++++ ai/other_team/img.png | Bin 0 -> 48467 bytes ai/other_team/rione_racoon_ai_beta/index.html | 1991 +++++ ai/other_team/robodragons/index.html | 1744 +++++ ai/other_team/tigers/index.html | 2528 +++++++ ai/progress/index.html | 2034 +++++ ai/rule/index.html | 2907 +++++++ ai/rvo2_local_planner/index.html | 1826 +++++ ai/setup/index.html | 1826 +++++ ai/simple_ai/index.html | 1772 +++++ ai/skill/index.html | 2275 ++++++ ai/tools/index.html | 1793 +++++ ai/vision/index.html | 2098 ++++++ assets/images/favicon.png | Bin 0 -> 1870 bytes assets/javascripts/bundle.83f73b43.min.js | 16 + assets/javascripts/bundle.83f73b43.min.js.map | 7 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.el.min.js | 1 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.he.min.js | 1 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.hy.min.js | 1 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.kn.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + assets/javascripts/lunr/min/lunr.sa.min.js | 1 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.te.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++ .../workers/search.6ce7567c.min.js | 42 + .../workers/search.6ce7567c.min.js.map | 7 + assets/stylesheets/main.6f8fc17f.min.css | 1 + assets/stylesheets/main.6f8fc17f.min.css.map | 1 + assets/stylesheets/palette.06af60db.min.css | 1 + .../stylesheets/palette.06af60db.min.css.map | 1 + index.html | 1619 ++++ search/search_index.json | 1 + sitemap.xml | 3 + sitemap.xml.gz | Bin 0 -> 127 bytes 100 files changed, 104791 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 ai/attacker/index.html create mode 100644 ai/ball_possession/index.html create mode 100644 ai/coordinates/index.html create mode 100644 ai/diagram/index.html create mode 100644 ai/docker/index.html create mode 100644 ai/grSim/index.html create mode 100644 ai/index.html create mode 100644 ai/logs/2023-04-16/index.html create mode 100644 ai/logs/2023-05-03/index.html create mode 100644 ai/logs/2023-05-06/index.html create mode 100644 ai/logs/2023-05-07/index.html create mode 100644 ai/logs/2023-05-13/index.html create mode 100644 ai/logs/2023-05-14/index.html create mode 100644 ai/logs/2023-05-27/index.html create mode 100644 ai/logs/2023-05-28/index.html create mode 100644 ai/logs/2023-05-30/index.html create mode 100644 ai/logs/2023-06-06/index.html create mode 100644 ai/logs/2023-06-07/index.html create mode 100644 ai/logs/2023-06-12/index.html create mode 100644 ai/logs/2023-06-17/index.html create mode 100644 ai/logs/2023-06-18/index.html create mode 100644 ai/logs/2023-06-21/index.html create mode 100644 ai/logs/2023-06-22/index.html create mode 100644 ai/logs/2023-07-01/index.html create mode 100644 ai/logs/2023-07-23/index.html create mode 100644 ai/logs/2023-11-04/index.html create mode 100644 ai/logs/2023-11-10/index.html create mode 100644 ai/logs/2024-01-28/index.html create mode 100644 ai/logs/2024-01-30/index.html create mode 100644 ai/logs/2024-01-31/index.html create mode 100644 ai/logs/2024-08-16/index.html create mode 100644 ai/logs/laytency/index.html create mode 100644 ai/match/index.html create mode 100644 ai/network/index.html create mode 100644 ai/nodes/game_analyzer/index.html create mode 100644 ai/nodes/play_switcher/index.html create mode 100644 ai/offense/index.html create mode 100644 ai/other_team/Sumatra/index.html create mode 100644 ai/other_team/ZJUNLict/index.html create mode 100644 ai/other_team/img.png create mode 100644 ai/other_team/rione_racoon_ai_beta/index.html create mode 100644 ai/other_team/robodragons/index.html create mode 100644 ai/other_team/tigers/index.html create mode 100644 ai/progress/index.html create mode 100644 ai/rule/index.html create mode 100644 ai/rvo2_local_planner/index.html create mode 100644 ai/setup/index.html create mode 100644 ai/simple_ai/index.html create mode 100644 ai/skill/index.html create mode 100644 ai/tools/index.html create mode 100644 ai/vision/index.html create mode 100644 assets/images/favicon.png create mode 100644 assets/javascripts/bundle.83f73b43.min.js create mode 100644 assets/javascripts/bundle.83f73b43.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.el.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.he.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hy.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.kn.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sa.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.te.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.6ce7567c.min.js create mode 100644 assets/javascripts/workers/search.6ce7567c.min.js.map create mode 100644 assets/stylesheets/main.6f8fc17f.min.css create mode 100644 assets/stylesheets/main.6f8fc17f.min.css.map create mode 100644 assets/stylesheets/palette.06af60db.min.css create mode 100644 assets/stylesheets/palette.06af60db.min.css.map create mode 100644 index.html create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz 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..d6e564c --- /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
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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ではロボットを中心にサンプリングしている
+bmN(stSyIVDNGp?q T_j}4i*X;4vG-hQ@p~=zsNNRf4IPZZ4yDK|sEpksL;uh~c9=7z(2p1+
zCAsHJAi7CPHKe`-s--7?vaWx4l9TB75*=%5C%-Qj+D$KBUJys2jlii$_=Z=qyR`sU
zj9&JoIim-{E$u6j*q39mfpLyuI`%*D?71MOLul4fFj0M$kLqS!S0w qZiGGx%bn%L;}aF{IM84LYM5|%C+V_4tYg>SbsFLw
zoD=vF@?p0Ifr@^y4Xm81_jNFa$?_@tx=BC7PmqlRF=_rR+%`iqG~()FYoe`ze3UdJ
zEZmPw8HHX&3hDruu%&IiBt!T(WVcxQTEO8EzD6v{X>2|GCUzfC(;s
zgB8C)N`gx+v$j=@v?R2YmyD$_;x!+>rht+u=S_}nPuMQ@pFSy0|KRCwYc48BSQt}A
zFoB^A53Mb!`xNoW34Pjoe9lPO6NIxYM@QZkDJemT4s?Edzf~Zy6t3kk)yB%7pQrhs
za$wn?q^kO-sAT~Wj+Y_g^fss5cKhu`^Gi9>k-r~a@^E$cb)w(Pid8G)_B-z=_7xq;
z_lapV!@@FNcI7v{1^
z*E`;^?TnaO7$88($j1zu7Kls+N@RC69e6S^8drV*nl`D!^Bw{S070E
(
zs#MYq;Y^1w5G9&C&4#g8JPn(lI3YD^Jn@Oe+pr41muj<8xT3Aa>X-xUr0;5)rf^H+
zht)uH)*08kbdz*4%L}w@9P=Q?h2LFzUJ;*^Qz)eR3QHv8Xf#rWQ(2|{43cB6Z7ts?
ziQOGkiZUAI#>%ki3-ik2rpAw{z=y5Xasl8T4N&ZKR)2$
zny6!Rr6G|3;DJyW55VoV4Zs09NR%-S$M~71)TV{aw&=qwWSqC0?J!~6^8SW>Z53Rl
zX-gdmf-tY^rP=9%urj$G_r2YSCcw)pDU*I26J#c1ZL8jG?sflC!9T_0z=5*@Ms!?K
zzxMdSya?KIj;(5}RH34MAnPVAsy(GPFRWR8%F&{^nuJNLUYr(BY^GkEFDI|qiYQcB
zh!m0Y>OU~7;znfrOXuajJnb$Q8gBR(J}EK3b(O(MKjuo3=lvq<)tQ1NMes09T+B-G
zk~(5Iz&;CrtGta
+