12#include <magic_enum.hpp>
29 const std::shared_ptr<const IHexapodCoordinateConverter>& converter_ptr,
30 const std::shared_ptr<const IHexapodJointCalculator>& calculator_ptr,
31 const std::shared_ptr<const IHexapodPostureValidator>& checker_ptr) :
33 converter_ptr_(converter_ptr),
34 calculator_ptr_(calculator_ptr),
35 checker_ptr_(checker_ptr),
36 display_type_(DisplayMode::kDefualt),
40 const int button_size_x = 90;
41 const int button_size_y = 30;
44 std::make_unique<SimpleButton>(
46 10 + button_size_x / 2,
51 button_.back()->SetActivateFunction(
52 [
this]() {display_type_ = DisplayMode::kDefualt; });
55 std::make_unique<SimpleButton>(
57 (10 + button_size_x / 2) + (10 + button_size_x),
62 button_.back()->SetActivateFunction(
63 [
this]() {display_type_ = DisplayMode::kJointState; });
66 std::make_unique<SimpleButton>(
68 (10 + button_size_x / 2) + (10 + button_size_x) * 2,
73 button_.back()->SetActivateFunction(
74 [
this]() {display_type_ = DisplayMode::kGlobalPos; });
76 const int close_button_size = 28;
78 const int close_button_y =
gui_top_pos_y_ + close_button_size / 2 + 2;
80 button_.push_back(std::make_unique<SimpleButton>(
81 "×", close_button_x, close_button_y,
82 close_button_size, close_button_size));
91 if (!calculator_ptr_) {
96 joint_state_ = calculator_ptr_->CalculateAllJointState(display_node_);
115 if (display_type_ == DisplayMode::kDefualt) {
118 else if (display_type_ == DisplayMode::kJointState) {
121 else if (display_type_ == DisplayMode::kGlobalPos) {
131void DxlibGuiNodeDisplayer::DrawNodeInfo()
const {
134 const unsigned int text_color = GetColor(10, 10, 10);
135 const unsigned int text_color_dark = GetColor(80, 80, 80);
139 const int text_interval_y = 20;
141 const std::array<std::string, HexapodConst::kLegNum> leg_name = {
142 "右前",
"右中",
"右後",
"左後",
"左中",
"左前" };
146 DrawFormatStringToHandle(
147 text_pos_x, text_pos_y_min + text_interval_y * (text_line++),
149 DrawFormatStringToHandle(
150 text_pos_x, text_pos_y_min + text_interval_y * (text_line++),
152 " bit : %s", display_node_.
leg_state.to_string().c_str());
154 const auto com_pos_name =
155 EnumToStringRemoveTopK(
159 DrawFormatStringToHandle(
160 text_pos_x, text_pos_y_min + text_interval_y * (text_line++),
162 " 重心 : %s(%d)", com_pos_name.c_str(), com_pos_num);
164 std::string str_leg_pos_right =
"";
165 std::string str_leg_pos_left =
"";
166 std::string str_ground =
"";
180 str_leg_pos_right += std::format(
184 static_cast<int>(pos));
187 str_leg_pos_left += std::format(
191 static_cast<int>(pos));
195 DrawFormatStringToHandle(
197 text_pos_y_min + text_interval_y * (text_line++),
199 " 脚位置 : ", str_leg_pos_right.c_str());
201 DrawFormatStringToHandle(
203 text_pos_y_min + text_interval_y * (text_line++),
205 " %s", str_leg_pos_right.c_str());
207 DrawFormatStringToHandle(
208 text_pos_x, text_pos_y_min + text_interval_y * (text_line++),
210 " %s", str_leg_pos_left.c_str());
212 DrawFormatStringToHandle(
213 text_pos_x, text_pos_y_min + text_interval_y * (text_line++),
215 " 脚の状態:%s", str_ground.c_str());
219 DrawFormatStringToHandle(
221 text_pos_y_min + text_interval_y * (text_line++),
225 DrawFormatStringToHandle(
227 text_pos_y_min + text_interval_y * (text_line++),
232 DrawFormatStringToHandle(
234 text_pos_y_min + text_interval_y * (text_line++),
236 "回転 (w:%5.3f,x:%5.3f,y:%5.3f,z:%5.3f)",
245 DrawFormatStringToHandle(
247 text_pos_y_min + text_interval_y * (text_line++),
249 " オイラー角(x:%5.3f[deg],y:%5.3f[deg],z:%5.3f[deg])",
256 DrawFormatStringToHandle(
258 text_pos_y_min + text_interval_y * (text_line++),
263 DrawFormatStringToHandle(
265 text_pos_y_min + text_interval_y * (text_line++),
269 display_node_.
leg_pos[i].ToString().c_str());
275 DrawFormatStringToHandle(
277 text_pos_y_min + text_interval_y * (text_line++),
279 " %s脚の基準座標は現在の脚位置と同じです.", leg_name[i].c_str());
282 DrawFormatStringToHandle(
284 text_pos_y_min + text_interval_y * (text_line++),
286 " %s脚の基準座標(x:%5.3f,y:%5.3f,z:%5.3f)",
297 DrawFormatStringToHandle(
299 text_pos_y_min + text_interval_y * (text_line++),
305 DrawFormatStringToHandle(
307 text_pos_y_min + text_interval_y * (text_line++),
309 "指定がなければ単位は長さが[mm],角度が[rad]");
312void DxlibGuiNodeDisplayer::DrawJointInfo()
const {
316 const unsigned int text_color = GetColor(10, 10, 10);
317 const unsigned int error_text_color = GetColor(128, 10, 10);
320 const int text_interval_y = 20;
322 if (!calculator_ptr_) {
323 DrawFormatStringToHandle(
325 text_pos_y_min + text_interval_y * 0,
328 "計算クラスが nullptr です");
333 DrawFormatStringToHandle(
335 text_pos_y_min + text_interval_y * 0,
338 "チェッカークラスが nullptr です");
343 if (joint_state_[i].joint_angle.size() != 3) {
344 DrawFormatStringToHandle(
346 text_pos_y_min + text_interval_y * 0,
349 "間接の計算ができていない,またはされていません.");
354 if (joint_state_[i].joint_pos_leg_coordinate.size() != 4) {
355 DrawFormatStringToHandle(
357 text_pos_y_min + text_interval_y * 0,
360 "間接の計算ができていない,またはされていません.");
370 const float coxa_angle_deg =
372 const float femur_angle_deg =
374 const float tibia_angle_deg =
377 DrawFormatStringToHandle(
379 text_pos_y_min + text_interval_y * (text_line++),
382 "[%d] c %s[deg],f %s[deg],t %s[deg]",
388 const auto coxa_to_femur = joint_state_[i].joint_pos_leg_coordinate[0] -
389 joint_state_[i].joint_pos_leg_coordinate[1];
390 const auto femur_to_tibia = joint_state_[i].joint_pos_leg_coordinate[1] -
391 joint_state_[i].joint_pos_leg_coordinate[2];
392 const auto tibia_to_end = joint_state_[i].joint_pos_leg_coordinate[2] -
393 joint_state_[i].joint_pos_leg_coordinate[3];
395 DrawFormatStringToHandle(
397 text_pos_y_min + text_interval_y * (text_line++),
400 " c %3.3f[mm],f %3.3f[mm],t %3.3f[mm]",
401 coxa_to_femur.GetLength(),
402 femur_to_tibia.GetLength(),
403 tibia_to_end.GetLength());
406 if (checker_ptr_->IsLegInRange(
407 i, joint_state_[i].joint_pos_leg_coordinate[3])) {
408 DrawFormatStringToHandle(
410 text_pos_y_min + text_interval_y * (text_line++),
413 " 近似値された可動域内にあります.");
416 DrawFormatStringToHandle(
418 text_pos_y_min + text_interval_y * (text_line++),
425 std::string str =
"";
427 const float coxa_min_angle =
430 const float coxa_max_angle =
434 if (joint_state_[i].joint_angle[0] < coxa_min_angle) {
438 if (joint_state_[i].joint_angle[0] > coxa_max_angle) {
458 if (!joint_state_[i].is_in_range) {
459 str +=
"脚先が届いていません ";
463 const size_t max_str_size = 30;
464 if (str.size() > max_str_size) { str = str.substr(0, max_str_size); }
466 DrawFormatStringToHandle(
468 text_pos_y_min + text_interval_y * (text_line++),
471 " 実際の可動域の外です. %s", str.c_str());
474 DrawFormatStringToHandle(
476 text_pos_y_min + text_interval_y * (text_line++),
484void DxlibGuiNodeDisplayer::DrawGlobalPosInfo()
const {
485 const unsigned int text_color = GetColor(10, 10, 10);
488 const int text_interval_y = 20;
489 const std::array<std::string, HexapodConst::kLegNum> leg_name = {
490 "右前",
"右中",
"右後",
"左後",
"左中",
"左前" };
494 DrawFormatStringToHandle(text_pos_x,
495 text_pos_y_min + text_interval_y * (text_line++),
501 DrawFormatStringToHandle(
503 text_pos_y_min + text_interval_y * (text_line++),
508 display_node_.
leg_pos[i].ToString().c_str());
513 DrawFormatStringToHandle(text_pos_x,
514 text_pos_y_min + text_interval_y * (text_line++),
520 const std::string str =
521 converter_ptr_->ConvertLegToRobotCoordinate(
522 display_node_.
leg_pos[i], i).ToString();
524 DrawFormatStringToHandle(
526 text_pos_y_min + text_interval_y * (text_line++),
529 "%s %s", leg_name[i].c_str(), str.c_str());
533 DrawFormatStringToHandle(text_pos_x,
534 text_pos_y_min + text_interval_y * (text_line++),
539 DrawFormatStringToHandle(
541 text_pos_y_min + text_interval_y * (text_line++),
550 DrawFormatStringToHandle(
552 text_pos_y_min + text_interval_y * (text_line++),
557 converter_ptr_->ConvertLegToGlobalCoordinate(
562 true).ToString().c_str());
569 DrawFormatStringToHandle(
570 text_pos_x +
width_ / 2 * (i % 2),
571 text_pos_y_min + text_interval_y * text_line,
576 display_node_.
leg_pos[i].ProjectedXY().GetLength());
578 if (i % 2 == 1) { ++text_line; }
582bool DxlibGuiNodeDisplayer::IsInWindow()
const {
void DrawBackground(const std::string &str) const
int gui_left_pos_x_
GUIの左端の位置.
static constexpr int kTitleBarHeight
タイトルバーの高さ.
int gui_top_pos_y_
GUIの上端の位置.
void SetVisible(bool visible) override
GUIの表示を行うかどうかを設定する.
int font_handle_
フォントハンドル.
std::vector< std::unique_ptr< SimpleButton > > button_
ボタンのリスト.
void SetNode(const RobotStateNode &node) override
ノードをセットする.
void Draw() const override
GUIの描画.
DxlibGuiNodeDisplayer(int window_x, int window_y, const std::shared_ptr< const IHexapodCoordinateConverter > &converter_ptr, const std::shared_ptr< const IHexapodJointCalculator > &calculator_ptr, const std::shared_ptr< const IHexapodPostureValidator > &checker_ptr)
void Update() override
GUIの更新,毎フレーム実行すること.
static constexpr int kLegNum
static constexpr float kTibiaAngleMax
static constexpr float kFemurAngleMin
第2関節の可動範囲の最大値[rad].詳しくは referenceフォルダ参照.
static constexpr float kFemurAngleMax
第2関節の可動範囲の最小値[rad].詳しくは referenceフォルダ参照.
static constexpr float kCoxaAngleMin
第1関節の可動範囲の最大値[rad].詳しくは referenceフォルダ参照.
static constexpr float kTibiaAngleMin
第2関節の可動範囲の最大値[rad].詳しくは referenceフォルダ参照.
static constexpr std::array< float, kPhantomXLegNum > kCoxaDefaultAngle
第1関節の初期角度[rad]
static constexpr float kCoxaAngleMax
第2関節の可動範囲の最小値[rad].詳しくは referenceフォルダ参照.
bool IsGrounded(const LegStateBit &leg_state, const int leg_index)
脚番号 leg_index 0 ~ 5 に応じて,その脚が接地しているかを調べる. 脚は右前脚を0番として,時計回りに0,1,2,3,4,5となる.左前足が5番.
DiscreteLegPos GetDiscreteLegPos(const LegStateBit &leg_state, const int leg_index)
脚状態を取得する.
enums::DiscreteComPos GetDiscreteComPos(const LegStateBit &leg_state)
現在の脚状態から重心パターンを取得する.
std::string FloatingPointNumToString(const T num, const int digit=kDigit, const int width=kWidth)
小数を文字列に変換する関数. C++ では C のフォーマットのように %3.3f とかで小数を文字列に変換できないため自作する.
constexpr T ConvertRadToDeg(const T rad) noexcept
角度を [rad]から [deg] に変換する関数.
std::string EnumToStringRemoveTopK(const T &enum_value)
enumを文字列に変換する関数. Google C++ coding style だと enumの要素は 先頭にkをつけてキャメルケースで書くことが推奨されている....
DiscreteLegPos
離散化された脚位置を表す列挙体. 先行研究では 1~7の int型の数値で表現されているが, 可読性を上げるために列挙体にした. 離散化された脚位置は 3bit (0 ~ 7)の範囲で表現される...
EulerXYZ ToEulerXYZ(const RotationMatrix3x3 &rot)
回転角行列からXYZオイラー角への変換.
std::array< Vector3, HexapodConst::kLegNum > leg_pos
[4 * 3 * 6 = 72 byte] 脚先の座標.(coxa(脚の付け根)を原点とする)
leg_func::LegStateBit leg_state
[4 byte] 脚状態,重心パターンを bitで表す.旧名 leg_con.
Vector3 center_of_mass_global_coord
[4 * 3 = 12byte] グローバル座標系における重心の位置.旧名 GCOM
Quaternion posture
[4 * 4 = 16byte] 姿勢を表すクォータニオン.
std::array< Vector3, HexapodConst::kLegNum > leg_reference_pos
int depth
[4 byte] 自身の深さ.一番上の親が深さ0となる.
std::string ToString() const
このベクトルを文字列にして返す. (x, y, z) の形式,小数点以下3桁まで.