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