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