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_({ {
40 leg_base_pos_robot_coordinate_({ {
48 kMaxLegRArray(InitMaxLegR()),
49 kMinLegPosXY(InitMinLegPosXY()),
50 kMaxLegPosXY(InitMaxLegPosXY()),
51 kMinLegDistance(50.0) {}
54 const int leg_index,
const Vector3& leg_pos)
const noexcept {
56 assert(0 <= leg_index);
62 const int kJointNum = 4;
63 const int kJointAngleNum = kJointNum - 1;
80 float coxa_joint_angle = std::atan2f(leg_pos.y, leg_pos.x);
82 if (leg_pos.y == 0 && leg_pos.x == 0) {
89 leg_index, coxa_joint_angle + std::numbers::pi_v<float>)) {
90 coxa_joint_angle += std::numbers::pi_v<float>;
93 leg_index, coxa_joint_angle - std::numbers::pi_v<float>)) {
94 coxa_joint_angle -= std::numbers::pi_v<float>;
116 const float angle_ft = std::atan2(
117 leg_pos.z - femur_joint_pos.
z,
118 (leg_pos.ProjectedXY() - femur_joint_pos.
ProjectedXY()).GetLength());
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;
136 const Vector3 candidate_leg_pos_phase = femur_joint_pos +
Vector3{
149 const float distance = (leg_pos - candidate_leg_pos).GetLength();
150 const float distance_phase = (leg_pos - candidate_leg_pos_phase).GetLength();
152 float angle_f = 0, angle_t = 0;
154 if (distance < distance_phase) {
159 angle_f = angle_ft_phase;
160 angle_t = -std::numbers::pi_v<float>;
200 const float femur_to_leg_x =
202 ((leg_pos.ProjectedXY().GetSquaredLength() >
205 const float femur_to_leg_z = femur_to_leg.
z;
208 const float arc_cos_upper =
216 const float arc_cos_arg = arc_cos_upper / arc_cos_lower;
219 const float femur_joint_angle =
220 std::acos(arc_cos_arg) +
221 std::atan2(femur_to_leg_z, femur_to_leg_x);
246 const float tibia_angle = std::atan2(
262 assert(joint_state.joint_pos_leg_coordinate.size() == 4);
263 assert(joint_state.joint_angle.size() == 3);
297 if (joint_state.joint_pos_leg_coordinate[3] != leg_pos) {
return false; }
304 const Vector3& converted_position,
306 const Vector3& center_of_mass_global,
308 const bool consider_rot)
const {
310 assert(0 <= leg_index);
314 return RotateVector3(converted_position - center_of_mass_global,
319 return converted_position -
320 center_of_mass_global -
326 const Vector3& converted_position,
328 const Vector3& center_of_mass_global,
330 const bool consider_rot)
const {
332 assert(0 <= leg_index);
337 robot_quat) + center_of_mass_global;
340 return converted_position +
346 const Vector3& converted_position,
347 const Vector3& center_of_mass_global,
349 const bool consider_rot)
const {
351 return RotateVector3(converted_position, robot_quat) + center_of_mass_global;
354 return converted_position + center_of_mass_global;
359 const int leg_index)
const {
364 const int leg_index)
const {
371 assert(0 <= leg_index);
374 return free_leg_pos_leg_coordinate_[leg_index];
379 assert(0 <= leg_index);
382 return leg_base_pos_robot_coordinate_[leg_index];
388 assert(0 <= leg_index);
398 if (kMinLegPosXY[leg_index].Cross(leg_pos_xy) < 0.0f) {
402 if (kMaxLegPosXY[leg_index].Cross(leg_pos_xy) > 0.0f) {
408 if (
static_cast<int>(leg_pos.
z) < -kMaxLegRSize || 0 <
static_cast<int>(leg_pos.
z)) {
429 const std::array<Vector3, HexapodConst::kLegNum>& leg_pos)
const {
461 return kBodyLiftingHeightMin;
465 return kBodyLiftingHeightMax;
470 const std::array<Vector3, HexapodConst::kLegNum>& leg_pos)
const {
475 std::array<Vector2, HexapodConst::kLegNum> ground_leg_pos;
478 int ground_leg_pos_num = 0;
484 ground_leg_pos[ground_leg_pos_num] = leg_pos[i].ProjectedXY() +
487 ground_leg_pos_num++;
492 float min_margin = 0;
493 bool is_first =
true;
495 for (
int i = 0; i < ground_leg_pos_num; i++)
497 Vector2 i_to_i_plus_1 = ground_leg_pos[(i + 1) % ground_leg_pos_num] -
511 min_margin = (std::min)(min_margin, margin);
519 const std::array<Vector3, HexapodConst::kLegNum>& leg_pos)
const
530 const float top_z = (std::max)(
552 if (devide_map.
IsInMap(coxa_pos_global_coord))
554 const float coxa_top_z = (std::max)(
570 if (devide_map.
IsInMap(leg_pos_global_coord))
572 const float leg_top_z = (std::max)(
588std::array<float, PhantomXMkII::kMaxLegRSize> PhantomXMkII::InitMaxLegR()
const
593 std::array <float, kMaxLegRSize> res;
601 const float PERMISSION = 0.5f;
605 const float mins[3] = { -1.428f, -1.780f, -1.194f };
608 const float maxes[3] = { 1.402f, 1.744f, 1.769f };
613 for (
int iz = 0; iz < 200; iz++)
615 for (
int ix = 53; ix < 248; ix++)
618 const Vector3 line_end(
static_cast<float>(ix), 0.0f,
static_cast<float>(iz));
639 const float _q1 = -atan2(line_end.z, _IK_trueX);
642 const float _q2 = acos(
647 const float _femur_angle = _q1 + _q2;
648 const float _tibia_angle = acos(
653 std::numbers::pi_v<float> / 2.0f;
658 cos(_femur_angle + _tibia_angle - std::numbers::pi_v<float> / 2.0f);
662 _kinematics.y = 0.0f;
666 sin(_femur_angle + _tibia_angle - std::numbers::pi_v<float> / 2.0f));
668 const float _Permission = (_kinematics - line_end).GetSquaredLength();
670 if (PERMISSION > _Permission)
672 constexpr float kLegRom_RMargin = 2.f;
675 res[iz] =
static_cast<float>(ix) - kLegRom_RMargin;
682 res[iz] = MAX_LEG_RADIUS;
692std::array<Vector2, HexapodConst::kLegNum> PhantomXMkII::InitMinLegPosXY()
const
694 std::array<Vector2, HexapodConst::kLegNum> res;
699 res[i] = Vector2(cos(angle), sin(angle)).GetNormalized();
705std::array<Vector2, HexapodConst::kLegNum> PhantomXMkII::InitMaxLegPosXY()
const
707 std::array<Vector2, HexapodConst::kLegNum> res;
712 res[i] = Vector2(cos(angle), sin(angle)).GetNormalized();
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 ¢er_of_mass_global, const Quaternion &robot_quat, const bool consider_rot) const override
脚座標系で表現されている座標を,グローバル座標系に変換する.
Vector3 ConvertGlobalToLegCoordinate(const Vector3 &converted_position, int leg_index, const Vector3 ¢er_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 ¶meter_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 ¢er_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番.
std::bitset< kLegStateBitNum > LegStateBit
脚状態を保存する型.28bitのビット型.
constexpr bool CanMakeTriangle(const T a, const T b, const T c) noexcept
3辺で三角形が作れるか調べる関数.
constexpr bool IsEqual(const T num1, const T num2) noexcept
C++において,小数同士の計算は誤差が出てしまう. 誤差込みで値が等しいか調べる.
constexpr T Squared(const T num) noexcept
2乗した値を返す関数.
Vector3 RotateVector3(const Vector3 &vec, const EulerXYZ &rot)
回転させたベクトルを返す.三角関数の処理が多く重たいので注意.
std::vector< Vector3 > joint_pos_leg_coordinate
bool is_in_range
目標座標に脚が届かないならば false になる.
std::vector< float > joint_angle
bool HasIntersection(const LineSegment2 &other) const
他の線分と交点が存在しているかどうか調べる関数.
float 型と double 型の定数を提供するクラス.
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] 姿勢を表すクォータニオン.
Vector2 GetNormalized() const
このベクトルを正規化したベクトルを返す.
constexpr float GetSquaredLength() const noexcept
このベクトルの長さの2乗を返す.
constexpr float Cross(const Vector2 &other) const noexcept
自分×引数 の外積の結果を返す.
float GetLength() const
このベクトルの長さを返す.
constexpr float GetSquaredLength() const noexcept
ベクトルの長さの2乗を返す.
float GetLength() const noexcept
ベクトルの長さを返す.
constexpr Vector2 ProjectedXY() const noexcept
XY平面に射影したベクトルを返す.