GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
graph_searcher_turn.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 <vector>
11
12#include "cassert_define.h"
13
14namespace designlab {
15
17 const std::shared_ptr<const IHexapodCoordinateConverter>& converter_ptr,
18 const std::shared_ptr<const IHexapodPostureValidator>& checker_ptr)
19 : converter_ptr_(converter_ptr),
20 checker_ptr_(checker_ptr),
21 evaluator_(InitializeEvaluator()) {}
22
23std::tuple<GraphSearchResult, GraphSearchEvaluationValue, RobotStateNode>
25 const RobotOperation& operation,
26 const DividedMapState& divided_map_state,
27 const int max_depth) const {
28 assert(operation.operation_type == RobotOperationType::kTurn);
29
30 if (!graph.HasRoot()) {
32 "ルートノードがありません."};
33 return {result, GraphSearchEvaluationValue{}, RobotStateNode{}};
34 }
35
36 // 初期化.
37 Quaternion target_quat;
38
40 target_quat = operation.spot_turn_last_posture;
41 } else {
42 assert(false);
43 }
44
45 const float target_z_value =
46 InitTargetZValue(graph.GetRootNode(), divided_map_state, target_quat);
47
48 GraphSearchEvaluationValue max_evaluation_value =
49 evaluator_.InitializeEvaluationValue();
50 int max_evaluation_value_index = -1;
51
52 for (int i = 0; i < graph.GetGraphSize(); i++) {
53 // 最大深さのノードのみを評価する.
54 if (graph.GetNode(i).depth != max_depth) {
55 continue;
56 }
57
58 // 評価値を計算する.
59 GraphSearchEvaluationValue candidate_evaluation_value =
60 evaluator_.InitializeEvaluationValue();
61
62 candidate_evaluation_value.value.at(kTagAmountOfTurn) =
63 GetAmountOfTurnEvaluationValue(graph.GetNode(i), target_quat);
64 candidate_evaluation_value.value.at(kTagLegRot) =
65 GetLegRotEvaluationValue(graph.GetNode(i), graph.GetRootNode());
66 candidate_evaluation_value.value.at(kTagZDiff) =
67 GetZDiffEvaluationValue(graph.GetNode(i), target_z_value);
68
69 // 評価値を比較する.
70 if (evaluator_.LeftIsBetter(candidate_evaluation_value,
71 max_evaluation_value)) {
72 max_evaluation_value = candidate_evaluation_value;
73 max_evaluation_value_index = i;
74 }
75 }
76
77 // インデックスが範囲外ならば失敗.
78 if (max_evaluation_value_index < 0 ||
79 graph.GetGraphSize() <= max_evaluation_value_index) {
81 "最大評価値のインデックスが範囲外です."};
82 return {result, GraphSearchEvaluationValue{}, RobotStateNode{}};
83 }
84
85 const GraphSearchResult result = {enums::Result::kSuccess, ""};
86
87 return {
88 result,
89 max_evaluation_value,
90 graph.GetParentNode(max_evaluation_value_index, 1),
91 };
92}
93
94std::tuple<GraphSearchResult, GraphSearchEvaluationValue, RobotStateNode>
96 const std::vector<GaitPatternGraphTree>& graph_vector,
97 const RobotOperation& operation, const DividedMapState& divided_map_state,
98 int max_depth) const {
99 std::vector<
100 std::tuple<GraphSearchResult, GraphSearchEvaluationValue, RobotStateNode>>
101 result_vector;
102
103 for (const auto& graph : graph_vector) {
104 const auto result =
105 SearchGraphTree(graph, operation, divided_map_state, max_depth);
106
107 result_vector.push_back(result);
108 }
109
110 // 最大評価値を持つものを探す.
111 GraphSearchEvaluationValue max_evaluation_value =
112 evaluator_.InitializeEvaluationValue();
113 int max_evaluation_value_index = -1;
114
115 for (int i = 0; i < result_vector.size(); i++) {
116 const auto& [result, evaluation_value, _] = result_vector.at(i);
117
118 if (result.result != enums::Result::kSuccess) {
119 continue;
120 }
121
122 if (evaluator_.LeftIsBetter(evaluation_value, max_evaluation_value)) {
123 max_evaluation_value = evaluation_value;
124 max_evaluation_value_index = i;
125 }
126 }
127
128 // インデックスが範囲外ならば失敗.
129 if (max_evaluation_value_index < 0 ||
130 max_evaluation_value_index >= result_vector.size()) {
132 "最大評価値のインデックスが範囲外です."};
133 return {result, GraphSearchEvaluationValue{}, RobotStateNode{}};
134 }
135
136 return result_vector[max_evaluation_value_index];
137}
138
139GraphSearchEvaluator GraphSearcherTurn::InitializeEvaluator() const {
140 GraphSearchEvaluator::EvaluationMethod amount_of_turn_method = {
141 .is_lower_better = false,
142 .margin = 0.0f,
143 };
144
145 GraphSearchEvaluator::EvaluationMethod leg_rot_method = {
146 .is_lower_better = false,
147 .margin = 0.0f,
148 };
149
150 GraphSearchEvaluator::EvaluationMethod z_diff_method = {
151 .is_lower_better = true,
152 .margin = 5.0f,
153 };
154
155 GraphSearchEvaluator ret({{kTagAmountOfTurn, amount_of_turn_method},
156 {kTagLegRot, leg_rot_method},
157 {kTagZDiff, z_diff_method}},
158 {kTagZDiff, kTagAmountOfTurn, kTagLegRot});
159
160 return ret;
161}
162
163float GraphSearcherTurn::InitTargetZValue(
164 const RobotStateNode& node, const DividedMapState& divided_map_state,
165 const Quaternion& target_quat) const {
166 const int div = 50;
167 const float min_z = -150.0f;
168 const float max_z = 150.0f;
169
170 for (int i = 0; i < div; i++) {
171 const float z = min_z + (max_z - min_z) / static_cast<float>(div) *
172 static_cast<float>(i);
173
174 Vector3 pos = node.center_of_mass_global_coord;
175 pos.z += z;
176
177 RobotStateNode temp_node = node;
178 temp_node.ChangeGlobalCenterOfMass(pos, false);
179 temp_node.ChangePosture(converter_ptr_, target_quat);
180
181 if (!checker_ptr_->IsBodyInterferingWithGround(temp_node,
182 divided_map_state)) {
183 return node.center_of_mass_global_coord.z + z;
184 }
185 }
186
187 return node.center_of_mass_global_coord.z;
188}
189
190float GraphSearcherTurn::GetAmountOfTurnEvaluationValue(
191 const RobotStateNode& node, const Quaternion& target_quat) const {
192 // 目標姿勢を Qt,現在の姿勢を Qc とする.
193 // Qt = Qc * Qd となるような Qd を求める.
194 // Qd = Qc^-1 * Qt となる.
195
196 // 最終姿勢を表すクォータニオンとの差分を計算する.
197 const Quaternion target_to_current =
198 node.posture.GetConjugate() * target_quat;
199
200 return target_to_current.w;
201}
202
203float GraphSearcherTurn::GetLegRotEvaluationValue(
204 const RobotStateNode& node, const RobotStateNode& root_node) const {
205 float result = 0.0f;
206
207 for (int i = 0; i < HexapodConst::kLegNum; i++) {
208 if (leg_func::IsGrounded(node.leg_state, i)) {
209 result +=
210 (node.leg_pos[i].ProjectedXY() - root_node.leg_pos[i].ProjectedXY())
211 .GetLength();
212 } else {
213 result += (node.leg_pos[i] - root_node.leg_pos[i]).GetLength();
214 }
215 }
216
217 return result;
218
219 // const float margin = 50.0f;
220}
221
222float GraphSearcherTurn::GetZDiffEvaluationValue(
223 const RobotStateNode& node, const float target_z_value) const {
224 return abs(node.center_of_mass_global_coord.z - target_z_value);
225}
226
227} // namespace designlab
マップを格子状に分割して管理するクラス.
RobotStateNode 構造体をノードとする木構造のグラフのクラス.
const RobotStateNode & GetRootNode() const
グラフの根ノードの参照を返す.
const RobotStateNode & GetParentNode(const int index, const int depth) const
指定したノードの親ノードの参照を返す.depthは親ノードの深さを指定する.
const RobotStateNode & GetNode(const int index) const
グラフのノードの参照を返す.
constexpr bool HasRoot() const
グラフが根ノードを持つかどうかを返す. 根ノードとは,親を持たないノードのこと. 一番最初に追加するノードは必ず根になるため, 根を持つかどうかはノードの総数が0でないかどうかで判定できる.
constexpr int GetGraphSize() const
グラフのノードの総数を返す.
グラフ探索の評価値を評価するクラス.
bool LeftIsBetter(const GraphSearchEvaluationValue &left, const GraphSearchEvaluationValue &right, bool return_true_case_of_equal=true) const
2つの評価値を比較する.左側の評価値が良い場合は true を返す.
GraphSearchEvaluationValue InitializeEvaluationValue() const
評価値を初期化する. 自身の持つ評価方法を用いて,評価値を初期化する.
GraphSearcherTurn(const std::shared_ptr< const IHexapodCoordinateConverter > &converter_ptr, const std::shared_ptr< const IHexapodPostureValidator > &checker_ptr)
std::tuple< GraphSearchResult, GraphSearchEvaluationValue, RobotStateNode > SearchGraphTreeVector(const std::vector< GaitPatternGraphTree > &graph_vector, const RobotOperation &operation, const DividedMapState &divided_map_state, int max_depth) const override
std::tuple< GraphSearchResult, GraphSearchEvaluationValue, RobotStateNode > SearchGraphTree(const GaitPatternGraphTree &graph, const RobotOperation &operation, const DividedMapState &divided_map_state, int max_depth) const override
グラフを受け取り,その中から最適な次の動作を出力する.
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
@ kTurn
旋回中心と,旋回半径と,旋回方向を与えて旋回させる.
@ kSpotTurnLastPosture
その場で旋回させる(最終的な姿勢 Posture を示す)
グラフ探索の評価値を格納する構造体.
bool is_lower_better
評価値が小さいほど良い場合は true.
グラフ探索の結果を表す構造体.
クォータニオンを表す構造体.
探索において目標となる座標や角度,評価する値についてまとめた構造体.
RobotOperationType operation_type
Quaternion spot_turn_last_posture
旋回時の回転軸.右ねじの回転.
グラフ構造のためのノード(頂点).
int depth
[4 byte] 自身の深さ.一番上の親が深さ0となる.