PositionPath.cpp

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;                   // empty path is considered to be complete
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                 // update end position and create new node with the same start position
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                 // we may have to update the translation box under certain circumstances
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;// just make sure there is a value
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;       // just to have no random value...
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         // we may have to update the translation box under certain circumstances
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         // check which parts of the box has to be updated
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         // and then update these coordinates if neccessary
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         // delete nodes
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         // reset other members
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         // special case 1: pointer already points to the correct node
00367         if (node_pointer != NULL && node_pointer->start_time >= time && node_pointer->end_time < time)
00368         {return;}
00369 
00370         // special case 2: first time that 'time' is bigger than the beginning of the path
00371         if (node_pointer == NULL && first_node != NULL && first_node->start_time <= time)
00372         {node_pointer = first_node;}
00373         else
00374         {
00375                 // time still smaller than the beginning of the path
00376                 if (node_pointer == NULL)
00377                 {return;}
00378         }
00379 
00380         // now iterate either forward or backward
00381         if (node_pointer->start_time > time)
00382         {
00383                 // backward
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                 // forward
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                 // set node pointer
00408                 SeekTime (time);
00409 
00410                 // error (before)
00411                 if (node_pointer == NULL)
00412                 {return constant_position;}
00413 
00414                 // error (after)
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         // poor performance version
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         // unknown mode
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                 // before beginning
00488                 if (node_pointer == NULL) return false;
00489 
00490                 // after current (but before next)
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 

Generated on Sun Jul 2 13:20:39 2006 for Demo by  doxygen 1.4.6-NO