GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
graphic_main_display_model.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 <numbers>
11
13#include "camera_dragger.h"
14#include "dxlib_camera.h"
15#include "dxlib_gui_camera.h"
18#include "dxlib_util.h"
20#include "keyboard.h"
22#include "map_renderer.h"
23#include "math_util.h"
24#include "node_initializer.h"
25#include "phantomx_mk2_const.h"
27#include "toml_file_importer.h"
28#include "world_grid_renderer.h"
29
30namespace designlab {
31
33 const std::shared_ptr<const IHexapodCoordinateConverter>& converter_ptr,
34 const std::shared_ptr<const IHexapodJointCalculator>& calculator_ptr,
35 const std::shared_ptr<const IHexapodPostureValidator>& checker_ptr,
36 const std::shared_ptr<const ApplicationSettingRecord>& setting_ptr)
37 : mouse_ptr_(std::make_shared<Mouse>()),
38 calculator_ptr_(calculator_ptr),
39 converter_ptr_(converter_ptr) {
40 NodeInitializer node_initializer{Vector3{0.f, 0.f, 30.f}, EulerXYZ(),
42 robot_ = node_initializer.InitNode();
43
44 TomlFileImporter<SimulationSettingRecord> simulation_setting_importer;
45 const SimulationSettingRecord simulation_setting_record =
46 simulation_setting_importer.ImportOrUseDefault(
47 "./simulation_condition/simulation_setting.toml");
48 auto map_creator = MapCreatorSelector{}.Select(simulation_setting_record);
49
50 map_state_ = map_creator->InitMap();
51 divided_map_state_.Init(map_state_, {});
52
53 const auto camera = std::make_shared<DxlibCamera>();
54 const auto camera_gui = std::make_shared<DxlibGuiCamera>(
55 setting_ptr->window_size_x, setting_ptr->window_size_y, camera);
56 camera_gui->SetPos(10, 10, kDxlibGuiAnchorLeftTop, true);
57
58 const auto camera_dragger = std::make_shared<CameraDragger>(camera);
59
60 const auto camera_parameter_gui =
61 std::make_shared<DxlibGuiCameraParameterDisplayer>(
62 setting_ptr->window_size_x, setting_ptr->window_size_y, camera);
63 camera_parameter_gui->SetPos(10, 10, kDxlibGuiAnchorLeftTop, true);
64 camera_parameter_gui->SetVisible(false);
65
66 const auto node_display_gui = std::make_shared<DxlibGuiNodeDisplayer>(
67 setting_ptr->window_size_x, setting_ptr->window_size_y, converter_ptr,
68 calculator_ptr, checker_ptr);
69 node_display_gui->SetPos(setting_ptr->window_size_x - 10, 10,
71
72 const auto [hexapod_renderer, hexapod_node_setter] =
73 HexapodRendererBuilder::Build(converter_ptr_, calculator_ptr_,
74 setting_ptr->gui_display_quality);
75
76 const auto map_renderer = std::make_shared<MapRenderer>();
77 map_renderer->SetMapState(map_state_);
78 map_renderer->SetNode(robot_);
79
80 const auto world_grid_renderer = std::make_shared<WorldGridRenderer>();
81
82 const auto approximated_motion_range_render =
83 std::make_shared<ApproximatedMotionRangeRender>(checker_ptr,
84 converter_ptr);
85
86 gui_updater_.Register(camera_parameter_gui, 1);
87 gui_updater_.Register(camera_dragger, 0);
88 gui_updater_.Register(node_display_gui, 1);
89 gui_updater_.Register(camera_gui, 1);
90
91 gui_updater_.OpenTerminal();
92
93 node_setter_group_.Register(approximated_motion_range_render);
94 node_setter_group_.Register(camera_gui);
95 node_setter_group_.Register(node_display_gui);
96 node_setter_group_.Register(hexapod_node_setter);
97 node_setter_group_.Register(map_renderer);
98
99 // render_group_.Register(approximated_motion_range_render);
100 render_group_.Register(hexapod_renderer);
101 render_group_.Register(map_renderer);
102 render_group_.Register(world_grid_renderer);
103}
104
106 assert(mouse_ptr_ != nullptr);
107
108 mouse_ptr_->Update();
109
110 if (keyboard_.GetPressingCount(KEY_INPUT_LSHIFT) > 0 ||
111 keyboard_.GetPressingCount(KEY_INPUT_RSHIFT) > 0) {
112 MoveBody();
113 } else {
114 MoveLeg();
115 }
116
117 gui_updater_.Activate(mouse_ptr_);
118
119 node_setter_group_.SetNode(robot_);
120
121 keyboard_.Update();
122
123 return true;
124}
125
127 render_group_.Draw();
128
129 gui_updater_.Draw();
130}
131
132void GraphicMainDisplayModel::MoveBody() {
133 const float kComSpeed = 1.1f;
134
135 if (keyboard_.GetPressingCount(KEY_INPUT_Q) > 0) {
136 Vector3 com =
138 RotateVector3(Vector3::GetUpVec() * kComSpeed, robot_.posture);
139
140 robot_.ChangeGlobalCenterOfMass(com, false);
141 } else if (keyboard_.GetPressingCount(KEY_INPUT_E) > 0) {
142 Vector3 com =
144 RotateVector3(Vector3::GetUpVec() * -kComSpeed, robot_.posture);
145
146 robot_.ChangeGlobalCenterOfMass(com, false);
147 } else if (keyboard_.GetPressingCount(KEY_INPUT_A) > 0) {
148 Vector3 com =
150 RotateVector3(Vector3::GetLeftVec() * kComSpeed, robot_.posture);
151
152 robot_.ChangeGlobalCenterOfMass(com, false);
153 } else if (keyboard_.GetPressingCount(KEY_INPUT_D) > 0) {
154 Vector3 com =
156 RotateVector3(Vector3::GetLeftVec() * -kComSpeed, robot_.posture);
157
158 robot_.ChangeGlobalCenterOfMass(com, false);
159 } else if (keyboard_.GetPressingCount(KEY_INPUT_W) > 0) {
160 Vector3 com =
162 RotateVector3(Vector3::GetFrontVec() * kComSpeed, robot_.posture);
163
164 robot_.ChangeGlobalCenterOfMass(com, false);
165 } else if (keyboard_.GetPressingCount(KEY_INPUT_S) > 0) {
166 Vector3 com =
168 RotateVector3(Vector3::GetFrontVec() * -kComSpeed, robot_.posture);
169
170 robot_.ChangeGlobalCenterOfMass(com, false);
171 } else if (keyboard_.GetPressingCount(KEY_INPUT_R) > 0) {
172 float angle_speed = kComSpeed / 360.0f * 2.f * std::numbers::pi_v<float>;
173
174 if (keyboard_.GetPressingCount(KEY_INPUT_I) > 0) {
175 angle_speed *= -1.f;
176 }
177
178 Quaternion rot =
180 robot_.posture;
181
182 robot_.ChangePosture(converter_ptr_, rot);
183 } else if (keyboard_.GetPressingCount(KEY_INPUT_P) > 0) {
184 float angle_speed = kComSpeed / 360.0f * 2.f * std::numbers::pi_v<float>;
185
186 if (keyboard_.GetPressingCount(KEY_INPUT_I) > 0) {
187 angle_speed *= -1.f;
188 }
189
190 Quaternion rot =
192 robot_.posture;
193
194 robot_.ChangePosture(converter_ptr_, rot);
195 } else if (keyboard_.GetPressingCount(KEY_INPUT_Y) > 0) {
196 float angle_speed = kComSpeed / 360.0f * 2.f * std::numbers::pi_v<float>;
197
198 if (keyboard_.GetPressingCount(KEY_INPUT_I) > 0) {
199 angle_speed *= -1.f;
200 }
201
202 Quaternion rot =
204 robot_.posture;
205
206 robot_.ChangePosture(converter_ptr_, rot);
207 }
208}
209
210void GraphicMainDisplayModel::MoveLeg() {
211 const float kSpeed = 1;
212 const float kAngleSpeed = 0.01f;
213
214 for (int i = 0; i < HexapodConst::kLegNum; i++) {
215 if (keyboard_.GetPressingCount(KEY_INPUT_1 + i) > 0) {
216 if (keyboard_.GetPressingCount(KEY_INPUT_Q) > 0) {
217 robot_.leg_pos[i].z += kSpeed;
218 } else if (keyboard_.GetPressingCount(KEY_INPUT_E) > 0) {
219 robot_.leg_pos[i].z -= kSpeed;
220 } else if (keyboard_.GetPressingCount(KEY_INPUT_A) > 0) {
221 robot_.leg_pos[i].y += kSpeed;
222 } else if (keyboard_.GetPressingCount(KEY_INPUT_D) > 0) {
223 robot_.leg_pos[i].y -= kSpeed;
224 } else if (keyboard_.GetPressingCount(KEY_INPUT_W) > 0) {
225 robot_.leg_pos[i].x += kSpeed;
226 } else if (keyboard_.GetPressingCount(KEY_INPUT_S) > 0) {
227 robot_.leg_pos[i].x -= kSpeed;
228 } else if (keyboard_.GetPressingCount(KEY_INPUT_M) == 1) {
229 Vector3 global = converter_ptr_->ConvertLegToGlobalCoordinate(
231 robot_.posture, true);
232
233 int map_x = divided_map_state_.GetDividedMapIndexX(global.x);
234 int map_y = divided_map_state_.GetDividedMapIndexY(global.y);
235
236 if (keyboard_.GetPressingCount(KEY_INPUT_UP) > 0) {
237 map_x++;
238 } else if (keyboard_.GetPressingCount(KEY_INPUT_DOWN) > 0) {
239 map_x--;
240 }
241 if (keyboard_.GetPressingCount(KEY_INPUT_LEFT) > 0) {
242 map_y++;
243 } else if (keyboard_.GetPressingCount(KEY_INPUT_RIGHT) > 0) {
244 map_y--;
245 }
246
247 const auto map_pos =
248 divided_map_state_.GetPointNum(map_x, map_y)
249 .and_then([&](int pos_num) {
250 return divided_map_state_.GetPointPos(
251 map_x, map_y, divided_map_tile_index_ % pos_num);
252 });
253 if (!map_pos) {
254 continue;
255 }
256
257 ++divided_map_tile_index_;
258
259 robot_.leg_pos[i] = converter_ptr_->ConvertGlobalToLegCoordinate(
260 *map_pos, i, robot_.center_of_mass_global_coord, robot_.posture,
261 true);
262 }
263
264 if (keyboard_.GetPressingCount(KEY_INPUT_C) > 0 ||
265 keyboard_.GetPressingCount(KEY_INPUT_F) > 0 ||
266 keyboard_.GetPressingCount(KEY_INPUT_T) > 0) {
267 std::array<HexapodJointState, HexapodConst::kLegNum> res =
268 calculator_ptr_->CalculateAllJointState(robot_);
269
270 float coxa = res[i].joint_angle[0];
271 float femur = res[i].joint_angle[1];
272 float tibia = res[i].joint_angle[2];
273
274 if (keyboard_.GetPressingCount(KEY_INPUT_C) > 0) {
275 const float speed = keyboard_.GetPressingCount(KEY_INPUT_I) > 0
276 ? kAngleSpeed
277 : kAngleSpeed * -1.f;
278
279 coxa += speed;
280
283 coxa
286 : coxa;
287
290 coxa
293 : coxa;
294 } else if (keyboard_.GetPressingCount(KEY_INPUT_F) > 0) {
295 const float speed = keyboard_.GetPressingCount(KEY_INPUT_I) > 0
296 ? kAngleSpeed
297 : kAngleSpeed * -1.f;
298
299 femur += speed;
300
301 femur = (femur + tibia - std::numbers::pi_v<float>) > 0
302 ? femur - speed
303 : femur;
304 femur = PhantomXMkIIConst::kFemurAngleMax <= femur
306 : femur;
307 femur = PhantomXMkIIConst::kFemurAngleMin >= femur
309 : femur;
310 } else if (keyboard_.GetPressingCount(KEY_INPUT_T) > 0) {
311 float speed = keyboard_.GetPressingCount(KEY_INPUT_I) > 0
312 ? kAngleSpeed
313 : kAngleSpeed * -1.f;
314 tibia += speed;
315 tibia = (femur + tibia - std::numbers::pi_v<float>) > 0
316 ? tibia - speed
317 : tibia;
318 tibia = PhantomXMkIIConst::kTibiaAngleMax <= tibia
320 : tibia;
321 tibia = PhantomXMkIIConst::kTibiaAngleMin >= tibia
323 : tibia;
324 }
325
326 Vector3 leg_pos;
327
328 leg_pos += Vector3{PhantomXMkIIConst::kCoxaLength * cos(coxa),
329 PhantomXMkIIConst::kCoxaLength * sin(coxa), 0};
330
331 leg_pos +=
332 Vector3{PhantomXMkIIConst::kFemurLength * cos(coxa) * cos(femur),
333 PhantomXMkIIConst::kFemurLength * sin(coxa) * cos(femur),
335
336 leg_pos += Vector3{
337 PhantomXMkIIConst::kTibiaLength * cos(coxa) * cos(femur + tibia),
338 PhantomXMkIIConst::kTibiaLength * sin(coxa) * cos(femur + tibia),
339 PhantomXMkIIConst::kTibiaLength * sin(femur + tibia)};
340
341 robot_.leg_pos[i] = leg_pos;
342 }
343 }
344 }
345}
346
347} // namespace designlab
constexpr int GetDividedMapIndexX(const float pos_x) const noexcept
指定した座標を DividedMap のインデックスに変換する. 範囲外の値を指定した場合でも,値を丸めずに返す. そのため,IsInMap で範囲内に存在するかどうかを確認する必要がある.
nostd::expected< Vector3, std::string > GetPointPos(int x_index, int y_index, int divided_map_index) const
格子状に切り分けられたマップから,脚設置可能点の実際の座標を取得する. 範囲外の値を指定した場合は, unexpected を返す.
void Init(const MapState &map_state, const Vector3 global_robot_com)
マップのデータを初期化する. ロボットの重心座標を中心にマップのデータを格子状に分割し, その中に存在する脚設置可能点を集める.
constexpr int GetDividedMapIndexY(const float pos_y) const noexcept
指定した座標を DividedMap のインデックスに変換する. 範囲外の値を指定した場合でも,値を丸めずに返す. そのため,IsInMap で範囲内に存在するかどうかを確認する必要がある.
nostd::expected< int, std::string > GetPointNum(int x_index, int y_index) const
格子状に切り分けられたマップから,脚設置可能点の数を取得する. 範囲外の値を指定した場合は, unexpected を返す.
void Register(const std::shared_ptr< IDxlib3dRenderer > &renderer)
3D描画を行うクラスを登録する.
void Draw() const
登録されているクラスの draw 関数を呼ぶ. また,Zソートを行う.
void Register(const std::shared_ptr< T > &gui_ptr, int priority)
UpdateとDrawを行うGUIを登録する. IDxlibClickableまたは,IDxlibDraggable, IDxlibWheelHandlerを継承している場合は,...
void OpenTerminal()
Terminalを開く. 他のGUIをRegisterした後に呼び出すこと. 2回目以降の呼び出しは無視される. また,Terminalは最も優先度が高い.
void Draw() const
登録済みのGUIのDraw関数を実行する.
void Activate(const std::shared_ptr< const Mouse > &mouse_ptr)
GUIのUpdate関数を実行し,クリック,ドラッグなどの判定を行う. 優先度の高いものから順に各種判定を行う.
void Register(const std::shared_ptr< IDxlibNodeSetter > &setter)
ノードの設定を行うクラスを登録する.
void SetNode(const RobotStateNode &node)
登録済みの全てのクラスに対してノードの設定を行う.
void Draw() const override
描画を行う. ここでは描画系の処理のみを行い内部のデータを 更新しないため const を付けている.
bool Update() override
描画画面の更新を行う.純粋仮想関数のため, 継承先では必ず override する必要がある.
GraphicMainDisplayModel(const std::shared_ptr< const IHexapodCoordinateConverter > &converter_ptr, const std::shared_ptr< const IHexapodJointCalculator > &calculator_ptr, const std::shared_ptr< const IHexapodPostureValidator > &checker_ptr, const std::shared_ptr< const ApplicationSettingRecord > &setting_ptr)
static constexpr int kLegNum
static std::tuple< std::shared_ptr< IDxlib3dRenderer >, std::shared_ptr< IDxlibNodeSetter > > Build(const std::shared_ptr< const IHexapodCoordinateConverter > &converter_ptr, const std::shared_ptr< const IHexapodJointCalculator > &calculator_ptr, DisplayQuality display_quality)
HexapodRendererクラスのインスタンスを作成する. static関数なので,HexapodRendererBuilder::Build()と呼び出す.
void Update()
キー入力を更新する. これを毎フレーム実行しないと,キー入力を取得できない.
Definition keyboard.cpp:25
int GetPressingCount(const int key_code) const
keyCodeのキーが押されているフレーム数を取得する.
Definition keyboard.cpp:58
マップを生成するクラスを生成するクラス.
std::unique_ptr< IMapCreator > Select(const SimulationSettingRecord &record) const
マップを生成するクラスを生成する.
Dxlibでマウス入力を取得するクラス.
Definition mouse.h:21
ノードの初期化を行うクラス. シミュレーション時にノードの初期値を設定するために使用する.
static constexpr float kFemurLength
第2関節部の長さ[mm].
static constexpr float kTibiaAngleMax
static constexpr float kFemurAngleMin
第2関節の可動範囲の最大値[rad].詳しくは referenceフォルダ参照.
static constexpr float kFemurAngleMax
第2関節の可動範囲の最小値[rad].詳しくは referenceフォルダ参照.
static constexpr float kCoxaLength
第1関節部の長さ[mm].
static constexpr float kCoxaAngleMin
第1関節の可動範囲の最大値[rad].詳しくは referenceフォルダ参照.
static constexpr float kTibiaAngleMin
第2関節の可動範囲の最大値[rad].詳しくは referenceフォルダ参照.
static constexpr float kTibiaLength
第3関節部の長さ[mm].
static constexpr std::array< float, kPhantomXLegNum > kCoxaDefaultAngle
第1関節の初期角度[rad]
static constexpr float kCoxaAngleMax
第2関節の可動範囲の最小値[rad].詳しくは referenceフォルダ参照.
tomlファイルを読み込んで構造体に変換するテンプレートクラス.
T ImportOrUseDefault(const std::string &file_path) const
指定したファイルパスのファイルを読み込み,構造体に変換する. 読込に失敗した場合は,デフォルトの構造体を返す. また,読込に失敗した場合には, デフォルトの構造体をファイルに出力するかどうかをユーザに問...
Vector3 RotateVector3(const Vector3 &vec, const EulerXYZ &rot)
回転させたベクトルを返す.三角関数の処理が多く重たいので注意.
constexpr unsigned int kDxlibGuiAnchorRightTop
@ kNone
何も動作をしない.
constexpr unsigned int kDxlibGuiAnchorLeftTop
Definition com_type.h:21
XYZオイラー角を用いた回転を表す構造体.
Definition math_euler.h:30
static Quaternion MakeByAngleAxis(float rad_angle, const Vector3 &axis)
回転軸と回転角からクォータニオンを作成する. q = cos(θ/2) * w + sin(θ/2) * { v.x + v.y + v.z } となる. ノルムは必ず1になる.
std::array< Vector3, HexapodConst::kLegNum > leg_pos
[4 * 3 * 6 = 72 byte] 脚先の座標.(coxa(脚の付け根)を原点とする)
Vector3 center_of_mass_global_coord
[4 * 3 = 12byte] グローバル座標系における重心の位置.旧名 GCOM
void ChangePosture(const std::shared_ptr< const IHexapodCoordinateConverter > &converter_ptr, const Quaternion &new_posture)
クォータニオンを変更し,胴体を回転させる関数.
Quaternion posture
[4 * 4 = 16byte] 姿勢を表すクォータニオン.
std::array< Vector3, HexapodConst::kLegNum > leg_reference_pos
void ChangeGlobalCenterOfMass(const Vector3 &new_com, bool do_change_leg_base_pos)
重心位置を変更する関数.
3次元の位置ベクトルを表す構造体.
static constexpr Vector3 GetUpVec() noexcept
上に進む単位ベクトルを返す. 静的な関数なので,Vector3::GetUpVec() と呼び出せる.
static constexpr Vector3 GetFrontVec() noexcept
正面に進む単位ベクトルを返す. 静的な関数なので,Vector3::GetFrontVec() と呼び出せる.
static constexpr Vector3 GetLeftVec() noexcept
左に進む単位ベクトルを返す. 静的な関数なので,Vector3::GetLeftVec() と呼び出せる.