GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
system_main_graph_viewer.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 <format>
11#include <iostream>
12#include <string>
13#include <utility>
14#include <vector>
15
16#include <boost/thread.hpp>
17#include <magic_enum.hpp>
18
19#include "cassert_define.h"
20#include "cmdio_util.h"
22#include "graph_search_const.h"
23#include "node_initializer.h"
24#include "phantomx_mk2.h"
25#include "string_util.h"
26
27
28namespace designlab
29{
30
32 std::unique_ptr<GraphTreeCreator>&& graph_tree_creator,
33 std::unique_ptr<IMapCreator>&& map_creator,
34 const std::shared_ptr<GraphicDataBroker>& broker_ptr,
35 const std::shared_ptr<const ApplicationSettingRecord>& setting_ptr) :
36 graph_tree_creator_ptr_(std::move(graph_tree_creator)),
37 map_creator_ptr_(std::move(map_creator)),
38 broker_ptr_(broker_ptr),
39 setting_ptr_(setting_ptr)
40{
41 assert(graph_tree_creator_ptr_ != nullptr);
42 assert(map_creator_ptr_ != nullptr);
43 assert(broker_ptr_ != nullptr);
44 assert(setting_ptr_ != nullptr);
45
46 CmdIOUtil::OutputTitle("Graph Viewer Mode"); // タイトルを表示する.
47
48 map_state_ = map_creator_ptr_->InitMap();
49
50 broker_ptr_->map_state.SetData(map_state_);
51}
52
53
55{
56 using enum OutputDetail;
57
58 // ノードを初期化する.
59 CmdIOUtil::InfoOutput("Initializes a node.");
60
61 RobotStateNode first_node = NodeInitializer{ Vector3{0.f, 0.f, 30.f}, EulerXYZ {}, HexapodMove::kComUpDown }.InitNode();
62 std::vector<RobotStateNode> graph;
63
64 while (true)
65 {
66 OutputGraphStatus(graph);
67
68 if (graph.size() == 0)
69 {
70 // グラフがない場合,
71
72 CmdIOUtil::Output("No graphs have been generated yet.", kSystem);
73
74 if (CmdIOUtil::InputYesNo("Do you want to create a graph?"))
75 {
76 CreateGraph(first_node, &graph); // グラフを作成する.
77
78 // グラフ木の値を仲介人にセットする.これでGUIにグラフが表示される.
79 broker_ptr_->graph.SetData(graph);
80 }
81 else
82 {
83 // 終了するか質問する.
84 if (CmdIOUtil::InputYesNo("Do you wish to terminate?"))
85 {
86 break;
87 }
88 }
89 }
90 else
91 {
92 // グラフがある場合.
93
94 CmdIOUtil::Output("Displays the operation menu.", kSystem);
95
96 // 操作メニューを表示する.
97
98 // 操作をおこなう関数をラムダ式宣言し,関数ポインタで受け取る vector.
99 std::vector<std::function<void()>> func_list;
100
101 func_list.push_back(
102 [&]()
103 {
104 RobotStateNode selected = SelectNodeByInput(graph);
105 CreateGraph(selected, &graph);
106 broker_ptr_->graph.SetData(graph);
107 });
108
109 func_list.push_back(
110 [&]()
111 {
112 RobotStateNode selected = SelectNodeByInput(graph);
113
119 });
120
121 func_list.push_back(
122 [&]()
123 {
124 graph.clear();
125 broker_ptr_->graph.Clean();
126 CmdIOUtil::Output("グラフを全て削除しました", kSystem);
128 });
129
130
132 CmdIOUtil::Output("操作を選択してください", kSystem);
133 CmdIOUtil::Output(" 0 : ノード選択し,そのノードを親にしてグラフを生成する", kSystem);
134 CmdIOUtil::Output(" 1 : ノード選択して表示する", kSystem);
135 CmdIOUtil::Output(" 2 : グラフを全削除する", kSystem);
136 CmdIOUtil::Output(" 3 : 終了する", kSystem);
137
138 int selected_index =
139 CmdIOUtil::InputInt(0, static_cast<int>(func_list.size()),
140 static_cast<int>(func_list.size()),
141 "整数で操作を選択してください.範囲外の値の場合終了します.");
142
143 // 選択された操作を実行する.
144 if (selected_index < func_list.size())
145 {
146 func_list[selected_index]();
147 }
148 else
149 {
150 if (CmdIOUtil::InputYesNo("終了しますか?"))
151 {
152 break;
153 }
154 }
155 }
156 } // while (true)
157}
158
159
160void SystemMainGraphViewer::CreateGraph(const RobotStateNode parent, std::vector<RobotStateNode>* graph)
161{
162 assert(graph != nullptr);
163
164 using enum OutputDetail;
165
167 CmdIOUtil::Output("グラフ木を作成する", kSystem);
169
170 // グラフ探索をする.
171 RobotStateNode parent_node = parent;
172 parent_node.ChangeLootNode();
173
174 RobotStateNode fake_result_node;
175
176 DividedMapState divided_map;
177 divided_map.Init(map_state_, parent_node.center_of_mass_global_coord);
178
179 GaitPatternGraphTree graph_tree(1000000);
180 graph_tree.Reset();
181 graph_tree.AddNode(parent_node);
182
183
184 graph_tree_creator_ptr_->Init(divided_map);
185
186 stopwatch_.Start();
187
188 const GraphSearchResult result = graph_tree_creator_ptr_->CreateGraphTree(0, 5, &graph_tree);
189
190 stopwatch_.End();
191
192 // グラフ探索の結果を取得する.
193 (*graph).clear();
194
195 for (int i = 0; i < graph_tree.GetGraphSize(); i++)
196 {
197 (*graph).push_back(graph_tree.GetNode(i));
198 }
199
200
201 // グラフ探索の結果を表示する.
203 CmdIOUtil::Output("グラフ探索終了", kSystem);
204 CmdIOUtil::Output(std::format("グラフ探索にかかった時間 : {}", stopwatch_.GetElapsedMilliSecondString()), kSystem);
205
206 CmdIOUtil::Output(std::format("グラフ探索結果 : {}", string_util::EnumToStringRemoveTopK(result.result)), kSystem);
207}
208
209void SystemMainGraphViewer::OutputGraphStatus(const std::vector<RobotStateNode>& graph) const
210{
211 const OutputDetail detail = OutputDetail::kInfo;
212
213 CmdIOUtil::OutputNewLine(1, detail);
215 CmdIOUtil::OutputNewLine(1, detail);
216 CmdIOUtil::Output("Displays the status of the graph.", detail);
217 CmdIOUtil::OutputNewLine(1, detail);
218 CmdIOUtil::FormatOutput(detail, "Number of nodes in the graph : {}", graph.size());
219
220
221 if (graph.size() > 0)
222 {
223 // 深さごとのノード数を記録する.
224
225 std::vector<int> depth_num(GraphSearchConst::kMaxDepth + 1);
226
227 CmdIOUtil::Output(std::format("Maximum depth of graph search : {}", GraphSearchConst::kMaxDepth), detail);
228
229 for (const auto& i : graph)
230 {
231 if (i.depth < depth_num.size())
232 {
233 depth_num[i.depth]++;
234 }
235 }
236
237 // 深さごとのノード数を表示する.
238
239 int depth_cnt = 0;
240
241 for (const auto& i : depth_num)
242 {
243 CmdIOUtil::FormatOutput(detail, "- depth {} : {}", depth_cnt, i);
244 depth_cnt++;
245 }
246 }
247 else
248 {
249 CmdIOUtil::Output("グラフが空なので,深さごとのノード数を表示できません.", detail);
250 }
251
252 CmdIOUtil::OutputNewLine(1, detail);
254 CmdIOUtil::OutputNewLine(1, detail);
255}
256
257RobotStateNode SystemMainGraphViewer::SelectNodeByInput(
258 const std::vector<RobotStateNode>& graph) const
259{
260 using enum OutputDetail;
261
263 CmdIOUtil::Output("ノードを選択する", kSystem);
264
265 if (graph.size() == 0)
266 {
267 CmdIOUtil::Output("グラフが空なので,初期状態のノードを返す", kSystem);
268
269 NodeInitializer node_initializer{ Vector3{0.f, 0.f, 30.f}, EulerXYZ(), HexapodMove::kNone };
270 RobotStateNode first_node = node_initializer.InitNode();
271
272 return first_node;
273 }
274 else
275 {
276 CmdIOUtil::Output("グラフの中から1つのノードを選択してください.", kSystem);
277
278 // ノードを選択する.
279 int selected_node_index = CmdIOUtil::InputInt(0,
280 static_cast<int>(graph.size()) - 1,
281 0,
282 "整数でノードを選択してください.");
283
284 CmdIOUtil::Output(std::format("選択されたノード,{}番を親にします.",
285 selected_node_index), kSystem);
286
287 return graph[selected_node_index];
288 }
289}
290
291} // namespace designlab
static void Output(const std::string &str, OutputDetail detail)
コマンドラインに文字を出力する関数. SetOutputLimit() で設定した出力の許可範囲内であれば出力される. 必ず SetOutputLimit() を呼び出してから使うこと.
static int InputInt(int min, int max, int default_num, const std::string &str="Please enter an integer.")
整数を入力させる関数. 出力される文字列は,必ず 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 InfoOutput(const std::string &str)
コマンドラインに文字を出力する関数.Info用の出力.
Definition cmdio_util.h:84
static void FormatOutput(OutputDetail detail, const std::format_string< Args... > str, Args &&... args)
コマンドラインに文字を出力する関数. SetOutputLimit() で設定した出力の許可範囲内であれば出力される. 必ず SetOutputLimit() を呼び出してから使うこと.
Definition cmdio_util.h:117
マップを格子状に分割して管理するクラス.
void Init(const MapState &map_state, const Vector3 global_robot_com)
マップのデータを初期化する. ロボットの重心座標を中心にマップのデータを格子状に分割し, その中に存在する脚設置可能点を集める.
RobotStateNode 構造体をノードとする木構造のグラフのクラス.
static const int kMaxDepth
グラフ探索の最大深さ.
ノードの初期化を行うクラス. シミュレーション時にノードの初期値を設定するために使用する.
std::string GetElapsedMilliSecondString() const
経過時間をミリ秒で表した文字列を取得する.
Definition stopwatch.cpp:85
void End()
計測終了時にこの関数を呼ぶ.
Definition stopwatch.cpp:32
void Start()
計測開始にこの関数を呼ぶ. リセット処理などを呼ぶ必要なしで,再度計測できる.
Definition stopwatch.cpp:26
void Main() override
主要な処理を行う関数.
SystemMainGraphViewer(std::unique_ptr< GraphTreeCreator > &&graph_tree_creator, std::unique_ptr< IMapCreator > &&map_creator, const std::shared_ptr< GraphicDataBroker > &broker_ptr, const std::shared_ptr< const ApplicationSettingRecord > &setting_ptr)
std::string EnumToStringRemoveTopK(const T &enum_value)
enumを文字列に変換する関数. Google C++ coding style だと enumの要素は 先頭にkをつけてキャメルケースで書くことが推奨されている. 例えば,
Definition string_util.h:54
OutputDetail
コマンドラインに文字を出力する際に,その詳細を指定するための列挙体.
@ kInfo
優先度低めの情報.
@ kSystem
システムメッセージ,常に出力する.
@ kNone
何も動作をしない.
@ kComUpDown
重心の上下移動.
Definition com_type.h:24
XYZオイラー角を用いた回転を表す構造体.
Definition math_euler.h:33
グラフ探索の結果を表す構造体.
enums::Result result
成功か失敗か.
グラフ構造のためのノード(頂点).旧名 LNODE
void ChangeLootNode()
自身を根ノードに変更する関数. depthを0に,parent_numを-1に初期化する.
Vector3 center_of_mass_global_coord
[4 * 3 = 12byte] グローバル座標系における重心の位置.旧名 GCOM
std::string ToString() const
ノードの情報を文字列に変換する関数. デバッグ用に詳細な情報を出力する.
3次元の位置ベクトルを表す構造体.