00001 #include "PositionPath.h"
00002
00003 PositionPath::PositionPath ()
00004 {
00005 Initialize ();
00006 }
00007
00008 PositionPath::~PositionPath ()
00009 {
00010 DeletePath ();
00011 }
00012
00013 void PositionPath::Initialize ()
00014 {
00015 is_constant = false;
00016 has_dynamic_rotation = false;
00017 has_static_rotation = false;
00018 first_node = NULL;
00019 current_node = NULL;
00020 not_complete = false;
00021 node_pointer = NULL;
00022
00023 constant_position.x = 0.0f;
00024 constant_position.y = 0.0f;
00025 constant_position.z = 0.0f;
00026 constant_position.roll = 0.0f;
00027 constant_position.pitch = 0.0f;
00028 constant_position.yaw = 0.0f;
00029
00030 translation_box.xmin = 0.0f;
00031 translation_box.xmax = 0.0f;
00032 translation_box.ymin = 0.0f;
00033 translation_box.ymax = 0.0f;
00034 translation_box.zmin = 0.0f;
00035 translation_box.zmax = 0.0f;
00036 }
00037
00038 void PositionPath::SetConstantPosition (float x, float y, float z, float roll, float pitch, float yaw)
00039 {
00040 DeletePath ();
00041
00042 constant_position.x = x;
00043 constant_position.y = y;
00044 constant_position.z = z;
00045 constant_position.roll = roll;
00046 constant_position.pitch = pitch;
00047 constant_position.yaw = yaw;
00048
00049 translation_box.xmin = x;
00050 translation_box.xmax = x;
00051 translation_box.ymin = y;
00052 translation_box.ymax = y;
00053 translation_box.zmin = z;
00054 translation_box.zmax = z;
00055
00056 is_constant = true;
00057 has_dynamic_rotation = false;
00058 if (roll == 0.0f && pitch == 0.0f && yaw == 0.0f)
00059 {has_static_rotation = false;}
00060 else
00061 {has_static_rotation = true;}
00062 }
00063
00064 void PositionPath::AddCheckpoint (float x, float y, float z, float roll, float pitch, float yaw)
00065 {
00066 PathNode * temp;
00067
00068 if (not_complete)
00069 {
00070
00071 current_node->end_position.x = x;
00072 current_node->end_position.y = y;
00073 current_node->end_position.z = z;
00074 current_node->end_position.roll = roll;
00075 current_node->end_position.pitch = pitch;
00076 current_node->end_position.yaw = yaw;
00077
00078 if (x > translation_box.xmax) translation_box.xmax = x;
00079 if (x < translation_box.xmin) translation_box.xmin = x;
00080 if (y > translation_box.ymax) translation_box.ymax = y;
00081 if (y < translation_box.ymin) translation_box.ymin = y;
00082 if (z > translation_box.zmax) translation_box.zmax = z;
00083 if (z < translation_box.zmin) translation_box.zmin = z;
00084
00085 if (current_node->start_position.roll != current_node->end_position.roll ||
00086 current_node->start_position.pitch != current_node->end_position.pitch ||
00087 current_node->start_position.yaw != current_node->end_position.yaw)
00088 {
00089 has_dynamic_rotation = true;
00090 has_static_rotation = true;
00091 }
00092
00093
00094 ConservativeUpdate (current_node);
00095
00096 temp = current_node;
00097
00098 current_node->next = new PathNode;
00099 current_node->next->start_time = current_node->end_time;
00100 current_node->next->start_position = current_node->end_position;
00101 current_node = current_node->next;
00102 current_node->next = NULL;
00103 current_node->previous = temp;
00104 current_node->end_time = current_node->start_time + 1000;
00105 }
00106 else
00107 {printf ("Path Construction: You have to start a new path before adding a checkpoint (AddCheckpoint)\n"); return;}
00108 }
00109
00110 void PositionPath::StartPath (int offset, float x, float y, float z, float roll, float pitch, float yaw)
00111 {
00112 PathNode * temp;
00113
00114 if (not_complete)
00115 {printf ("Path Construction: You have to complete the current path before starting a new one (StartPath)\n"); return;}
00116
00117 not_complete = true;
00118 is_constant = false;
00119
00120 if (first_node == NULL)
00121 {
00122 first_node = new PathNode;
00123 current_node = first_node;
00124 temp = NULL;
00125
00126 translation_box.xmin = x;
00127 translation_box.xmax = x;
00128 translation_box.ymin = y;
00129 translation_box.ymax = y;
00130 translation_box.zmin = z;
00131 translation_box.zmax = z;
00132 }
00133 else
00134 {
00135 current_node->next = new PathNode;
00136 temp = current_node;
00137 current_node = current_node->next;
00138
00139 if (x > translation_box.xmax) translation_box.xmax = x;
00140 if (x < translation_box.xmin) translation_box.xmin = x;
00141 if (y > translation_box.ymax) translation_box.ymax = y;
00142 if (y < translation_box.ymin) translation_box.ymin = y;
00143 if (z > translation_box.zmax) translation_box.zmax = z;
00144 if (z < translation_box.zmin) translation_box.zmin = z;
00145 }
00146
00147 current_node->next = NULL;
00148 current_node->previous = temp;
00149 current_node->start_position.x = x;
00150 current_node->start_position.y = y;
00151 current_node->start_position.z = z;
00152 current_node->start_position.roll = roll;
00153 current_node->start_position.pitch = pitch;
00154 current_node->start_position.yaw = yaw;
00155 current_node->start_time = (current_node->previous == NULL ? offset : current_node->previous->end_time + offset);
00156 current_node->end_time = current_node->start_time + 1000;
00157
00158 if (roll != 0.0f || pitch != 0.0f || yaw != 0.0f)
00159 {has_static_rotation = true;}
00160
00161 if (current_node->previous != NULL)
00162 {
00163 if (current_node->start_position.roll != current_node->previous->end_position.roll ||
00164 current_node->start_position.pitch != current_node->previous->end_position.pitch ||
00165 current_node->start_position.yaw != current_node->previous->end_position.yaw)
00166 {has_dynamic_rotation = true;}
00167 }
00168 }
00169
00170 void PositionPath::CompletePath (float x, float y, float z, float roll, float pitch, float yaw)
00171 {
00172 if (!not_complete)
00173 {printf ("Path Construction: You have to start a new path before it can be completed (CompletePath)\n"); return;}
00174
00175 current_node->end_position.x = x;
00176 current_node->end_position.y = y;
00177 current_node->end_position.z = z;
00178 current_node->end_position.roll = roll;
00179 current_node->end_position.pitch = pitch;
00180 current_node->end_position.yaw = yaw;
00181
00182 if (x > translation_box.xmax) translation_box.xmax = x;
00183 if (x < translation_box.xmin) translation_box.xmin = x;
00184 if (y > translation_box.ymax) translation_box.ymax = y;
00185 if (y < translation_box.ymin) translation_box.ymin = y;
00186 if (z > translation_box.zmax) translation_box.zmax = z;
00187 if (z < translation_box.zmin) translation_box.zmin = z;
00188
00189 if (current_node->start_position.roll != current_node->end_position.roll ||
00190 current_node->start_position.pitch != current_node->end_position.pitch ||
00191 current_node->start_position.yaw != current_node->end_position.yaw)
00192 {
00193 has_dynamic_rotation = true;
00194 has_static_rotation = true;
00195 }
00196
00197
00198 ConservativeUpdate (current_node);
00199
00200 not_complete = false;
00201 }
00202
00203 BoundingBox PositionPath::GetTranslationBox ()
00204 {
00205 return translation_box;
00206 }
00207
00208 void PositionPath::Shift (float x, float y, float z)
00209 {
00210 if (is_constant)
00211 {
00212 constant_position.x += x;
00213 constant_position.y += y;
00214 constant_position.z += z;
00215 }
00216 else
00217 {
00218 PathNode * current_node;
00219
00220 current_node = first_node;
00221 while (current_node != NULL)
00222 {
00223 current_node->start_position.x += x;
00224 current_node->start_position.y += y;
00225 current_node->start_position.z += z;
00226 current_node->end_position.x += x;
00227 current_node->end_position.y += y;
00228 current_node->end_position.z += z;
00229 current_node = current_node->next;
00230 }
00231 }
00232
00233 translation_box.xmax += x;
00234 translation_box.xmin += x;
00235 translation_box.ymax += y;
00236 translation_box.ymin += y;
00237 translation_box.zmax += z;
00238 translation_box.zmin += z;
00239 }
00240
00241 void PositionPath::ConservativeUpdate (PathNode * node)
00242 {
00243 float temp;
00244 bool update_x, update_y, update_z;
00245
00246 update_x = false;
00247 update_y = false;
00248 update_z = false;
00249
00250
00251 if (node->global_transition_evaluator)
00252 {
00253 if ((node->transition_evaluator[0] == PP_SINE && node->transition_parameter[0] != 0.0f) ||
00254 (node->transition_evaluator[0] == PP_COSINE && node->transition_parameter[0] != 0.0f))
00255 {
00256 update_x = true;
00257 update_y = true;
00258 update_z = true;
00259 }
00260 }
00261 else
00262 {
00263 if ((node->transition_evaluator[0] == PP_SINE && node->transition_parameter[0] != 0.0f) ||
00264 (node->transition_evaluator[0] == PP_COSINE && node->transition_parameter[0] != 0.0f))
00265 {update_x = true;}
00266
00267 if ((node->transition_evaluator[1] == PP_SINE && node->transition_parameter[1] != 0.0f) ||
00268 (node->transition_evaluator[1] == PP_COSINE && node->transition_parameter[1] != 0.0f))
00269 {update_y = true;}
00270
00271 if ((node->transition_evaluator[2] == PP_SINE && node->transition_parameter[2] != 0.0f) ||
00272 (node->transition_evaluator[2] == PP_COSINE && node->transition_parameter[2] != 0.0f))
00273 {update_z = true;}
00274 }
00275
00276
00277 if (update_x)
00278 {
00279 temp = node->start_position.x - (node->end_position.x - node->start_position.x);
00280 if (translation_box.xmin > temp) translation_box.xmin = temp;
00281 if (translation_box.xmax < temp) translation_box.xmax = temp;
00282 }
00283
00284 if (update_y)
00285 {
00286 temp = node->start_position.y - (node->end_position.y - node->start_position.y);
00287 if (translation_box.ymin > temp) translation_box.ymin = temp;
00288 if (translation_box.ymax < temp) translation_box.ymax = temp;
00289 }
00290
00291 if (update_z)
00292 {
00293 temp = node->start_position.z - (node->end_position.z - node->start_position.z);
00294 if (translation_box.zmin > temp) translation_box.zmin = temp;
00295 if (translation_box.zmax < temp) translation_box.zmax = temp;
00296 }
00297 }
00298
00299 void PositionPath::DeletePath ()
00300 {
00301 PathNode * curr_node;
00302 PathNode * to_be_deleted;
00303
00304
00305 curr_node = first_node;
00306 while (curr_node != NULL)
00307 {
00308 to_be_deleted = curr_node;
00309 curr_node = curr_node->next;
00310 delete to_be_deleted;
00311 }
00312
00313
00314 Initialize ();
00315 }
00316
00317 void PositionPath::SetDuration (int time)
00318 {
00319 if (!not_complete)
00320 {printf ("Path Construction: You have to start a new path first (SetDuration)\n"); return;}
00321
00322 current_node->end_time = current_node->start_time + time;
00323 }
00324
00325 void PositionPath::SetGlobalTransition (int mode, float parameter)
00326 {
00327 if (!not_complete)
00328 {printf ("Path Construction: You have to start a new path before setting a transition. (SetGlobalTransition)\n"); return;}
00329
00330 current_node->global_transition_evaluator = true;
00331 current_node->transition_evaluator[0] = mode;
00332 current_node->transition_parameter[0] = parameter;
00333 }
00334
00335 void PositionPath::SetTransitionModes (int m_x, int m_y, int m_z, int m_r, int m_p, int m_yaw)
00336 {
00337 if (!not_complete)
00338 {printf ("Path Construction: You have to start a new path before setting transition modes. (SetTransitionModes)\n"); return;}
00339
00340 current_node->global_transition_evaluator = false;
00341 current_node->transition_evaluator[0] = m_x;
00342 current_node->transition_evaluator[1] = m_y;
00343 current_node->transition_evaluator[2] = m_z;
00344 current_node->transition_evaluator[3] = m_r;
00345 current_node->transition_evaluator[4] = m_p;
00346 current_node->transition_evaluator[5] = m_yaw;
00347 }
00348
00349 void PositionPath::SetParameters (float p_x, float p_y, float p_z, float p_r, float p_p, float p_yaw)
00350 {
00351 if (!not_complete)
00352 {printf ("Path Construction: You have to start a new path before setting transition parameters. (SetParameters)\n"); return;}
00353
00354 current_node->transition_parameter[0] = p_x;
00355 current_node->transition_parameter[1] = p_y;
00356 current_node->transition_parameter[2] = p_z;
00357 current_node->transition_parameter[3] = p_r;
00358 current_node->transition_parameter[4] = p_p;
00359 current_node->transition_parameter[5] = p_yaw;
00360 }
00361
00362 void PositionPath::SeekTime (int time)
00363 {
00364 this->constant_position = this->constant_position;
00365
00366
00367 if (node_pointer != NULL && node_pointer->start_time >= time && node_pointer->end_time < time)
00368 {return;}
00369
00370
00371 if (node_pointer == NULL && first_node != NULL && first_node->start_time <= time)
00372 {node_pointer = first_node;}
00373 else
00374 {
00375
00376 if (node_pointer == NULL)
00377 {return;}
00378 }
00379
00380
00381 if (node_pointer->start_time > time)
00382 {
00383
00384 while (node_pointer != NULL && time < node_pointer->start_time)
00385 {node_pointer = node_pointer->previous;}
00386 return;
00387 }
00388
00389 if (node_pointer->next != NULL && node_pointer->next->start_time <= time)
00390 {
00391
00392 while (node_pointer->next != NULL && node_pointer->next->start_time <= time)
00393 {node_pointer = node_pointer->next;}
00394 return;
00395 }
00396 }
00397
00398
00399 Position PositionPath::GetPosition (int time)
00400 {
00401 if (is_constant)
00402 {
00403 return constant_position;
00404 }
00405 else
00406 {
00407
00408 SeekTime (time);
00409
00410
00411 if (node_pointer == NULL)
00412 {return constant_position;}
00413
00414
00415 if (node_pointer->end_time <= time)
00416 {return constant_position;}
00417
00418 return EvaluateNode (node_pointer, (float)(time - node_pointer->start_time) / (float)(node_pointer->end_time - node_pointer->start_time));
00419 }
00420 return constant_position;
00421 }
00422
00423 Position PositionPath::EvaluateNode (PathNode * node, float progress)
00424 {
00425 Position result;
00426 float interpolation;
00427
00428 if (node->global_transition_evaluator)
00429 {
00430 interpolation = EvaluateValue (node->transition_evaluator[0], progress, node->transition_parameter[0]);
00431
00432 result.x = node->start_position.x * (1 - interpolation) + node->end_position.x * interpolation;
00433 result.y = node->start_position.y * (1 - interpolation) + node->end_position.y * interpolation;
00434 result.z = node->start_position.z * (1 - interpolation) + node->end_position.z * interpolation;
00435 result.roll = node->start_position.roll * (1 - interpolation) + node->end_position.roll * interpolation;
00436 result.pitch = node->start_position.pitch * (1 - interpolation) + node->end_position.pitch * interpolation;
00437 result.yaw = node->start_position.yaw * (1 - interpolation) + node->end_position.yaw * interpolation;
00438 }
00439 else
00440 {
00441 interpolation = EvaluateValue (node->transition_evaluator[0], progress, node->transition_parameter[0]);
00442 result.x = node->start_position.x * (1 - interpolation) + node->end_position.x * interpolation;
00443
00444 interpolation = EvaluateValue (node->transition_evaluator[1], progress, node->transition_parameter[1]);
00445 result.y = node->start_position.y * (1 - interpolation) + node->end_position.y * interpolation;
00446
00447 interpolation = EvaluateValue (node->transition_evaluator[2], progress, node->transition_parameter[2]);
00448 result.z = node->start_position.z * (1 - interpolation) + node->end_position.z * interpolation;
00449
00450 interpolation = EvaluateValue (node->transition_evaluator[3], progress, node->transition_parameter[3]);
00451 result.roll = node->start_position.roll * (1 - interpolation) + node->end_position.roll * interpolation;
00452
00453 interpolation = EvaluateValue (node->transition_evaluator[4], progress, node->transition_parameter[4]);
00454 result.pitch = node->start_position.pitch * (1 - interpolation) + node->end_position.pitch * interpolation;
00455
00456 interpolation = EvaluateValue (node->transition_evaluator[5], progress, node->transition_parameter[5]);
00457 result.yaw = node->start_position.yaw * (1 - interpolation) + node->end_position.yaw * interpolation;
00458 }
00459 return result;
00460 }
00461
00462 float PositionPath::EvaluateValue (int mode, float value, float parameter)
00463 {
00464
00465 switch (mode)
00466 {
00467 case PP_LINEAR: return value;
00468 case PP_SINE: return sin ((parameter + 0.25f) * value * 2 * MY_PI);
00469 case PP_COSINE: return 1 - cos ((parameter + 0.25f) * value * 2 * MY_PI);
00470 case PP_JUMP: return value < parameter ? 0.0f : 1.0f;
00471 }
00472
00473
00474 return 0.0f;
00475 }
00476
00477 bool PositionPath::IsDefined (int time)
00478 {
00479 if (is_constant)
00480 {
00481 return true;
00482 }
00483 else
00484 {
00485 SeekTime (time);
00486
00487
00488 if (node_pointer == NULL) return false;
00489
00490
00491 if (node_pointer->end_time <= time) return false;
00492
00493 return true;
00494 }
00495 }
00496
00497 bool PositionPath::HasStaticRotation ()
00498 {
00499 return has_static_rotation;
00500 }
00501
00502 bool PositionPath::HasDynamicRotation ()
00503 {
00504 return has_dynamic_rotation;
00505 }
00506
00507 void PositionPath::PrintToConsole ()
00508 {
00509 PathNode * current;
00510
00511 printf ("-------------------- Printing Path --------------------\n");
00512 if (is_constant)
00513 {
00514 printf ("Constant Position:{ %g, %g, %g, %g, %g, %g}\n", constant_position.x, constant_position.y,
00515 constant_position.z, constant_position.roll, constant_position.pitch ,constant_position.yaw);
00516 }
00517 else
00518 {
00519 current = first_node;
00520 while (current != NULL)
00521 {
00522 printf ("time: %d -> %d\n", current->start_time, current->end_time);
00523 printf ("pos: {%g, %g, %g, %g, %g, %g} -> {%g, %g, %g, %g, %g, %g}\n", current->start_position.x,
00524 current->start_position.y, current->start_position.z, current->start_position.roll,
00525 current->start_position.pitch, current->start_position.yaw, current->end_position.x,
00526 current->end_position.y, current->end_position.z, current->end_position.roll,
00527 current->end_position.pitch, current->end_position.yaw);
00528
00529 if (current->global_transition_evaluator)
00530 {
00531 printf ("global transition: ");
00532 switch (current->transition_evaluator[0])
00533 {
00534 case PP_LINEAR: printf ("LINEAR (%g)\n", current->transition_parameter [0]);
00535 break;
00536 case PP_SINE: printf ("SINE (%g)\n", current->transition_parameter [0]);
00537 break;
00538 case PP_COSINE: printf ("COSINE (%g)\n", current->transition_parameter [0]);
00539 break;
00540 case PP_JUMP: printf ("JUMP (%g)\n", current->transition_parameter [0]);
00541 break;
00542 default: printf ("UNKNOWN TRANSITION\n");
00543 break;
00544 }
00545 }
00546 else
00547 {
00548 printf ("local transitions (x, y, z, roll, pitch, yaw):\n");
00549 for (int index = 0; index < 6; index++)
00550 {
00551 switch (current->transition_evaluator[0])
00552 {
00553 case PP_LINEAR: printf ("LINEAR (%g)\n", current->transition_parameter [index]);
00554 break;
00555 case PP_SINE: printf ("SINE (%g)\n", current->transition_parameter [index]);
00556 break;
00557 case PP_COSINE: printf ("COSINE (%g)\n", current->transition_parameter [index]);
00558 break;
00559 case PP_JUMP: printf ("JUMP (%g)\n", current->transition_parameter [index]);
00560 break;
00561 default: printf ("UNKNOWN TRANSITION\n");
00562 break;
00563 }
00564 }
00565 }
00566
00567 current = current->next;
00568 }
00569 }
00570 printf ("--------------------- Translation --------------------\n");
00571 printf ("xmin, xmax: {%g, %g}\n", translation_box.xmin, translation_box.xmax);
00572 printf ("ymin, ymax: {%g, %g}\n", translation_box.ymin, translation_box.ymax);
00573 printf ("zmin, zmax: {%g, %g}\n", translation_box.zmin, translation_box.zmax);
00574 printf ("-------------------- End of Path --------------------\n");
00575 }
00576