GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
com_selector.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
8#include "com_selector.h"
9
10#include <algorithm>
11#include <iostream>
12
13#include "math_util.h"
14#include "leg_state.h"
15
16
17namespace designlab
18{
19
21 const Polygon2& polygon,
22 const RobotStateNode& current_node,
23 Vector3* output_com) const
24{
25 std::pair<bool, Vector2> com_candidate[kDiscretizationNum * kDiscretizationNum];
26
27 // 候補点を生成する.
28 if (!MakeComCandidatePoint(polygon, com_candidate))
29 {
30 return false;
31 }
32
33 // 頂点から次の頂点へ向かう辺を正規化したベクトルを作成する.
34 std::vector<Vector2> edge_vec;
35 edge_vec.resize(polygon.GetVertexNum());
36
37 for (int i = 0; i < polygon.GetVertexNum(); ++i)
38 {
39 Vector2 edge = polygon.GetVertex(i) - polygon.GetVertex((i + 1) % polygon.GetVertexNum());
40 edge_vec[i] = edge.GetNormalized();
41 }
42
43 // 候補点を順番にチェックし,移動後の重心が安定余裕を満たすならば,
44 // その点を重心として採用する.
45 for (int i = 0; i < kDiscretizationNum * kDiscretizationNum; ++i)
46 {
47 if (!IsInMargin(polygon, edge_vec, com_candidate[i].second))
48 {
49 // 候補点が多角形の外側ならば次の候補点へ.
50 com_candidate[i].first = false;
51 continue;
52 }
53
54 // 現在の重心を移動させたものを作成する.
55 Vector3 after_move_com_pos = { com_candidate[i].second.x,
56 com_candidate[i].second.y,
57 current_node.center_of_mass_global_coord.z };
58 const Vector3 dif = after_move_com_pos - current_node.center_of_mass_global_coord;
59 const Vector3 real_dif = RotateVector3(dif, current_node.posture.GetConjugate());
60
61 for (int j = 0; j < HexapodConst::kLegNum; ++j)
62 {
63 if (leg_func::IsGrounded(current_node.leg_state, j))
64 {
65 const Vector3 after_move_leg_pos = current_node.leg_pos[j] - real_dif;
66
67 if (!checker_ptr_->IsLegInRange(j, after_move_leg_pos))
68 {
69 // 脚が可動範囲外ならば次の候補点へ.
70 com_candidate[i].first = false;
71 continue;
72 }
73 }
74 }
75 }
76
77 // 候補点の中から現在の重心から最も遠くに移動できるものを選択する.
78
79 const Vector2 k_rotate_center = { -10000, 0 };
80 const float k_rotate_r = 10000;
81
82 float min_dist = -100000;
83 int min_index = -1;
84
85 for (int i = 0; i < kDiscretizationNum * kDiscretizationNum; ++i)
86 {
87 if (com_candidate[i].first)
88 {
89 const float dist = fabsf(
90 (com_candidate[i].second - k_rotate_center).GetLength() - k_rotate_r);
91
92 if (min_dist < dist)
93 {
94 min_dist = dist;
95 min_index = i;
96 }
97 }
98 }
99
100 if (min_index == -1)
101 {
102 // 該当するものがなければ false を返す.
103 return false;
104 }
105
106 (*output_com).x = com_candidate[min_index].second.x;
107 (*output_com).y = com_candidate[min_index].second.y;
108 (*output_com).z = current_node.center_of_mass_global_coord.z;
109 return true;
110}
111
112
113bool ComSelector::MakeComCandidatePoint(
114 const Polygon2& polygon,
115 std::pair<bool, Vector2> coms[kDiscretizationNum * kDiscretizationNum]) const
116{
117 // 波東さんの処理では多角形を囲むような四角形を作るので,まずはそれを作る.
118 const float kMinX = polygon.GetMinX();
119 const float kMaxX = polygon.GetMaxX();
120 const float kMinY = polygon.GetMinY();
121 const float kMaxY = polygon.GetMaxY();
122
123 const float kWidth = kMaxX - kMinX;
124 const float kHeight = kMaxY - kMinY;
125
126 if (math_util::IsEqual(kWidth, 0.0f) || math_util::IsEqual(kHeight, 0.0f))
127 {
128 return false;
129 }
130
131 const float kDeltaWidth = kWidth / static_cast<float>(kDiscretizationNum);
132 const float kDeltaHeight = kHeight / static_cast<float>(kDiscretizationNum);
133
134 // 上記の四角形の中にある点を全て候補に追加する.
135 for (int x = 0; x < kDiscretizationNum; ++x)
136 {
137 for (int y = 0; y < kDiscretizationNum; ++y)
138 {
139 coms[x * kDiscretizationNum + y].first = true;
140 coms[x * kDiscretizationNum + y].second.x = kMinX + kDeltaWidth * x;
141 coms[x * kDiscretizationNum + y].second.y = kMinY + kDeltaHeight * y;
142 }
143 }
144
145 return true;
146}
147
148
149bool ComSelector::IsInMargin(const Polygon2& polygon,
150 const std::vector<Vector2>& edge_vec,
151 const Vector2& candidate_point) const
152{
153 for (int i = 0; i < polygon.GetVertexNum(); ++i)
154 {
155 Vector2 v_map = candidate_point - polygon.GetVertex(i);
156
157 if (v_map.Cross(edge_vec[i]) > -kStabilityMargin)
158 {
159 // 安定余裕を満たさないならば候補から削除する.
160 return false;
161 }
162 }
163
164 return true;
165}
166
167} // namespace designlab
bool GetComFromPolygon(const Polygon2 &polygon, const RobotStateNode &current_node, Vector3 *output_com) const
重心を求める.
static constexpr int kLegNum
bool IsGrounded(const LegStateBit &leg_state, const int leg_index)
脚番号 leg_index 0 ~ 5 に応じて,その脚が接地しているかを調べる. 脚は右前脚を0番として,時計回りに0,1,2,3,4,5となる.左前足が5番.
Definition leg_state.cpp:43
constexpr bool IsEqual(const T num1, const T num2) noexcept
C++において,小数同士の計算は誤差が出てしまう. 誤差込みで値が等しいか調べる.
Definition math_util.h:45
Vector3 RotateVector3(const Vector3 &vec, const EulerXYZ &rot)
回転させたベクトルを返す.三角関数の処理が多く重たいので注意.
2次元の多角形を表す構造体.
constexpr float GetMaxX() const
頂点の中で最大のx座標を返す関数.
constexpr float GetMinY() const
頂点の中で最小のy座標を返す関数.
constexpr int GetVertexNum() const
多角形の頂点数を返す関数.
constexpr float GetMaxY() const
頂点の中で最大のy座標を返す関数.
constexpr Vector2 GetVertex(const int i) const
頂点の座標を返す関数.
constexpr float GetMinX() const
頂点の中で最小のx座標を返す関数.
constexpr Quaternion GetConjugate() const noexcept
クォータニオンの共役を返す. 共役なクォータニオンとは,ベクトル成分の符号を反転させたもの q = w + xi + yj + zk とすると, qの共役は w - xi - yj - zk となる...
グラフ構造のためのノード(頂点).旧名 LNODE
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] 姿勢を表すクォータニオン.
2次元の位置ベクトルを表す構造体.
Vector2 GetNormalized() const
このベクトルを正規化したベクトルを返す.
3次元の位置ベクトルを表す構造体.
float x
ロボットの正面方向に正.
float z
ロボットの上向きに正.