17 const std::shared_ptr<const IHexapodCoordinateConverter>& converter_ptr)
18 : converter_ptr_(converter_ptr) {}
22 if (IsNoChange(current_node, next_node)) {
26 if (IsBodyRot(current_node, next_node)) {
27 return CreateBodyRotInterpolatedNode(current_node, next_node);
30 if (IsBodyMove(current_node, next_node)) {
31 return CreateBodyMoveInterpolatedNode(current_node, next_node);
34 return CreateLegMoveInterpolatedNode(current_node, next_node);
37bool InterpolatedNodeCreator::IsNoChange(
60bool InterpolatedNodeCreator::IsBodyMove(
61 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const {
62 return current_node.center_of_mass_global_coord !=
63 next_node.center_of_mass_global_coord;
66bool InterpolatedNodeCreator::IsBodyRot(
const RobotStateNode& current_node,
67 const RobotStateNode& next_node)
const {
68 return current_node.posture.GetNormalized() !=
69 next_node.posture.GetNormalized();
72std::vector<RobotStateNode>
73InterpolatedNodeCreator::CreateBodyMoveInterpolatedNode(
74 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const {
75 std::vector<RobotStateNode> res;
77 const Vector3 dif = next_node.center_of_mass_global_coord -
78 current_node.center_of_mass_global_coord;
80 if (dif.GetLength() < kInterpolatedDistance) {
84 if (dif.GetLength() > kBodyMoveMaxInterpolatedDistance) {
90 while (kInterpolatedDistance *
static_cast<float>(cnt) < dif.GetLength()) {
91 RobotStateNode temp_node = current_node;
93 temp_node.ChangeGlobalCenterOfMass(
94 temp_node.center_of_mass_global_coord + dif.GetNormalized() *
95 kInterpolatedDistance *
96 static_cast<float>(cnt),
99 res.push_back(temp_node);
107std::vector<RobotStateNode>
108InterpolatedNodeCreator::CreateBodyRotInterpolatedNode(
109 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const {
110 std::vector<RobotStateNode> res;
112 constexpr int kBodyMoveInterpolatedNodeNum =
115 for (
int i = 0; i < kBodyMoveInterpolatedNodeNum; i++) {
116 RobotStateNode temp_node = current_node;
117 const float ex = (
static_cast<float>(i) + 1.0f) /
118 (
static_cast<float>(kBodyMoveInterpolatedNodeNum));
120 const Quaternion quat =
124 temp_node.ChangePosture(converter_ptr_, quat);
126 res.push_back(temp_node);
132std::vector<RobotStateNode>
133InterpolatedNodeCreator::CreateLegMoveInterpolatedNode(
134 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const {
135 std::vector<RobotStateNode> res;
141 std::vector<int> ground_move_index =
142 GetGroundMoveIndex(current_node, next_node);
146 RobotStateNode temp_node = res.empty() ? current_node : res.back();
150 for (
const auto& i : ground_move_index) {
152 const float angle_current =
153 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
154 const float angle_next =
155 atan2(next_node.leg_pos[i].y, next_node.leg_pos[i].x);
157 if (angle_current > angle_next + kInterpolatedAngle) {
158 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
159 temp_node.leg_pos[i].x =
160 length * cos(angle_current - kInterpolatedAngle);
161 temp_node.leg_pos[i].y =
162 length * sin(angle_current - kInterpolatedAngle);
164 }
else if (angle_current < angle_next - kInterpolatedAngle) {
165 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
166 temp_node.leg_pos[i].x =
167 length * cos(angle_current + kInterpolatedAngle);
168 temp_node.leg_pos[i].y =
169 length * sin(angle_current + kInterpolatedAngle);
172 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
173 temp_node.leg_pos[i].x = length * cos(angle_next);
174 temp_node.leg_pos[i].y = length * sin(angle_next);
178 const float length_current =
179 temp_node.leg_pos[i].ProjectedXY().GetLength();
180 const float length_next =
181 next_node.leg_pos[i].ProjectedXY().GetLength();
183 if (length_current > length_next + kInterpolatedDistance) {
185 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
186 temp_node.leg_pos[i].x =
187 (length_current - kInterpolatedDistance) * cos(angle);
188 temp_node.leg_pos[i].y =
189 (length_current - kInterpolatedDistance) * sin(angle);
191 }
else if (length_current < length_next - kInterpolatedDistance) {
193 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
194 temp_node.leg_pos[i].x =
195 (length_current + kInterpolatedDistance) * cos(angle);
196 temp_node.leg_pos[i].y =
197 (length_current + kInterpolatedDistance) * sin(angle);
201 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
202 temp_node.leg_pos[i].x = length_next * cos(angle);
203 temp_node.leg_pos[i].y = length_next * sin(angle);
207 res.push_back(temp_node);
218 RobotStateNode temp_node = res.back();
222 for (
const auto& i : ground_move_index) {
223 if (temp_node.leg_pos[i].z >
224 next_node.leg_pos[i].z + kInterpolatedDistance) {
225 temp_node.leg_pos[i].z -= kInterpolatedDistance;
227 }
else if (temp_node.leg_pos[i].z <
228 next_node.leg_pos[i].z - kInterpolatedDistance) {
229 temp_node.leg_pos[i].z += kInterpolatedDistance;
232 temp_node.leg_pos[i].z = next_node.leg_pos[i].z;
237 res.push_back(temp_node);
247 std::vector<int> free_move_index =
248 GetFreeMoveIndex(current_node, next_node);
254 RobotStateNode temp_node = res.back();
258 for (
const auto& i : free_move_index) {
259 if (temp_node.leg_pos[i].z >
260 next_node.leg_pos[i].z + kInterpolatedDistance) {
261 temp_node.leg_pos[i].z -= kInterpolatedDistance;
263 }
else if (temp_node.leg_pos[i].z <
264 next_node.leg_pos[i].z - kInterpolatedDistance) {
265 temp_node.leg_pos[i].z += kInterpolatedDistance;
268 temp_node.leg_pos[i].z = next_node.leg_pos[i].z;
273 res.push_back(temp_node);
282 RobotStateNode temp_node = res.empty() ? current_node : res.back();
286 for (
const auto& i : free_move_index) {
288 const float angle_current =
289 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
290 const float angle_next =
291 atan2(next_node.leg_pos[i].y, next_node.leg_pos[i].x);
293 if (angle_current > angle_next + kInterpolatedAngle) {
294 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
295 temp_node.leg_pos[i].x =
296 length * cos(angle_current - kInterpolatedAngle);
297 temp_node.leg_pos[i].y =
298 length * sin(angle_current - kInterpolatedAngle);
300 }
else if (angle_current < angle_next - kInterpolatedAngle) {
301 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
302 temp_node.leg_pos[i].x =
303 length * cos(angle_current + kInterpolatedAngle);
304 temp_node.leg_pos[i].y =
305 length * sin(angle_current + kInterpolatedAngle);
308 const float length = temp_node.leg_pos[i].ProjectedXY().GetLength();
309 temp_node.leg_pos[i].x = length * cos(angle_next);
310 temp_node.leg_pos[i].y = length * sin(angle_next);
314 const float length_current =
315 temp_node.leg_pos[i].ProjectedXY().GetLength();
316 const float length_next =
317 next_node.leg_pos[i].ProjectedXY().GetLength();
319 if (length_current > length_next + kInterpolatedDistance) {
321 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
322 temp_node.leg_pos[i].x =
323 (length_current - kInterpolatedDistance) * cos(angle);
324 temp_node.leg_pos[i].y =
325 (length_current - kInterpolatedDistance) * sin(angle);
327 }
else if (length_current < length_next - kInterpolatedDistance) {
329 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
330 temp_node.leg_pos[i].x =
331 (length_current + kInterpolatedDistance) * cos(angle);
332 temp_node.leg_pos[i].y =
333 (length_current + kInterpolatedDistance) * sin(angle);
337 atan2(temp_node.leg_pos[i].y, temp_node.leg_pos[i].x);
338 temp_node.leg_pos[i].x = length_next * cos(angle);
339 temp_node.leg_pos[i].y = length_next * sin(angle);
343 res.push_back(temp_node);
354std::vector<int> InterpolatedNodeCreator::GetGroundMoveIndex(
355 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const {
357 std::array<Vector3, HexapodConst::kLegNum> dif;
360 dif[i] = next_node.leg_pos[i] - current_node.leg_pos[i];
364 std::vector<int> res_index;
368 res_index.push_back(i);
375std::vector<int> InterpolatedNodeCreator::GetFreeMoveIndex(
376 const RobotStateNode& current_node,
const RobotStateNode& next_node)
const {
378 std::array<Vector3, HexapodConst::kLegNum> dif;
381 dif[i] = next_node.leg_pos[i] - current_node.leg_pos[i];
385 std::vector<int> res_index;
389 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| で求められる.
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] 姿勢を表すクォータニオン.