00001 //========================================================================= 00002 // 00003 // File: IK_InvKinBase.cpp 00004 // 00005 // Created 07-Feb-01 by Shane Schneider 00006 // 00007 // Planner Base for planners requiring a graph data structure 00008 // Contains the actual graph structure as well as several draw and 00009 // computation functions. 00010 00011 00012 00013 // IK_InvKinBase 00014 #include "synchronization/semaphore.h" 00015 #include "planners/InverseKin/IK_InvKinBase.h" 00016 #include "robots/R_OpenChain.h" 00017 00018 #include <assert.h> 00019 #include <math.h> 00020 #include <math/math2.h> 00021 #include <iosfwd> 00022 #include <iostream> 00023 #include <opengl/gl_Frame.h> 00024 00025 // fix gl path... 00026 // #include <gl/glos.h> 00027 #ifndef NOGL 00028 #include "opengl/glos.h" 00029 #include <gl/gl.h> 00030 #endif 00031 00032 using std::endl; 00033 00034 //--------------------- Constants --------------- 00035 static const int FRAMEDOF = 6; 00036 00037 // Class IK_InvKinBase 00038 00039 // Default Constructor 00040 IK_InvKinBase::IK_InvKinBase() 00041 : 00042 m_GoalFrameIndex( -1 ) 00043 { 00044 } 00045 00046 00047 IK_InvKinBase::~IK_InvKinBase() 00048 { 00049 // Default Destructor 00050 } 00051 00052 00053 //============================================================================= 00054 // DrawExplicit 00055 // 00056 // Purpose: Draws the planner data to the planner window when called 00057 //============================================================================= 00058 bool IK_InvKinBase::DrawExplicit () const 00059 { 00060 00061 return false; 00062 } 00063 00064 //============================================================================= 00065 // DrawExplicit 00066 // 00067 // Purpose: Draws the planner data to the planner window when called 00068 //============================================================================= 00069 void IK_InvKinBase::DrawUniversePortion() const 00070 { 00071 #ifndef NOGL 00072 GL_Frame glFrame( goalFrame ); 00073 ::glPushMatrix(); 00074 glFrame.GLDraw(); 00075 ::glPopMatrix(); 00076 #endif 00077 } 00078 00079 00080 //============================================================================= 00081 // Load 00082 // 00083 // Purpose: Loads partailly complete planner data from the disk 00084 //============================================================================= 00085 bool IK_InvKinBase::Load (const char *filename) 00086 { 00087 Semaphore semaphore( this->guid ); 00088 semaphore.Lock(); 00089 00090 // Add file loading code here... 00091 00092 // IMPROVE: This class and all derived classes will need to save the goal frame 00093 00094 semaphore.Unlock(); 00095 return true; 00096 } 00097 00098 00099 //============================================================================= 00100 // Does Planning 00101 // 00102 // Purpose: performs the planning task 00103 //============================================================================= 00104 bool IK_InvKinBase::Plan () 00105 { 00106 assert( false ); //this is an abstract base class, and should never be called 00107 return false; 00108 } 00109 00110 //============================================================================= 00111 // Save 00112 // 00113 // Purpose: Saves partial plan data to disk 00114 //============================================================================= 00115 bool IK_InvKinBase::Save (const char *filename) const 00116 { 00117 Semaphore semaphore( this->guid ); 00118 semaphore.Lock(); 00119 00120 // Add file saving data here... 00121 00122 // IMPROVE: This class and all derived classes will need to save the goal frame 00123 00124 semaphore.Unlock(); 00125 return true; 00126 } 00127 00128 //============================================================================= 00129 // SetStartConfig 00130 // 00131 // Purpose: Sets the start config. 00132 // 00133 //============================================================================= 00134 /*void IK_InvKinBase::SetStartConfig( const Configuration& config ) 00135 { 00136 // Call the parent SetStartConfig to ensure all required initialization is established. 00137 PL_Boolean_Output::SetStartConfig( config ); 00138 00139 } 00140 */ 00141 //============================================================================= 00142 // SetGoalConfig 00143 // 00144 // Purpose: Overloads the SetGoalConfig of normal planners and prevents 00145 // a goal configuration from being assigned since the IK planner 00146 // uses a goal frame and not a goal configuration. Once the 00147 // the IK planner has computed a configuration and path to the goal frame, 00148 // the AssignGoalConfig is called which saves the computed configuration 00149 // as the goal configuration. 00150 // 00151 //============================================================================= 00152 /*void IK_InvKinBase::SetGoalConfig( const Configuration& config ) 00153 { 00154 00155 // does nothing! 00156 00157 //IMPROVE: Remove call to parent's assign goal config 00158 PL_Boolean_Output::SetGoalConfig( config ); 00159 00160 00161 return; 00162 00163 } */ 00164 00165 //============================================================================= 00166 // CopySettings 00167 // 00168 // Purpose: copies the settings from a different planner 00169 //============================================================================= 00170 void IK_InvKinBase::CopySettings( PlannerBase* original ) 00171 { 00172 IK_InvKinBase* originalIKBase = dynamic_cast< IK_InvKinBase* >( original ); 00173 if( originalIKBase == NULL ) 00174 { 00175 return; 00176 } 00177 00178 this->goalFrame = originalIKBase->goalFrame; 00179 } 00180 00181 00182 //============================================================================= 00183 // AssignGoalConfig 00184 // 00185 // Purpose: locally called function that assigns the computed goal configuration 00186 // for the solved goal frame in the server and the planner. 00187 // 00188 // This function is used after the planner has solved the IK planning 00189 // problem and computes a configuration that meets the goal frame. 00190 // This function then saves the computed configuration so other 00191 // planners can try to solve for the same configuration. 00192 //============================================================================= 00193 void IK_InvKinBase::AssignGoalConfig( const Configuration& config ) 00194 { 00195 // Assign the goal config to the planner 00196 // Call the parent SetGoalConfig to ensure all required initialization is established. 00197 PL_Boolean_Output::SetGoalConfig( config ); 00198 00199 // IMPROVE: Add code to set the goal config to the server. 00200 00201 } 00202 00203 00204 //============================================================================= 00205 // SetGoalFrame 00206 // 00207 // Purpose: Assign the desired goal frame to solve for. 00208 // 00209 // NOTE: This is the function that should be eventually called by all 00210 // overloaded versions of the function. It is used to assign and set 00211 // any other parameters required when setting the goal frame. 00212 //============================================================================= 00213 void IK_InvKinBase::SetGoalFrame( const Matrix4x4& newFrame ) 00214 { 00215 if ( goalFrame != newFrame ) 00216 { 00217 goalFrame = newFrame; 00218 00219 // Initialize a new search. 00220 this->InitNewSearch(); 00221 } 00222 } 00223 00224 //============================================================================= 00225 // SetGoalFrame 00226 // 00227 // Purpose: Assign the desired goal frame to solve for based on the tool frame 00228 // generated by the given configuration. 00229 //============================================================================= 00230 void IK_InvKinBase::SetGoalFrame( const Configuration& config ) 00231 { 00232 // find the tool frame from the given configuration 00233 Matrix4x4 tempFrame = GetToolFrame( config ); 00234 00235 // assign the goal frame 00236 SetGoalFrame( tempFrame ); 00237 } 00238 00239 //============================================================================= 00240 // SetGoalFrame 00241 // 00242 // Purpose: Assign the desired goal frame to solve for based on DOF vector given 00243 //============================================================================= 00244 void IK_InvKinBase::SetGoalFrame( const VectorN& dofVector ) 00245 { 00246 // verify the vector has the correct number of components. 00247 assert( dofVector.Length() == FRAMEDOF ); 00248 00249 // assign the goal frame 00250 SetGoalFrame( dofVector[0], dofVector[1], dofVector[2], 00251 dofVector[3], dofVector[4], dofVector[5] ); 00252 00253 } 00254 00255 //============================================================================= 00256 // SetGoalFrame 00257 // 00258 // Purpose: Assign the desired goal frame to solve for based on fixed angle 00259 // X-Y-Z rotation and translated accordingly. 00260 // 00261 // Note: Roll, Pitch, and Yaw are to be expressed in degrees. 00262 //============================================================================= 00263 void IK_InvKinBase::SetGoalFrame( const double& x, const double& y, const double& z, 00264 const double& roll, const double& pitch, const double& yaw ) 00265 { 00266 Matrix4x4 newFrame = GetTransformFrame( x, y, z, roll, pitch, yaw ); 00267 00268 // Assign the generated frame as the new goal frame 00269 SetGoalFrame( newFrame ); 00270 } 00271 00272 //============================================================================= 00273 // GetTransformFrame 00274 // 00275 // Purpose: Calculate a frame transformation based on fixed angle 00276 // X-Y-Z rotation and translated accordingly wrt to the world frame. 00277 // The parameters are passed as a VectorN of size FRAMEDOF. 00278 // The resulting frame can then be used as the desired goal frame. 00279 // 00280 // Note: Roll, Pitch, and Yaw are to be expressed in degrees. 00281 //============================================================================= 00282 Matrix4x4 IK_InvKinBase::GetTransformFrame( const VectorN& dofVector ) const 00283 { 00284 // verify the vector has the correct number of components. 00285 assert( dofVector.Length() == FRAMEDOF ); 00286 00287 // get the frame transformation 00288 Matrix4x4 newFrame = GetTransformFrame( dofVector[0], dofVector[1], dofVector[2], 00289 dofVector[3], dofVector[4], dofVector[5] ); 00290 00291 return newFrame; 00292 } 00293 00294 //============================================================================= 00295 // GetTransformFrame 00296 // 00297 // Purpose: Calculate a frame transformation based on fixed angle 00298 // X-Y-Z rotation and translated accordingly wrt to the world frame. 00299 // The resulting frame can then be used as the desired goal frame. 00300 // 00301 // Note: Roll, Pitch, and Yaw are to be expressed in degrees. 00302 //============================================================================= 00303 Matrix4x4 IK_InvKinBase::GetTransformFrame( const double& x, const double& y, const double& z, 00304 const double& roll, const double& pitch, const double& yaw ) 00305 { 00306 // translate angles from degress to radians. 00307 double alpha = Deg2Rad( yaw ); 00308 double beta = Deg2Rad( pitch ); 00309 double gamma = Deg2Rad( roll ); 00310 00311 // Cache trig values for quicker multiplcation. 00312 double cA = cos( alpha ); 00313 double sA = sin( alpha ); 00314 double cB = cos( beta ); 00315 double sB = sin( beta ); 00316 double cY = cos( gamma ); 00317 double sY = sin( gamma ); 00318 00319 // Generate frame based on translation and fixed angle rotation 00320 Matrix4x4 newFrame; 00321 newFrame( 0 , 0 ) = cA*cB; 00322 newFrame( 1 , 0 ) = sA*cB; 00323 newFrame( 2 , 0 ) = -sB; 00324 newFrame( 3 , 0 ) = 0; 00325 00326 newFrame( 0 , 1 ) = cA*sB*sY - sA*cY; 00327 newFrame( 1 , 1 ) = sA*sB*sY + cA*cY; 00328 newFrame( 2 , 1 ) = cB*sY; 00329 newFrame( 3 , 1 ) = 0; 00330 00331 newFrame( 0 , 2 ) = cA*sB*cY + sA*sY; 00332 newFrame( 1 , 2 ) = sA*sB*cY - cA*sY; 00333 newFrame( 2 , 2 ) = cB*cY; 00334 newFrame( 3 , 2 ) = 0; 00335 00336 newFrame( 0 , 3 ) = x; 00337 newFrame( 1 , 3 ) = y; 00338 newFrame( 2 , 3 ) = z; 00339 newFrame( 3 , 3 ) = 1; 00340 00341 // return resulting new frame 00342 return newFrame; 00343 00344 } 00345 00346 //============================================================================= 00347 // GetRotAngles 00348 // 00349 // Purpose: Calculates the fixed rotation angles and translation for the given 00350 // frame wrt to the world frame. The results are passed by reference. 00351 // 00352 // Note: Roll, Pitch, and Yaw are expressed in degrees. 00353 //============================================================================= 00354 void IK_InvKinBase::GetRotAngles( const Matrix4x4& frame, double& x, double& y, double& z, 00355 double& roll, double& pitch, double& yaw ) const 00356 { 00357 // Declare the fixed angle variables. 00358 double alpha, beta, gamma; 00359 00360 00361 // Calculate beta and cache the cosine. 00362 beta = atan2( -frame(2,0) , sqrt( Sqr(frame(0,0)) + Sqr(frame(1,0)) ) ); 00363 double cB = cos ( beta ); 00364 00365 // Calculate the other two rotations 00366 if ( cB == 0.0 ) 00367 { 00368 alpha = 0; 00369 if ( beta > 0 ) // if beta == PI/2 00370 { 00371 gamma = atan2( frame(0,1) , frame(1,1) ); 00372 } 00373 else 00374 { 00375 gamma = -atan2( frame(0,1), frame(1,1) ); 00376 } 00377 } 00378 else 00379 { 00380 alpha = atan2( frame(1,0) / cB , frame(0,0) / cB ); 00381 gamma = atan2( frame(2,1) / cB , frame(2,2) / cB ); 00382 } 00383 00384 // Convert angles to degrees and assign to appropriate parameters 00385 // NOTE: These angles must correspond to same angles used in SetGoalFrame 00386 yaw = Rad2Deg( alpha ); 00387 pitch = Rad2Deg( beta ); 00388 roll = Rad2Deg( gamma ); 00389 00390 // Get the translations 00391 x = frame(0,3); 00392 y = frame(1,3); 00393 z = frame(2,3); 00394 } 00395 00396 //============================================================================= 00397 // GetRotVector 00398 // 00399 // Purpose: Calculates the fixed rotation angles and translation for the given 00400 // frame wrt to the world frame, and returns the result as a vector of 00401 // size FRAMEDOF. 00402 // 00403 // Note: Roll, Pitch, and Yaw are expressed in degrees. 00404 //============================================================================= 00405 VectorN IK_InvKinBase::GetRotVector( const Matrix4x4& frame ) const 00406 { 00407 // create Vector 00408 VectorN returnMe; 00409 returnMe.SetLength( FRAMEDOF ); 00410 00411 // assign the values 00412 GetRotAngles( frame, returnMe[0], returnMe[1], returnMe[2], returnMe[3], returnMe[4], returnMe[5] ); 00413 00414 // return the vector 00415 return returnMe; 00416 } 00417 00418 //============================================================================= 00419 // GetGoalFrame 00420 // 00421 // Purpose: Returns the goal frame that the IK planner will attempt to solve for 00422 // 00423 //============================================================================= 00424 Matrix4x4 IK_InvKinBase::GetGoalFrame() const 00425 { 00426 return goalFrame; 00427 } 00428 00429 //============================================================================= 00430 // GetGoalFrame 00431 // 00432 // Purpose: Returns the goal frame that the IK planner will attempt to solve for 00433 // as a 6-dof of vector, with each component representing the translation 00434 // or fixed angle rotation about the axis 00435 // 00436 //============================================================================= 00437 VectorN IK_InvKinBase::GetGoalFrameVector() const 00438 { 00439 VectorN returnMe; 00440 returnMe.SetLength( FRAMEDOF ); 00441 00442 GetRotAngles( goalFrame, returnMe[0], returnMe[1], returnMe[2], returnMe[3], returnMe[4], returnMe[5] ); 00443 00444 return returnMe; 00445 } 00446 00447 //============================================================================= 00448 // GetToolFrame 00449 // 00450 // Purpose: Computes the tool frame for the robot for a given configuration wrt world frame. 00451 // 00452 // Note: This function will move the robot to the given configuration and 00453 // force an update of all frames. This function should not 00454 // be called too often. 00455 //============================================================================= 00456 Matrix4x4 IK_InvKinBase::GetToolFrame( const Configuration& config ) const 00457 { 00458 #if 0 00459 if ( collisionDetector == NULL ) 00460 { 00461 return Matrix4x4(); 00462 } 00463 00464 // get pointer to frame manager 00465 FrameManager* frameManager = collisionDetector->GetFrameManager(); 00466 00467 // move the robot to desired config 00468 collisionDetector->SetConfiguration( config ); 00469 00470 // IMPROVE: temporary method of finding the tool frame in frame manager 00471 int toolFrameNum = 0; 00472 if ( config.DOF() > 0 ) 00473 { 00474 toolFrameNum = collisionDetector->JointFrameNum( config.DOF() - 1 ); 00475 } 00476 00477 Matrix4x4 toolFrame = frameManager->GetWorldFrame( toolFrameNum ); 00478 #else 00479 Frame toolFrame = Matrix4x4(); 00480 00481 if ( collisionDetector != NULL ) 00482 { 00483 FrameManager* frameManager = collisionDetector->GetFrameManager(); 00484 collisionDetector->SetConfiguration( config ); 00485 //toolFrame = frameManager->GetWorldFrame( m_toolFrame ); 00486 R_OpenChain * robot = (R_OpenChain *)collisionDetector->GetRobot(0); 00487 int toolFrameID = robot->GetToolFrame(0); 00488 if (toolFrameID == -1) 00489 { 00490 toolFrameID = collisionDetector->JointFrameNum( config.DOF() - 1 ); 00491 toolFrame = frameManager->GetWorldFrame( toolFrameID ); 00492 } 00493 else 00494 { 00495 toolFrame = *(frameManager->GetFrameRef(toolFrameID)); 00496 toolFrame = frameManager->GetTransformRelative(collisionDetector->DOF(), 0) * toolFrame; 00497 } 00498 } 00499 00500 #endif 00501 return toolFrame; 00502 } 00503 00504 00505 //============================================================================= 00506 // InitNewSearch 00507 // 00508 // Purpose: Abstract function that initiates parameters in derived classes to 00509 // indicate if a new search has been requested. 00510 //============================================================================= 00511 void IK_InvKinBase::InitNewSearch() 00512 { 00513 // do nothing...this is an abstract class that should be defined in 00514 // derived classes if needed. 00515 00516 return; 00517 } 00518 00519