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