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