19 const std::shared_ptr<const IHexapodCoordinateConverter>& converter_ptr) :
20 converter_ptr_(converter_ptr)
28 if (IsNoChange(current_node, next_node))
33 if (IsBodyRot(current_node, next_node))
35 return CreateBodyRotInterpolatedNode(current_node, next_node);
38 if (IsBodyMove(current_node, next_node))
40 return CreateBodyMoveInterpolatedNode(current_node, next_node);
43 return CreateLegMoveInterpolatedNode(current_node, next_node);
46bool InterpolatedNodeCreator::IsNoChange(
const RobotStateNode& current_node,
73bool InterpolatedNodeCreator::IsBodyMove(
const RobotStateNode& current_node,
74 const RobotStateNode& next_node)
const
76 return current_node.center_of_mass_global_coord != next_node.center_of_mass_global_coord;
79bool InterpolatedNodeCreator::IsBodyRot(
const RobotStateNode& current_node,
80 const RobotStateNode& next_node)
const
82 return current_node.posture.GetNormalized() != next_node.posture.GetNormalized();
85std::vector<RobotStateNode> InterpolatedNodeCreator::CreateBodyMoveInterpolatedNode(
86 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const
88 std::vector<RobotStateNode> res;
90 const Vector3 dif = next_node.center_of_mass_global_coord - current_node.center_of_mass_global_coord;
92 if (dif.GetLength() < kInterpolatedDistance) {
return {}; }
94 if (dif.GetLength() > kBodyMoveMaxInterpolatedDistance) {
return {}; }
98 while (kInterpolatedDistance *
static_cast<float>(cnt) < dif.GetLength())
100 RobotStateNode temp_node = current_node;
102 temp_node.ChangeGlobalCenterOfMass(
103 temp_node.center_of_mass_global_coord + dif.GetNormalized() * kInterpolatedDistance *
static_cast<float>(cnt),
106 res.push_back(temp_node);
114std::vector<RobotStateNode> InterpolatedNodeCreator::CreateBodyRotInterpolatedNode(
115 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const
117 std::vector<RobotStateNode> res;
119 constexpr int kBodyMoveInterpolatedNodeNum = 100;
121 for (
int i = 0; i < kBodyMoveInterpolatedNodeNum; i++)
123 RobotStateNode temp_node = current_node;
124 const float ex = (
static_cast<float>(i) + 1.0f) /
125 (
static_cast<float>(kBodyMoveInterpolatedNodeNum));
127 const Quaternion quat =
130 temp_node.ChangePosture(converter_ptr_, quat);
132 res.push_back(temp_node);
138std::vector<RobotStateNode> InterpolatedNodeCreator::CreateLegMoveInterpolatedNode(
139 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const
141 std::vector<RobotStateNode> res;
147 std::vector<int> ground_move_index = GetGroundMoveIndex(current_node, next_node);
152 RobotStateNode temp_node = res.empty() ? current_node : res.back();
156 for (
const auto& i : ground_move_index)
159 const float angle_current = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
160 const float angle_next = atan2(next_node.leg_pos[i].y, next_node.leg_pos[i].x);
162 if (angle_current > angle_next + kInterpolatedAngle)
164 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
165 temp_node.leg_pos[i].x = length * cos(angle_current - kInterpolatedAngle);
166 temp_node.leg_pos[i].y = length * sin(angle_current - kInterpolatedAngle);
169 else if (angle_current < angle_next - kInterpolatedAngle)
171 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
172 temp_node.leg_pos[i].x = length * cos(angle_current + kInterpolatedAngle);
173 temp_node.leg_pos[i].y = length * sin(angle_current + kInterpolatedAngle);
178 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
179 temp_node.leg_pos[i].x = length * cos(angle_next);
180 temp_node.leg_pos[i].y = length * sin(angle_next);
184 const float length_current = temp_node.leg_pos[i].ProjectedXY().GetLength();
185 const float length_next = next_node.leg_pos[i].ProjectedXY().GetLength();
187 if (length_current > length_next + kInterpolatedDistance)
189 const float angle = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
190 temp_node.leg_pos[i].x = (length_current - kInterpolatedDistance) * cos(angle);
191 temp_node.leg_pos[i].y = (length_current - kInterpolatedDistance) * sin(angle);
194 else if (length_current < length_next - kInterpolatedDistance)
196 const float angle = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
197 temp_node.leg_pos[i].x = (length_current + kInterpolatedDistance) * cos(angle);
198 temp_node.leg_pos[i].y = (length_current + kInterpolatedDistance) * sin(angle);
203 const float angle = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
204 temp_node.leg_pos[i].x = length_next * cos(angle);
205 temp_node.leg_pos[i].y = length_next * sin(angle);
209 res.push_back(temp_node);
211 if (is_end) {
break; }
218 RobotStateNode temp_node = res.back();
222 for (
const auto& i : ground_move_index)
224 if (temp_node.leg_pos[i].z > next_node.leg_pos[i].z + kInterpolatedDistance)
226 temp_node.leg_pos[i].z -= kInterpolatedDistance;
229 else if (temp_node.leg_pos[i].z < next_node.leg_pos[i].z - kInterpolatedDistance)
231 temp_node.leg_pos[i].z += kInterpolatedDistance;
236 temp_node.leg_pos[i].z = next_node.leg_pos[i].z;
241 res.push_back(temp_node);
243 if (is_end) {
break; }
250 std::vector<int> free_move_index = GetFreeMoveIndex(current_node, next_node);
256 RobotStateNode temp_node = res.back();
260 for (
const auto& i : free_move_index)
262 if (temp_node.leg_pos[i].z > next_node.leg_pos[i].z + kInterpolatedDistance)
264 temp_node.leg_pos[i].z -= kInterpolatedDistance;
267 else if (temp_node.leg_pos[i].z < next_node.leg_pos[i].z - kInterpolatedDistance)
269 temp_node.leg_pos[i].z += kInterpolatedDistance;
274 temp_node.leg_pos[i].z = next_node.leg_pos[i].z;
279 res.push_back(temp_node);
281 if (is_end) {
break; }
287 RobotStateNode temp_node = res.empty() ? current_node : res.back();
291 for (
const auto& i : free_move_index)
294 const float angle_current = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
295 const float angle_next = atan2(next_node.leg_pos[i].y, next_node.leg_pos[i].x);
297 if (angle_current > angle_next + kInterpolatedAngle)
299 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
300 temp_node.leg_pos[i].x = length * cos(angle_current - kInterpolatedAngle);
301 temp_node.leg_pos[i].y = length * sin(angle_current - kInterpolatedAngle);
304 else if (angle_current < angle_next - kInterpolatedAngle)
306 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
307 temp_node.leg_pos[i].x = length * cos(angle_current + kInterpolatedAngle);
308 temp_node.leg_pos[i].y = length * sin(angle_current + kInterpolatedAngle);
313 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
314 temp_node.leg_pos[i].x = length * cos(angle_next);
315 temp_node.leg_pos[i].y = length * sin(angle_next);
319 const float length_current = temp_node.leg_pos[i].ProjectedXY().GetLength();
320 const float length_next = next_node.leg_pos[i].ProjectedXY().GetLength();
322 if (length_current > length_next + kInterpolatedDistance)
324 const float angle = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
325 temp_node.leg_pos[i].x = (length_current - kInterpolatedDistance) * cos(angle);
326 temp_node.leg_pos[i].y = (length_current - kInterpolatedDistance) * sin(angle);
329 else if (length_current < length_next - kInterpolatedDistance)
331 const float angle = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
332 temp_node.leg_pos[i].x = (length_current + kInterpolatedDistance) * cos(angle);
333 temp_node.leg_pos[i].y = (length_current + kInterpolatedDistance) * sin(angle);
338 const float angle = atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
339 temp_node.leg_pos[i].x = length_next * cos(angle);
340 temp_node.leg_pos[i].y = length_next * sin(angle);
344 res.push_back(temp_node);
346 if (is_end) {
break; }
353std::vector<int> InterpolatedNodeCreator::GetGroundMoveIndex(
354 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const
357 std::array<Vector3, HexapodConst::kLegNum> dif;
361 dif[i] = next_node.leg_pos[i] - current_node.leg_pos[i];
365 std::vector<int> res_index;
371 res_index.push_back(i);
378std::vector<int> InterpolatedNodeCreator::GetFreeMoveIndex(
379 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const
382 std::array<Vector3, HexapodConst::kLegNum> dif;
386 dif[i] = next_node.leg_pos[i] - current_node.leg_pos[i];
390 std::vector<int> res_index;
396 res_index.push_back(i);
static constexpr int kLegNum
std::vector< RobotStateNode > CreateInterpolatedNode(const RobotStateNode &node, const RobotStateNode &next_node) const
ノード間を補間する.
InterpolatedNodeCreator(const std::shared_ptr< const IHexapodCoordinateConverter > &converter_ptr)
void ChangeGround(const int leg_index, const bool is_ground, LegStateBit *leg_state)
脚の接地・遊脚情報を変更する.
Quaternion SlerpQuaternion(const Quaternion &q1, const Quaternion &q2, const float t)
球面線形補間を行う.
Quaternion GetNormalized() const noexcept
正規化したクォータニオンを返す. クォータニオンの正規化とは,ノルムを1にすることを表す. クォータニオンqの正規化は,q / |q| で求められる.
グラフ構造のためのノード(頂点).旧名 LNODE
std::array< Vector3, HexapodConst::kLegNum > leg_pos
[4 * 3 * 6 = 72 byte] 脚先の座標.(coxa(脚の付け根)を原点とする)
Vector3 center_of_mass_global_coord
[4 * 3 = 12byte] グローバル座標系における重心の位置.旧名 GCOM
Quaternion posture
[4 * 4 = 16byte] 姿勢を表すクォータニオン.