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 "leg_state.h"
14#include "math_util.h"
15
16namespace designlab {
17
19 const RobotStateNode& current_node,
20 Vector3* output_com) const {
21 std::pair<bool, Vector2>
22 com_candidate[kDiscretizationNum * kDiscretizationNum];
23
24 // 候補点を生成する.
25 if (!MakeComCandidatePoint(polygon, com_candidate)) {
26 return false;
27 }
28
29 // 頂点から次の頂点へ向かう辺を正規化したベクトルを作成する.
30 std::vector<Vector2> edge_vec;
31 edge_vec.resize(polygon.GetVertexNum());
32
33 for (int i = 0; i < polygon.GetVertexNum(); ++i) {
34 Vector2 edge = polygon.GetVertex(i) -
35 polygon.GetVertex((i + 1) % polygon.GetVertexNum());
36 edge_vec[i] = edge.GetNormalized();
37 }
38
39 // 候補点を順番にチェックし,移動後の重心が安定余裕を満たすならば,
40 // その点を重心として採用する.
41 for (int i = 0; i < kDiscretizationNum * kDiscretizationNum; ++i) {
42 if (!IsInMargin(polygon, edge_vec, com_candidate[i].second)) {
43 // 候補点が多角形の外側ならば次の候補点へ.
44 com_candidate[i].first = false;
45 continue;
46 }
47
48 // 現在の重心を移動させたものを作成する.
49 Vector3 after_move_com_pos = {com_candidate[i].second.x,
50 com_candidate[i].second.y,
51 current_node.center_of_mass_global_coord.z};
52 const Vector3 dif =
53 after_move_com_pos - current_node.center_of_mass_global_coord;
54 const Vector3 real_dif =
55 RotateVector3(dif, current_node.posture.GetConjugate());
56
57 for (int j = 0; j < HexapodConst::kLegNum; ++j) {
58 if (leg_func::IsGrounded(current_node.leg_state, j)) {
59 const Vector3 after_move_leg_pos = current_node.leg_pos[j] - real_dif;
60
61 if (!checker_ptr_->IsLegInRange(j, after_move_leg_pos)) {
62 // 脚が可動範囲外ならば次の候補点へ.
63 com_candidate[i].first = false;
64 continue;
65 }
66 }
67 }
68 }
69
70 // 候補点の中から現在の重心から最も遠くに移動できるものを選択する.
71
72 const Vector2 k_rotate_center = {-10000, 0};
73 const float k_rotate_r = 10000;
74
75 float min_dist = -100000;
76 int min_index = -1;
77
78 for (int i = 0; i < kDiscretizationNum * kDiscretizationNum; ++i) {
79 if (com_candidate[i].first) {
80 const float dist = fabsf(
81 (com_candidate[i].second - k_rotate_center).GetLength() - k_rotate_r);
82
83 if (min_dist < dist) {
84 min_dist = dist;
85 min_index = i;
86 }
87 }
88 }
89
90 if (min_index == -1) {
91 // 該当するものがなければ false を返す.
92 return false;
93 }
94
95 (*output_com).x = com_candidate[min_index].second.x;
96 (*output_com).y = com_candidate[min_index].second.y;
97 (*output_com).z = current_node.center_of_mass_global_coord.z;
98 return true;
99}
100
101bool ComSelector::MakeComCandidatePoint(
102 const Polygon2& polygon,
103 std::pair<bool, Vector2> coms[kDiscretizationNum * kDiscretizationNum])
104 const {
105 // 波東さんの処理では多角形を囲むような四角形を作るので,まずはそれを作る.
106 const float kMinX = polygon.GetMinX();
107 const float kMaxX = polygon.GetMaxX();
108 const float kMinY = polygon.GetMinY();
109 const float kMaxY = polygon.GetMaxY();
110
111 const float kWidth = kMaxX - kMinX;
112 const float kHeight = kMaxY - kMinY;
113
114 if (math_util::IsEqual(kWidth, 0.0f) || math_util::IsEqual(kHeight, 0.0f)) {
115 return false;
116 }
117
118 const float kDeltaWidth = kWidth / static_cast<float>(kDiscretizationNum);
119 const float kDeltaHeight = kHeight / static_cast<float>(kDiscretizationNum);
120
121 // 上記の四角形の中にある点を全て候補に追加する.
122 for (int x = 0; x < kDiscretizationNum; ++x) {
123 for (int y = 0; y < kDiscretizationNum; ++y) {
124 coms[x * kDiscretizationNum + y].first = true;
125 coms[x * kDiscretizationNum + y].second.x = kMinX + kDeltaWidth * x;
126 coms[x * kDiscretizationNum + y].second.y = kMinY + kDeltaHeight * y;
127 }
128 }
129
130 return true;
131}
132
133bool ComSelector::IsInMargin(const Polygon2& polygon,
134 const std::vector<Vector2>& edge_vec,
135 const Vector2& candidate_point) const {
136 for (int i = 0; i < polygon.GetVertexNum(); ++i) {
137 Vector2 v_map = candidate_point - polygon.GetVertex(i);
138
139 if (v_map.Cross(edge_vec[i]) > -kStabilityMargin) {
140 // 安定余裕を満たさないならば候補から削除する.
141 return false;
142 }
143 }
144
145 return true;
146}
147
148} // 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:46
constexpr bool IsEqual(const T num1, const T num2) noexcept
C++において,小数同士の計算は誤差が出てしまう. 誤差込みで値が等しいか調べる.
Definition math_util.h:42
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 となる...
グラフ構造のためのノード(頂点).
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
ロボットの上向きに正.