GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
system_main_simulation.cpp
[詳解]
1
3
4// Copyright(c) 2023-2025 Design Engineering Laboratory, Saitama University
5// Released under the MIT license
6// https://opensource.org/licenses/mit-license.php
7
9
10#include <boost/thread.hpp>
11#include <magic_enum.hpp>
12#include <utility>
13
14#include "cassert_define.h"
15#include "cmdio_util.h"
16#include "dead_lock_checker.h"
18#include "string_util.h"
19
20namespace designlab {
21
23 std::unique_ptr<IGaitPatternGenerator>&& gait_pattern_generator_ptr,
24 std::unique_ptr<IMapCreator>&& map_creator_ptr,
25 std::unique_ptr<ISimulationEndChecker>&& simulation_end_checker_ptr,
26 std::unique_ptr<IRobotOperator>&& robot_operator_ptr,
27 std::unique_ptr<NodeInitializer>&& node_initializer_ptr,
28 const std::shared_ptr<GraphicDataBroker>& broker_ptr,
29 const std::shared_ptr<const ApplicationSettingRecord>& setting_ptr,
30 const std::shared_ptr<ResultFileExporter>& result_exporter_ptr)
31 : gait_pattern_generator_ptr_(std::move(gait_pattern_generator_ptr)),
32 map_creator_ptr_(std::move(map_creator_ptr)),
33 simulation_end_checker_ptr_(std::move(simulation_end_checker_ptr)),
34 robot_operator_ptr_(std::move(robot_operator_ptr)),
35 node_initializer_ptr_(std::move(node_initializer_ptr)),
36 broker_ptr_(broker_ptr),
37 setting_ptr_(setting_ptr),
38 result_exporter_ptr_(result_exporter_ptr) {
39 assert(gait_pattern_generator_ptr_ != nullptr);
40 assert(map_creator_ptr_ != nullptr);
41 assert(simulation_end_checker_ptr_ != nullptr);
42 assert(robot_operator_ptr_ != nullptr);
43 assert(broker_ptr_ != nullptr);
44 assert(setting_ptr_ != nullptr);
45
46 // 結果をファイルに出力するクラスを初期化する.
47 result_exporter_ptr_->CreateRootDirectory();
48
49 // マップを生成する.
50 map_state_ = map_creator_ptr_->InitMap();
51
52 // 仲介人にマップを渡す.
53 broker_ptr_->map_state.SetData(map_state_);
54}
55
57 using enum OutputDetail;
58 using enum enums::Result;
60
61 // コマンドラインにタイトルを表示する.
62 cmdio::OutputTitle("Simulation mode");
63 OutputSetting(); // コマンドラインに設定を表示する.
64
65 DeadLockChecker dead_lock_checker;
66
67 // シミュレーションを行う回数分ループする.
68 for (int i = 0; i < kSimulationNum; ++i) {
69 // 現在のノードの状態を格納する変数.
70 RobotStateNode current_node = node_initializer_ptr_->InitNode();
71
72 RobotOperation operation =
73 robot_operator_ptr_->Init(); // 目標地点を決定する.
74
75 // シミュレーションの結果を格納する変数.
77
78 record.graph_search_result_recorder.push_back(
79 GraphSearchResultRecord{current_node, 0, {kSuccess, ""}});
80
81 cmdio::OutputF(kSystem, "Start simulation {} times", i + 1);
82 cmdio::SpacedOutputF(kInfo, "[Initial node state]\n{}",
83 current_node.ToString());
84
85 if (setting_ptr_->do_step_execution_each_simulation) {
87
88 if (!cmdio::InputYesNo("Do you want to start the simulation?")) {
89 break;
90 }
91 }
92
93 if (setting_ptr_->do_gui_display) {
94 // グラフィックが有効ならば,仲介人に最初のノードの状態を通達する.
95 broker_ptr_->graph.PushBack(current_node);
96 }
97
98 // 最大歩容生成回数分までループする.
99 for (int j = 0; j < kGaitPatternGenerationLimit; ++j) {
100 current_node.ChangeLootNode();
101
102 operation =
103 robot_operator_ptr_->Update(current_node); // 目標地点を更新する.
104
105 timer_.Start(); // タイマースタート.
106
107 RobotStateNode result_node; // グラフ探索の結果を格納する変数.
108
109 // グラフ探索を行う.
110 const GraphSearchResult result_state =
111 gait_pattern_generator_ptr_->GetNextNodeByGraphSearch(
112 current_node, map_state_, operation, &result_node);
113
114 timer_.End(); // タイマーストップ.
115
116 // ノード,計算時間,結果を格納する.
118 result_node, timer_.GetElapsedMilliSecond(), result_state});
119
120 // グラフ探索に失敗.
121 if (result_state.result != kSuccess) {
122 // シミュレーションの結果を格納する変数を失敗に更新する.
123 record.simulation_result =
125
127 kSystem,
128 "Simulation failed. SimulationResult = {}/ GraphSearch = {}",
129 EnumToStringRemoveTopK(record.simulation_result),
130 result_state.ToString());
131
132 // 次の歩容が生成できなかったら,このループを抜け,
133 // 次のシミュレーションへ進む.
134 break;
135 }
136
137 // 次の歩容が生成できているならば,ノードを更新する.
138 current_node = result_node;
139
140 if (setting_ptr_->do_gui_display) {
141 // グラフィックが有効ならば仲介人に結果を通達する.
142 broker_ptr_->graph.PushBack(current_node);
143 }
144
146 kInfo, "[ Simulation {} times / Gait generation {} times ]\n{}",
147 i + 1, j + 1, current_node.ToString());
149
150 // 動作チェッカーにもノードを通達する.
151 dead_lock_checker.AddNode(current_node);
152
153 if (dead_lock_checker.IsDeadLock()) {
154 // 動作がループして失敗した時.
155 // シミュレーションの結果を格納する変数を失敗に更新する.
156
157 record.simulation_result =
159
161 kSystem,
162 "Simulation failed. SimulationResult = {} / GraphSearch = {}",
163 EnumToStringRemoveTopK(record.simulation_result),
164 result_state.ToString());
165
166 // 動作がループしてしまっているならば,
167 // ループを一つ抜け,次のシミュレーションへ進む.
168 break;
169 }
170
171 // 成功時の処理.
172 if (simulation_end_checker_ptr_->IsEnd(current_node)) {
173 // シミュレーションの結果を格納する変数を成功に更新する.
175
177 "The simulation was successful. SimulationResult = {}",
178 EnumToStringRemoveTopK(record.simulation_result));
179
180 break; // 成功したら,このループを抜け,次のシミュレーションへ進む.
181 }
182
183 // forの最後のループであるならば,失敗したことを通達する.
184 if (j == kGaitPatternGenerationLimit - 1) {
185 // シミュレーションの結果を格納する変数を失敗に更新する.
186 record.simulation_result =
188
189 cmdio::OutputF(kSystem, "Simulation failed. SimulationResult = {}",
190 EnumToStringRemoveTopK(record.simulation_result));
191 }
192
193 // ステップ実行にしているならば,ここで一時停止する.
194 if (setting_ptr_->do_step_execution_each_gait) {
196 cmdio::WaitAnyKey("Generates the next step by key input");
197 }
198 } // 歩容生成のループ終了.
199
200 record.map_state =
201 map_state_; // 結果を格納する変数にマップの状態を格納する.
202 result_exporter_ptr_->PushSimulationResult(record); // 結果を追加する.
203
204 // 仲介人にシミュレーション終了を通達する.
205 broker_ptr_->simulation_end_index.PushBack(broker_ptr_->graph.GetSize() -
206 1);
207
211 } // シミュレーションのループ終了
212
213 // シミュレーションの結果を全てファイルに出力する.
214 if (cmdio::InputYesNo("Do you want to output results?")) {
215 result_exporter_ptr_->Export();
216 }
217
218 cmdio::SpacedOutput("Exit Simulation", kSystem);
219}
220
221void SystemMainSimulation::OutputSetting() const {
222 using enum OutputDetail;
223
224 cmdio::Output("[Setting]", kSystem);
226
227 if (setting_ptr_->do_cmd_output) {
228 cmdio::Output("・Output to command line.", kSystem);
229
230 const std::string output_str =
231 magic_enum::enum_name(setting_ptr_->cmd_output_detail).data();
232
234 kSystem,
235 "  ・Only those with a priority of {} or higher will be output.",
236 output_str);
237 } else {
238 const std::string output_str = magic_enum::enum_name(kSystem).data();
239
241 "・No output to the command line. (The exception "
242 "is the output of the one whose priority is {}.",
243 output_str);
244 }
245
247
248 if (setting_ptr_->do_step_execution_each_simulation) {
249 cmdio::Output("・Step through the simulation.", kSystem);
250 } else {
251 cmdio::Output("・Does not step through the simulation.", kSystem);
252 }
253
255
256 if (setting_ptr_->do_step_execution_each_gait) {
257 cmdio::Output("・Step through each step.", kSystem);
258 } else {
259 cmdio::Output("・Does not step through each step.", kSystem);
260 }
261
263
264 if (setting_ptr_->do_gui_display) {
265 cmdio::Output("・Display GUI.", kSystem);
266 } else {
267 cmdio::Output("・Do not display GUI.", kSystem);
268 }
269
273}
274
275} // namespace designlab
動作のループを感知するクラス.
void AddNode(const RobotStateNode &node)
ロボットが行った動作を追加する.上限数を超えたら,古いものから削除する.
bool IsDeadLock() const
直近に行った動作を比較して,ロボットが正しく動作できているか判断する.
double GetElapsedMilliSecond() const
計測結果をミリ秒で取得. start()と end()を呼び出してからこの関数を呼ぶ.
Definition stopwatch.cpp:40
void End()
計測終了時にこの関数を呼ぶ.
Definition stopwatch.cpp:24
void Start()
計測開始にこの関数を呼ぶ. リセット処理などを呼ぶ必要なしで,再度計測できる.
Definition stopwatch.cpp:22
SystemMainSimulation()=delete
デフォルトコンストラクタは禁止.
void Main() override
いままで int mainで行われた処理をまとめたもの. 目標地点へ着くか,歩容計画に失敗した場合に,シミュレーションを終える. また,規定の回数シミュレーションしたら終了する.
void OutputF(OutputDetail detail, const std::format_string< Args... > str, Args &&... args)
コマンドラインに文字を出力する関数, format した文字列を出力する. SetOutputLimit() で設定した出力の許可範囲内であれば出力される.
Definition cmdio_util.h:91
void SpacedOutput(const std::string &str, OutputDetail detail)
コマンドラインに文字を出力する関数. 前と後ろに改行を挿入する.
void OutputHorizontalLine(const std::string &line_visual, OutputDetail detail)
コマンドラインに水平線を出力する関数.
void WaitAnyKey(const std::string &str="Waiting for input.")
入力待ちをする関数. 出力される文字列は, 必ず OutputDetail::kSystem で出力される.
void OutputNewLine(int num, OutputDetail detail)
コマンドラインで改行をする関数.
void OutputTitle(const std::string &title_name, bool output_copy_right=false)
コマンドラインにこのソフトのタイトルを出力する関数. 出力される文字列は,必ず OutputDetail::kSystem で出力される.
void SpacedOutputF(OutputDetail detail, const std::format_string< Args... > str, Args &&... args)
コマンドラインに文字を出力する関数, format した文字列を出力する. SetOutputLimit 関数で設定した出力の許可範囲内であれば出力される.
Definition cmdio_util.h:148
void Output(const std::string &str, OutputDetail detail)
コマンドラインに文字を出力する関数. SetOutputLimit 関数で設定した出力の許可範囲内であれば出力される.
bool InputYesNo(const std::string &str="Are you sure?")
yesかnoを入力させる関数.返り値で yes なら true, no なら false を返す. 出力される文字列は,必ず OutputDetail::kSystem で出力される.
Result
成功か失敗かを表す列挙型.
@ kFailureByNodeLimitExceeded
ノード数の上限に達したため,シミュレーションに失敗した.
@ kFailureByLoopMotion
動作がループしてしまったため,シミュレーションに失敗した.
@ kSuccess
目標座標,姿勢を満たし,シミュレーションに成功した.
@ kFailureByGraphSearch
グラフ探索に失敗しため,シミュレーションに失敗した.
std::string EnumToStringRemoveTopK(const T &enum_value)
enumを文字列に変換する関数. Google C++ coding style だと enumの要素は 先頭にkをつけてキャメルケースで書くことが推奨されている....
Definition string_util.h:52
OutputDetail
コマンドラインに文字を出力する際に,その詳細を指定するための列挙体.
@ kInfo
優先度低めの情報.
@ kSystem
システムメッセージ,常に出力する.
Definition com_type.h:21
グラフ探索の結果を表す構造体.
enums::Result result
成功か失敗か.
グラフ探索の結果を格納する構造体.
探索において目標となる座標や角度,評価する値についてまとめた構造体.
グラフ構造のためのノード(頂点).
void ChangeLootNode()
自身を根ノードに変更する関数. depthを0に,parent_numを-1に初期化する.
std::string ToString() const
ノードの情報を文字列に変換する関数. デバッグ用に詳細な情報を出力する.
シミュレーションの結果を格納する構造体.
enums::SimulationResult simulation_result
シミュレーション全体の結果.
std::vector< GraphSearchResultRecord > graph_search_result_recorder
MapState map_state
最新の地面の状態.