GaitGeneration by Graph Search
読み取り中…
検索中…
一致する文字列を見つけられません
xr_r1.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 "xr_r1.h"
9
10#include <numbers>
11
12#include <cmath>
13
14#include "cassert_define.h"
15#include "math_line_segment2.h"
16#include "math_util.h"
17#include "leg_state.h"
18#include "xr_r1_const.h"
19
20namespace designlab {
21
22XrR1::XrR1(const XrR1ParameterRecord& parameter_record) :
23 kBodyLiftingHeightMin(parameter_record.body_lifting_height_min),
24 kBodyLiftingHeightMax(parameter_record.body_lifting_height_max),
25 kMovableCoxaAngleMin(math_util::ConvertDegToRad(parameter_record.movable_coxa_angle_min_deg)),
26 kMovableCoxaAngleMax(math_util::ConvertDegToRad(parameter_record.movable_coxa_angle_max_deg)),
27 kMinLegR(parameter_record.min_leg_range),
28 kMaxLegR(parameter_record.max_leg_range),
29 kFreeLegHeight(parameter_record.free_leg_height),
30 kStableMargin(parameter_record.stable_margin),
31 free_leg_pos_leg_coordinate_({ {
32 {160 * cos(XrR1Const::kCoxaDefaultAngle[0]), 160 * sin(XrR1Const::kCoxaDefaultAngle[0]), kFreeLegHeight},
33 {160 * cos(XrR1Const::kCoxaDefaultAngle[1]), 160 * sin(XrR1Const::kCoxaDefaultAngle[1]), kFreeLegHeight},
34 {160 * cos(XrR1Const::kCoxaDefaultAngle[2]), 160 * sin(XrR1Const::kCoxaDefaultAngle[2]), kFreeLegHeight},
35 {160 * cos(XrR1Const::kCoxaDefaultAngle[3]), 160 * sin(XrR1Const::kCoxaDefaultAngle[3]), kFreeLegHeight},
36 {160 * cos(XrR1Const::kCoxaDefaultAngle[4]), 160 * sin(XrR1Const::kCoxaDefaultAngle[4]), kFreeLegHeight},
37 {160 * cos(XrR1Const::kCoxaDefaultAngle[5]), 160 * sin(XrR1Const::kCoxaDefaultAngle[5]), kFreeLegHeight},
38 } }),
39 leg_base_pos_robot_coordinate_({ {
46 } }),
47 kMaxLegRArray(InitMaxLegR()),
48 kMinLegPosXY(InitMinLegPosXY()),
49 kMaxLegPosXY(InitMaxLegPosXY()),
50 kMinLegDistance(50.0) {}
51
53 const int leg_index, const Vector3& leg_pos) const noexcept {
54 // leg_indexは 0~5 である.
55 assert(0 <= leg_index);
56 assert(leg_index < HexapodConst::kLegNum);
57
58 // 各パラメータを初期化する.
60
61 const int kJointNum = 4;
62 const int kJointAngleNum = kJointNum - 1;
63
64 res.joint_pos_leg_coordinate.clear();
65 res.joint_angle.clear();
66
67 res.joint_pos_leg_coordinate.resize(kJointNum);
68 res.joint_angle.resize(kJointAngleNum);
69
70
71 // coxa jointの計算.脚座標系では coxa joint は原点にある.
72 res.joint_pos_leg_coordinate[0] = Vector3{ 0, 0, 0 };
73
74 // 脚先の追加.
75 res.joint_pos_leg_coordinate[3] = leg_pos;
76
77 // coxa angleの計算.
78 {
79 float coxa_joint_angle = std::atan2f(leg_pos.y, leg_pos.x);
80
81 if (leg_pos.y == 0 && leg_pos.x == 0) {
82 coxa_joint_angle = XrR1Const::kCoxaDefaultAngle[leg_index];
83 }
84
85 if (!XrR1Const::IsValidCoxaAngle(leg_index, coxa_joint_angle)) {
86 // 範囲外ならば,180度回転させた時に範囲内にあるかを調べる.
88 leg_index, coxa_joint_angle + std::numbers::pi_v<float>)) {
89 coxa_joint_angle += std::numbers::pi_v<float>;
90 }
92 leg_index, coxa_joint_angle - std::numbers::pi_v<float>)) {
93 coxa_joint_angle -= std::numbers::pi_v<float>;
94 }
95 }
96
97 res.joint_angle[0] = coxa_joint_angle;
98 }
99
100 // femur jointの計算.
101 {
102 const Vector3 femur_joint_pos = Vector3{
103 XrR1Const::kCoxaLength * std::cos(res.joint_angle[0]),
104 XrR1Const::kCoxaLength * std::sin(res.joint_angle[0]),
105 0
106 };
107
108 res.joint_pos_leg_coordinate[1] = femur_joint_pos;
109
110 if (!math_util::CanMakeTriangle((leg_pos - femur_joint_pos).GetLength(),
113 // そもそも脚先が脚の付け根から届かない場合,一番近い位置まで脚を伸ばす.
114
115 const float angle_ft = std::atan2(
116 leg_pos.z - femur_joint_pos.z,
117 (leg_pos.ProjectedXY() - femur_joint_pos.ProjectedXY()).GetLength());
118
119 // angle_ftの位相を180度回転する.-180度~180度の範囲にする.
120 float angle_ft_phase = angle_ft + std::numbers::pi_v<float>;
121 angle_ft_phase = (angle_ft_phase > std::numbers::pi_v<float>) ?
122 angle_ft_phase - std::numbers::pi_v<float> : angle_ft_phase;
123
124 const Vector3 candidate_leg_pos = femur_joint_pos + Vector3{
126 std::cos(res.joint_angle[0]) * std::cos(angle_ft),
127
129 std::sin(res.joint_angle[0]) * std::cos(angle_ft),
130
132 std::sin(angle_ft)
133 };
134
135 const Vector3 candidate_leg_pos_phase = femur_joint_pos + Vector3{
136 (XrR1Const::kFemurLength * std::cos(angle_ft_phase) +
137 XrR1Const::kTibiaLength * std::cos(angle_ft)) *
138 std::cos(res.joint_angle[0]),
139
140 (XrR1Const::kFemurLength * std::cos(angle_ft_phase) +
141 XrR1Const::kTibiaLength * std::cos(angle_ft)) *
142 std::sin(res.joint_angle[0]),
143
144 XrR1Const::kFemurLength * std::sin(angle_ft_phase) +
145 XrR1Const::kTibiaLength * std::sin(angle_ft)
146 };
147
148 const float distance = (leg_pos - candidate_leg_pos).GetLength();
149 const float distance_phase = (leg_pos - candidate_leg_pos_phase).GetLength();
150
151 float angle_f = 0, angle_t = 0;
152
153 if (distance < distance_phase) {
154 angle_f = angle_ft;
155 angle_t = 0;
156 }
157 else {
158 angle_f = angle_ft_phase;
159 angle_t = -std::numbers::pi_v<float>;
160 }
161
162 res.joint_angle[1] = angle_f;
163 res.joint_angle[2] = angle_t;
164
165 res.joint_pos_leg_coordinate[2] = femur_joint_pos + Vector3{
166 XrR1Const::kFemurLength * std::cos(angle_f) *
167 std::cos(res.joint_angle[0]),
168
169 XrR1Const::kFemurLength * std::cos(angle_f) *
170 std::sin(res.joint_angle[0]),
171
172 XrR1Const::kFemurLength * std::sin(angle_f)
173 };
174
176 XrR1Const::kTibiaLength * std::cos(angle_f + angle_t) *
177 std::cos(res.joint_angle[0]),
178
179 XrR1Const::kTibiaLength * std::cos(angle_f + angle_t) *
180 std::sin(res.joint_angle[0]),
181
182 XrR1Const::kTibiaLength * std::sin(angle_f + angle_t)
183 };
184
185 res.is_in_range = false; // 範囲外であることを示す.
186
187 return res;
188 }
189 }
190
191
192 // femur angle の計算.
193
194 // 脚先から第一関節までの長さ.
195 const Vector3 femur_to_leg = leg_pos - res.joint_pos_leg_coordinate[1];
196
197 // 脚先へ向かう方向をxの正方向にする座標系に置き換える.
198 // 脚先が第一関節よりも近い場合は正の方向にする.
199 const float femur_to_leg_x =
200 femur_to_leg.ProjectedXY().GetLength() *
201 ((leg_pos.ProjectedXY().GetSquaredLength() >
202 res.joint_pos_leg_coordinate[1].ProjectedXY().GetSquaredLength()) ? 1.f : -1.f);
203
204 const float femur_to_leg_z = femur_to_leg.z;
205
206 {
207 const float arc_cos_upper =
208 femur_to_leg.GetSquaredLength() +
211
212 const float arc_cos_lower = 2 * XrR1Const::kFemurLength *
213 femur_to_leg.GetLength();
214
215 const float arc_cos_arg = arc_cos_upper / arc_cos_lower;
216
217
218 const float femur_joint_angle =
219 std::acos(arc_cos_arg) +
220 std::atan2(femur_to_leg_z, femur_to_leg_x);
221
222 res.joint_angle[1] = femur_joint_angle;
223 }
224
225 // tibia jointの計算.
226 {
227 const Vector3 femur_to_tibia = Vector3{
228 XrR1Const::kFemurLength * std::cos(res.joint_angle[0]) *
229 std::cos(res.joint_angle[1]),
230
231 XrR1Const::kFemurLength * std::sin(res.joint_angle[0]) *
232 std::cos(res.joint_angle[1]),
233
234 XrR1Const::kFemurLength * std::sin(res.joint_angle[1])
235 };
236
237 const Vector3 tibia_joint_pos = res.joint_pos_leg_coordinate[1] + femur_to_tibia;
238
239 res.joint_pos_leg_coordinate[2] = tibia_joint_pos;
240 }
241
242
243 // tibia angleの計算.
244 {
245 const float tibia_angle = std::atan2(
246 (femur_to_leg_z - XrR1Const::kFemurLength * std::sin(res.joint_angle[1])),
247 (femur_to_leg_x - XrR1Const::kFemurLength * std::cos(res.joint_angle[1]))) -
248 res.joint_angle[1];
249
250 res.joint_angle[2] = tibia_angle;
251 }
252
253 res.is_in_range = true;
254
255 return res;
256}
257
258bool XrR1::IsValidJointState(const int leg_index,
259 const Vector3& leg_pos,
260 const HexapodJointState& joint_state) const noexcept {
261 assert(joint_state.joint_pos_leg_coordinate.size() == 4);
262 assert(joint_state.joint_angle.size() == 3);
263
264 // coxa関節の範囲内に存在しているかを確認する.
265 if (!XrR1Const::IsValidCoxaAngle(leg_index, joint_state.joint_angle[0])) {
266 return false;
267 }
268
269 // femur関節の範囲内に存在しているかを確認する.
270 if (!XrR1Const::IsValidFemurAngle(joint_state.joint_angle[1])) {
271 return false;
272 }
273
274 // tibia関節の範囲内に存在しているかを確認する.
275 if (!XrR1Const::IsValidTibiaAngle(joint_state.joint_angle[2])) {
276 return false;
277 }
278
279 // リンクの長さを確認する.
280 if (!math_util::IsEqual((joint_state.joint_pos_leg_coordinate[0] -
281 joint_state.joint_pos_leg_coordinate[1]).GetLength(), XrR1Const::kCoxaLength)) {
282 return false;
283 }
284
285 if (!math_util::IsEqual((joint_state.joint_pos_leg_coordinate[1] -
286 joint_state.joint_pos_leg_coordinate[2]).GetLength(), XrR1Const::kFemurLength)) {
287 return false;
288 }
289
290 if (!math_util::IsEqual((joint_state.joint_pos_leg_coordinate[2] -
291 joint_state.joint_pos_leg_coordinate[3]).GetLength(), XrR1Const::kTibiaLength)) {
292 return false;
293 }
294
295 // 脚位置と脚先座標が一致しているかを確認する.
296 if (joint_state.joint_pos_leg_coordinate[3] != leg_pos) { return false; }
297
298 return true;
299}
300
301
303 const Vector3& converted_position,
304 const int leg_index,
305 const Vector3& center_of_mass_global,
306 const Quaternion& robot_quat,
307 const bool consider_rot) const {
308 // leg_indexは 0~5 である.
309 assert(0 <= leg_index);
310 assert(leg_index < HexapodConst::kLegNum);
311
312 if (consider_rot) {
313 return RotateVector3(converted_position - center_of_mass_global,
314 robot_quat.GetConjugate()) -
316 }
317 else {
318 return converted_position -
319 center_of_mass_global -
321 }
322}
323
325 const Vector3& converted_position,
326 int leg_index,
327 const Vector3& center_of_mass_global,
328 const Quaternion& robot_quat,
329 const bool consider_rot) const {
330 // leg_indexは 0~5 である.
331 assert(0 <= leg_index);
332 assert(leg_index < HexapodConst::kLegNum);
333
334 if (consider_rot) {
335 return RotateVector3(converted_position + GetLegBasePosRobotCoordinate(leg_index),
336 robot_quat) + center_of_mass_global;
337 }
338 else {
339 return converted_position +
340 GetLegBasePosRobotCoordinate(leg_index) + center_of_mass_global;
341 }
342}
343
345 const Vector3& converted_position,
346 const Vector3& center_of_mass_global,
347 const Quaternion& robot_quat,
348 const bool consider_rot) const {
349 if (consider_rot) {
350 return RotateVector3(converted_position, robot_quat) + center_of_mass_global;
351 }
352 else {
353 return converted_position + center_of_mass_global;
354 }
355}
356
358 const int leg_index) const {
359 return converted_position - GetLegBasePosRobotCoordinate(leg_index);
360}
361
363 const int leg_index) const {
364 return converted_position + GetLegBasePosRobotCoordinate(leg_index);
365}
366
367
368Vector3 XrR1::GetFreeLegPosLegCoordinate(const int leg_index) const noexcept {
369 // leg_indexは 0~5 である.
370 assert(0 <= leg_index);
371 assert(leg_index < HexapodConst::kLegNum);
372
373 return free_leg_pos_leg_coordinate_[leg_index];
374}
375
376Vector3 XrR1::GetLegBasePosRobotCoordinate(const int leg_index) const noexcept {
377 // leg_indexは 0~5 である.
378 assert(0 <= leg_index);
379 assert(leg_index < HexapodConst::kLegNum);
380
381 return leg_base_pos_robot_coordinate_[leg_index];
382}
383
384
385bool XrR1::IsLegInRange(const int leg_index, const Vector3& leg_pos) const {
386 // leg_indexは 0~5 である.
387 assert(0 <= leg_index);
388 assert(leg_index < HexapodConst::kLegNum);
389
390 if (GetFreeLegPosLegCoordinate(leg_index).z < leg_pos.z) {
391 return false;
392 }
393
394 const Vector2 leg_pos_xy = leg_pos.ProjectedXY(); // 投射した脚先座標をえる.
395
396 // 脚の角度が範囲内にあるか調べる.外積計算で間にあるか調べる
397 if (kMinLegPosXY[leg_index].Cross(leg_pos_xy) < 0.0f) {
398 return false;
399 }
400
401 if (kMaxLegPosXY[leg_index].Cross(leg_pos_xy) > 0.0f) {
402 return false;
403 }
404
405
406 // 脚を伸ばすことのできない範囲に伸ばしていないか調べる.
407 if (static_cast<int>(leg_pos.z) < -kMaxLegRSize || 0 < static_cast<int>(leg_pos.z)) {
408 return false;
409 }
410
411 if (leg_pos_xy.GetSquaredLength() < math_util::Squared(kMinLegR)) {
412 return false;
413 }
414
415 if (math_util::Squared(kMaxLegR) < leg_pos_xy.GetSquaredLength()) {
416 return false;
417 }
418
419 if (math_util::Squared(kMaxLegRArray[-static_cast<int>(leg_pos.z)]) <
420 leg_pos_xy.GetSquaredLength()) {
421 return false;
422 }
423
424 return true;
425}
426
428 const std::array<Vector3, HexapodConst::kLegNum>& leg_pos) const {
429 // 重心を原点とした,座標系において,脚の干渉を調べる.
430
431 // 脚の干渉を調べる.
432 Vector2 leg_pos_xy[HexapodConst::kLegNum]; // 脚先の座標(ロボット座標系).
433 Vector2 joint_pos_xy[HexapodConst::kLegNum]; // 脚の根元の座標(ロボット座標系).
434
435 // 脚の根元の座標(ロボット座標系)を取得する.
436 for (int i = 0; i < HexapodConst::kLegNum; i++) {
437 joint_pos_xy[i] = GetLegBasePosRobotCoordinate(i).ProjectedXY();
438 leg_pos_xy[i] = ConvertLegToRobotCoordinate(leg_pos[i], i).ProjectedXY();
439 }
440
441 // 隣の脚との干渉を調べる.
442 for (int i = 0; i < HexapodConst::kLegNum; i++) {
443 // 脚が交差しているか調べる.
444 LineSegment2 line1(joint_pos_xy[i], leg_pos_xy[i]);
445 LineSegment2 line2(joint_pos_xy[(i + 1) % HexapodConst::kLegNum],
446 leg_pos_xy[(i + 1) % HexapodConst::kLegNum]);
447
448 if (line1.HasIntersection(line2)) { return true; }
449
450 // 脚先の距離を確認する.
451 if (leg_pos_xy[i].GetDistanceFrom(leg_pos_xy[(i + 1) % HexapodConst::kLegNum]) < kMinLegDistance) {
452 return true;
453 }
454 }
455
456 return false;
457}
458
459float XrR1::GetGroundHeightMarginMin() const noexcept {
460 return kBodyLiftingHeightMin;
461}
462
463float XrR1::GetGroundHeightMarginMax() const noexcept {
464 return kBodyLiftingHeightMax;
465}
466
468 const leg_func::LegStateBit& leg_state,
469 const std::array<Vector3, HexapodConst::kLegNum>& leg_pos) const {
470 // std::min をカッコで囲んでいるのは,マクロの min と被るため.
471 // (std::min) と書くと名前が衝突しない
472
473 // xy平面に投射した,重心を原点としたローカル(ロボット)座標系で,脚の位置を計算する.
474 std::array<Vector2, HexapodConst::kLegNum> ground_leg_pos;
475
476 // 速度の関係上 vectorでなく array を使う.
477 int ground_leg_pos_num = 0;
478
479
480 // 接地脚のみ追加する.
481 for (int i = 0; i < HexapodConst::kLegNum; i++) {
482 if (leg_func::IsGrounded(leg_state, i)) {
483 ground_leg_pos[ground_leg_pos_num] = leg_pos[i].ProjectedXY() +
485
486 ground_leg_pos_num++;
487 }
488 }
489
490
491 float min_margin = 0; // 多角形の辺と重心の距離の最小値
492 bool is_first = true; // 初回かどうか,最初は必ず値を更新する
493
494 for (int i = 0; i < ground_leg_pos_num; i++) {
495 Vector2 i_to_i_plus_1 = ground_leg_pos[(i + 1) % ground_leg_pos_num] -
496 ground_leg_pos[i];
497 Vector2 i_to_com = Vector2{ 0, 0 } - ground_leg_pos[i];
498
499 // 多角形の辺と重心の距離(静的安定余裕)
500 float margin = i_to_com.Cross(i_to_i_plus_1.GetNormalized());
501
502 if (is_first) {
503 min_margin = margin;
504 is_first = false;
505 }
506 else {
507 min_margin = (std::min)(min_margin, margin);
508 }
509 }
510
511 return min_margin;
512}
513
515 const std::array<Vector3, HexapodConst::kLegNum>& leg_pos) const {
516 // kStableMargin 以上の余裕があるか調べる.
517 return CalculateStabilityMargin(leg_state, leg_pos) > kStableMargin;
518}
519
521 const DividedMapState& divided_map) const {
522 // 重心の干渉を調べる.
523 const float top_z = (std::max)(
524 divided_map.GetMapMinZ(),
525 divided_map.GetTopZ(
528
529 if (top_z != divided_map.GetMapMinZ() &&
531 return true;
532 }
533
534
535 for (int i = 0; i < HexapodConst::kLegNum; ++i) {
536 // 脚の根元の座標(グローバル)を取得する.
537 const Vector3 coxa_pos_global_coord = ConvertRobotToGlobalCoordinate(
540 node.posture,
541 true);
542
543 if (divided_map.IsInMap(coxa_pos_global_coord)) {
544 const float coxa_top_z = (std::max)(
545 divided_map.GetTopZ(divided_map.GetDividedMapIndexX(coxa_pos_global_coord.x), divided_map.GetDividedMapIndexY(coxa_pos_global_coord.y)),
546 divided_map.GetMapMinZ());
547
548 if (coxa_top_z != divided_map.GetMapMinZ() &&
549 coxa_top_z + GetGroundHeightMarginMin() - MathConst<float>::kAllowableError > coxa_pos_global_coord.z) {
550 return true;
551 }
552 }
553
554 // 脚先の座標(グローバル)を取得する.
555 const Vector3 leg_pos_global_coord = leg_func::IsGrounded(node.leg_state, i) ?
558
559 if (divided_map.IsInMap(leg_pos_global_coord)) {
560 const float leg_top_z = (std::max)(
561 divided_map.GetTopZ(divided_map.GetDividedMapIndexX(leg_pos_global_coord.x), divided_map.GetDividedMapIndexY(leg_pos_global_coord.y)),
562 divided_map.GetMapMinZ());
563
564 if (leg_top_z != divided_map.GetMapMinZ() &&
566 return true;
567 }
568 }
569 }
570
571 return false;
572}
573
574
575std::array<float, XrR1::kMaxLegRSize> XrR1::InitMaxLegR() const {
576 // 2019年度の先行研究のコードそのまま.
577
578 // 逆運動学 coxaなしの計算結果を用いて準運動学を計算する.
579 std::array <float, kMaxLegRSize> res;
580
581 for (auto i : res) {
582 i = 0;
583 }
584
585 // 逆運動学と運動学を行った結果が半径 Permission ^ 0.5 の円の中なら等しいと考える.
586 const float PERMISSION = 0.5f;
587
588
589 // 脚可動範囲 おそらく rad 変換したやつ(-81.8° -101.98° -68.41°) 190527
590 const float mins[3] = { -1.428f, -1.780f, -1.194f };
591
592 // 左から coxa, femur, tibia (80.32° 99.92° 101.36°)
593 const float maxes[3] = { 1.402f, 1.744f, 1.769f };
594
595 // ans of kinematics use solution of i_kinematics.
596
597 // zは最大196.ixは最大248.
598 for (int iz = 0; iz < 200; iz++) {
599 for (int ix = 53; ix < 248; ix++) {
600 // 脚先座標(ローカル)
601 const Vector3 line_end(static_cast<float>(ix), 0.0f, static_cast<float>(iz));
602
603 // 逆運動学 coxa なし.
604
605 // const float _coxa_angle = atan2(line_end.x, line_end.y); // coxa角度.
606
607 // femurから足先までを結ぶベクトルをxy平面に投影したときのベクトルの大きさ.
608 const float _IK_trueX = sqrt(math_util::Squared(line_end.x) +
609 math_util::Squared(line_end.y)) -
611
612 // 絶対に正.
613 float _im = sqrt(math_util::Squared(_IK_trueX) + math_util::Squared(line_end.z));
614
615 if (_im == 0.0f) {
616 // 0割り対策.
617 _im += 0.01f;
618 }
619
620 // マイナスでおk座標系的にq1自体は常に負.xがゼロだと定義域エラー.
621 const float _q1 = -atan2(line_end.z, _IK_trueX);
622
623 // im = 0 だと定義域エラー.
624 const float _q2 = acos(
627 (2.0f * XrR1Const::kFemurLength * _im));
628
629 const float _femur_angle = _q1 + _q2;
630 const float _tibia_angle = acos(
633 math_util::Squared(_im)) /
635 std::numbers::pi_v<float> / 2.0f;
636
637 // 運動学
638 const float _K_trueX = XrR1Const::kFemurLength * cos(_femur_angle) +
640 cos(_femur_angle + _tibia_angle - std::numbers::pi_v<float> / 2.0f);
641
642 Vector3 _kinematics;
643 _kinematics.x = _K_trueX + XrR1Const::kCoxaLength;
644 _kinematics.y = 0.0f;
645 _kinematics.z =
646 -(XrR1Const::kFemurLength * sin(_femur_angle) +
648 sin(_femur_angle + _tibia_angle - std::numbers::pi_v<float> / 2.0f));
649
650 const float _Permission = (_kinematics - line_end).GetSquaredLength();
651
652 if (PERMISSION > _Permission) {
653 constexpr float kLegRom_RMargin = 2.f;
654
655 // y = 0のとき,脚高さzのときのx方向の最大の範囲.
656 res[iz] = static_cast<float>(ix) - kLegRom_RMargin;
657
658#ifdef MAX_LEG_RADIUS
659 // 脚を置く位置が遠すぎるとトルクが足りなくて
660 // 沈み込みが激しいから200までにした2020/11/09 Hato
661 if (iz <= 115) {
662 res[iz] = MAX_LEG_RADIUS;
663 }
664#endif
665 }
666 }
667 }
668
669 return res;
670}
671
672std::array<Vector2, HexapodConst::kLegNum> XrR1::InitMinLegPosXY() const {
673 std::array<Vector2, HexapodConst::kLegNum> res;
674
675 for (int i = 0; i < HexapodConst::kLegNum; i++) {
676 const float angle = kMovableCoxaAngleMin + XrR1Const::kCoxaDefaultAngle[i];
677 res[i] = Vector2(cos(angle), sin(angle)).GetNormalized();
678 }
679
680 return res;
681}
682
683std::array<Vector2, HexapodConst::kLegNum> XrR1::InitMaxLegPosXY() const {
684 std::array<Vector2, HexapodConst::kLegNum> res;
685
686 for (int i = 0; i < HexapodConst::kLegNum; i++) {
687 const float angle = kMovableCoxaAngleMax + XrR1Const::kCoxaDefaultAngle[i];
688 res[i] = Vector2(cos(angle), sin(angle)).GetNormalized();
689 }
690
691 return res;
692}
693
694} // namespace designlab
マップを格子状に分割して管理するクラス.
constexpr bool IsInMap(const float x, const float y) const noexcept
指定した座標がマップの範囲内に存在するかどうかを返す.
constexpr int GetDividedMapIndexX(const float pos_x) const noexcept
指定した座標を DividedMap のインデックスに変換する. 範囲外の値を指定した場合でも,値を丸めずに返す. そのため,IsInMap で範囲内に存在するかどうかを確認する必要がある.
constexpr int GetDividedMapIndexY(const float pos_y) const noexcept
指定した座標を DividedMap のインデックスに変換する. 範囲外の値を指定した場合でも,値を丸めずに返す. そのため,IsInMap で範囲内に存在するかどうかを確認する必要がある.
float GetTopZ(int x_index, int y_index) const
格子状に切り分けられたマップから,最も高いZ座標を返す.
float GetMapMinZ() const noexcept
static constexpr int kLegNum
static constexpr float kCoxaBaseOffsetX
coxa linkの付け根までの長さ(上方向)[mm].
Definition xr_r1_const.h:76
static constexpr bool IsValidCoxaAngle(const int leg_index, const float angle) noexcept
第1関節の角度が有効な範囲内かどうかを判定する.
Definition xr_r1_const.h:89
static constexpr std::array< float, kPhantomXLegNum > kCoxaDefaultAngle
第1関節の初期角度[rad]
Definition xr_r1_const.h:35
static constexpr float kFemurLength
第2関節部の長さ[mm].
Definition xr_r1_const.h:66
static constexpr float kCoxaBaseOffsetY
coxa linkの付け根(中央)までの長さ[mm].
Definition xr_r1_const.h:70
static constexpr float kCoxaLength
第1関節部の長さ[mm].
Definition xr_r1_const.h:65
static constexpr bool IsValidFemurAngle(const float angle) noexcept
第2関節の角度が有効な範囲内かどうかを判定する.
static constexpr float kTibiaLength
第3関節部の長さ[mm].
Definition xr_r1_const.h:67
static constexpr float kCoxaBaseOffsetZ
胴体の高さ[mm].
Definition xr_r1_const.h:79
static constexpr bool IsValidTibiaAngle(const float angle) noexcept
第3関節の角度が有効な範囲内かどうかを判定する.
static constexpr float kCenterCoxaBaseOffsetY
coxa linkの付け根(前方・後方)までの長さ[mm].
Definition xr_r1_const.h:73
bool IsStable(const leg_func::LegStateBit &leg_state, const std::array< Vector3, HexapodConst::kLegNum > &leg_pos) const override
安定余裕を用いて,静的に安定しているかどうかを判定する.
Definition xr_r1.cpp:514
float GetGroundHeightMarginMax() const noexcept override
地面の最大高さと重心位置を最大どれだけ離すかを返す.
Definition xr_r1.cpp:463
XrR1(const XrR1ParameterRecord &parameter_record)
Definition xr_r1.cpp:22
bool IsLegInterfering(const std::array< Vector3, HexapodConst::kLegNum > &leg_pos) const override
脚が他の脚と干渉しているかどうかを判定する.
Definition xr_r1.cpp:427
float GetGroundHeightMarginMin() const noexcept override
地面の最大高さと重心位置を最小どれだけ離すかを返す.
Definition xr_r1.cpp:459
Vector3 GetFreeLegPosLegCoordinate(int leg_index) const noexcept override
遊脚する位置を返す,脚座標系.
Definition xr_r1.cpp:368
bool IsBodyInterferingWithGround(const RobotStateNode &node, const DividedMapState &devide_map) const override
胴体が地面と干渉しているかどうかを判定する.
Definition xr_r1.cpp:520
bool IsValidJointState(const int leg_index, const Vector3 &leg_pos, const HexapodJointState &joint_state) const noexcept override
指定した脚のHexapodJointStateが正しく計算できているかを調べる. 目標座標に届かない場合や,間接の可動範囲外まで動いてしまう場合, 戻り値は false になる.
Definition xr_r1.cpp:258
HexapodJointState CalculateJointState(const int leg_index, const Vector3 &leg_pos) const noexcept override
指定した脚の関節のグローバル座標と,角度を計算する. 重たいのでグラフ探索や,描画処理中にループで使用することは推奨しない. 間接の可動範囲外まで動いてしまう場合でも,...
Definition xr_r1.cpp:52
Vector3 ConvertGlobalToLegCoordinate(const Vector3 &converted_position, int leg_index, const Vector3 &center_of_mass_global, const Quaternion &robot_quat, const bool consider_rot) const override
グローバル座標系で表現されている座標を,脚座標系に変換する.
Definition xr_r1.cpp:302
float CalculateStabilityMargin(const leg_func::LegStateBit &leg_state, const std::array< Vector3, HexapodConst::kLegNum > &leg_pos) const override
安定余裕(Stability Margin)を計算する. 詳しくは「不整地における歩行機械の静的安定性評価基準」 という論文を読んで欲しい. 接地脚を繋いで作られる多角形の辺と重心の距離の最小値を計...
Definition xr_r1.cpp:467
Vector3 ConvertLegToRobotCoordinate(const Vector3 &converted_position, int leg_index) const
脚座標系で表現されている座標を,ロボット座標系に変換する.
Definition xr_r1.cpp:362
bool IsLegInRange(int leg_index, const Vector3 &leg_pos) const override
脚が可動範囲内にあるかどうかを判定する.
Definition xr_r1.cpp:385
Vector3 GetLegBasePosRobotCoordinate(int leg_index) const noexcept override
脚の付け根の座標(leg base position )を取得する.ロボット座標系.
Definition xr_r1.cpp:376
Vector3 ConvertRobotToGlobalCoordinate(const Vector3 &converted_position, const Vector3 &center_of_mass_global, const Quaternion &robot_quat, const bool consider_rot) const override
ロボット座標系で表現されている座標を,グローバル座標系に変換する.
Definition xr_r1.cpp:344
Vector3 ConvertRobotToLegCoordinate(const Vector3 &converted_position, int leg_index) const
ロボット座標系で表現されている座標を,脚座標系に変換する.
Definition xr_r1.cpp:357
Vector3 ConvertLegToGlobalCoordinate(const Vector3 &converted_position, int leg_index, const Vector3 &center_of_mass_global, const Quaternion &robot_quat, const bool consider_rot) const override
脚座標系で表現されている座標を,グローバル座標系に変換する.
Definition xr_r1.cpp:324
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
std::bitset< kLegStateBitNum > LegStateBit
脚状態を保存する型.28bitのビット型.
Definition leg_state.h:55
constexpr bool CanMakeTriangle(const T a, const T b, const T c) noexcept
3辺で三角形が作れるか調べる関数.
Definition math_util.h:65
constexpr bool IsEqual(const T num1, const T num2) noexcept
C++において,小数同士の計算は誤差が出てしまう. 誤差込みで値が等しいか調べる.
Definition math_util.h:42
constexpr T Squared(const T num) noexcept
2乗した値を返す関数.
Definition math_util.h:55
Vector3 RotateVector3(const Vector3 &vec, const EulerXYZ &rot)
回転させたベクトルを返す.三角関数の処理が多く重たいので注意.
ロボットの関節の状態を表す構造体.
bool is_in_range
目標座標に脚が届かないならば false になる.
2次元の線分を表す構造体.
bool HasIntersection(const LineSegment2 &other) const
他の線分と交点が存在しているかどうか調べる関数.
float 型と double 型の定数を提供するクラス.
Definition math_const.h:22
クォータニオンを表す構造体.
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
このベクトルを正規化したベクトルを返す.
constexpr float GetSquaredLength() const noexcept
このベクトルの長さの2乗を返す.
constexpr float Cross(const Vector2 &other) const noexcept
自分×引数 の外積の結果を返す.
float GetLength() const
このベクトルの長さを返す.
3次元の位置ベクトルを表す構造体.
float x
ロボットの正面方向に正.
constexpr float GetSquaredLength() const noexcept
ベクトルの長さの2乗を返す.
float z
ロボットの上向きに正.
float GetLength() const noexcept
ベクトルの長さを返す.
constexpr Vector2 ProjectedXY() const noexcept
XY平面に射影したベクトルを返す.
float y
ロボットの左向きに正.