00001 #pragma warning( disable : 4786 ) 00002 00003 #include <synchronization/semaphore.h> 00004 #include "debug/debug.h" 00005 #include "color/colorf.h" 00006 #include "math/math2.h" 00007 #include "planners/neural/pl_neural.h" 00008 #include <gl\gl.h> 00009 00010 //============================================================================= 00011 // PL_Neural::PL_Neural 00012 //============================================================================= 00013 PL_Neural::PL_Neural() 00014 { 00015 } 00016 00017 //============================================================================= 00018 // PL_Neural::~PL_Neural 00019 //============================================================================= 00020 PL_Neural::~PL_Neural() 00021 { 00022 } 00023 00024 //============================================================================= 00025 // PL_Neural::DrawExplicit 00026 //============================================================================= 00027 void PL_Neural::AddObstaclePoint( const Configuration& c ) const 00028 { 00029 m_ObstacleLocations.push_back( c ); 00030 } 00031 00032 //============================================================================= 00033 // PL_Neural::CheckPathForObstacles 00034 //============================================================================= 00035 bool PL_Neural::CheckPathForObstacles() 00036 { 00037 int n = NodesInCollision(); 00038 int e = EdgeInCollision(); 00039 00040 if( ( n == -1 ) && ( e == -1 ) ) 00041 { 00042 return false; 00043 } 00044 return true; 00045 } 00046 00047 //============================================================================= 00048 // PL_Neural::ClampAllPointsToDofLimits 00049 //============================================================================= 00050 void PL_Neural::ClampAllPointsToJointLimits() 00051 { 00052 int i; 00053 int size = m_Path.Size(); 00054 for( i = 0; i < size; ++i ) 00055 { 00056 Configuration& c = m_Path[ i ]; 00057 c = ClampToJointLimits( c ); 00058 } 00059 } 00060 00061 //============================================================================= 00062 // PL_Neural::ClampAllPointsToDofLimits 00063 //============================================================================= 00064 Configuration PL_Neural::ClampToJointLimits( const Configuration& c ) const 00065 { 00066 int i; 00067 int size = c.DOF(); 00068 Configuration returnMe = c; 00069 for( i = 0; i < size; ++i ) 00070 { 00071 double min = collisionDetector->JointMin( i ); 00072 double max = collisionDetector->JointMax( i ); 00073 returnMe[ i ] = Clamp( returnMe[ i ], min, max ); 00074 } 00075 return returnMe; 00076 } 00077 00078 //============================================================================= 00079 // PL_Neural::ClosestObstacleToEdge 00080 //============================================================================= 00081 int PL_Neural::ClosestObstacleToEdge ( const unsigned int edgeNum ) const 00082 { 00083 int size = m_ObstacleLocations.size(); 00084 if( size == 0 ) 00085 { 00086 return -1; 00087 } 00088 const Configuration& c0 = m_Path[ edgeNum + 0 ]; 00089 const Configuration& c1 = m_Path[ edgeNum + 1 ]; 00090 00091 double bestDist = DistanceSquared( c0, c1, m_ObstacleLocations[ 0 ] ); 00092 int bestObstacle = 0; 00093 int i; 00094 for( i = 0; i < size; ++i ) 00095 { 00096 const Configuration& p = m_ObstacleLocations[ i ]; 00097 double distanceSqr = DistanceSquared( c0, c1, p ); 00098 if( distanceSqr < bestDist ) 00099 { 00100 bestDist = distanceSqr; 00101 bestObstacle = i; 00102 } 00103 } 00104 return bestObstacle; 00105 } 00106 00107 //============================================================================= 00108 // PL_Neural::ClosestObstacleToPoint 00109 //============================================================================= 00110 int PL_Neural::ClosestObstacleToPoint( const Configuration& c ) const 00111 { 00112 int size = m_ObstacleLocations.size(); 00113 if( size == 0 ) 00114 { 00115 return -1; 00116 } 00117 00118 double closestDistanceSquared = ( m_ObstacleLocations[ 0 ] - c ).MagSquared(); 00119 int bestPoint = 0; 00120 int i; 00121 for( i = 0; i < size; ++i ) 00122 { 00123 double distanceSqr = ( m_ObstacleLocations[ i ] - c ).MagSquared(); 00124 if( distanceSqr < closestDistanceSquared ) 00125 { 00126 closestDistanceSquared = distanceSqr; 00127 bestPoint = i; 00128 } 00129 } 00130 return bestPoint; 00131 } 00132 00133 //============================================================================= 00134 // PL_Neural::DrawExplicit 00135 //============================================================================= 00136 bool PL_Neural::DrawExplicit() const 00137 { 00138 Semaphore semaphore( this->guid ); 00139 semaphore.Lock(); 00140 Color::yellow_50.GlDraw(); 00141 Draw( m_Path ); 00142 00143 // 00144 // Draw obstacle locations 00145 // 00146 Color::red.GlDraw(); 00147 glBegin( GL_POINTS ); 00148 int i; 00149 int size = m_ObstacleLocations.size(); 00150 for( i = 0; i < size; ++i ) 00151 { 00152 const Configuration& c = m_ObstacleLocations[ i ]; 00153 Draw( c ); 00154 } 00155 glEnd(); 00156 00157 semaphore.Unlock(); 00158 return false; 00159 } 00160 00161 //============================================================================= 00162 // PL_Neural::DrawUniversePortion 00163 //============================================================================= 00164 void PL_Neural::DrawUniversePortion() const 00165 { 00166 Semaphore semaphore( guid ); 00167 semaphore.Lock(); 00168 00169 glDisable( GL_LIGHTING ); 00170 glShadeModel( GL_SMOOTH ); 00171 glPointSize( 2.0 ); 00172 00173 Color::yellow_50.GlDraw(); 00174 glPointSize( 2.0f ); 00175 glLineWidth( 1.0f ); 00176 DrawOverlay( m_Path ); 00177 00178 glDisable( GL_DEPTH_TEST ); 00179 // 00180 // Draw obstacle locations 00181 // 00182 glBegin( GL_POINTS ); 00183 Color::red.GlDraw(); 00184 int i; 00185 int size = m_ObstacleLocations.size(); 00186 for( i = 0; i < size; ++i ) 00187 { 00188 const Configuration& c = m_ObstacleLocations[ i ]; 00189 DrawOverlay( c ); 00190 } 00191 glEnd(); 00192 00193 // 00194 // draw repulsion vectors 00195 // 00196 /* 00197 int x; 00198 int y; 00199 Color::cyan.GlDraw(); 00200 for( x = -10; x < 10; ++x ) 00201 { 00202 for( y = -10; y < 10; ++y ) 00203 { 00204 Configuration config( VectorN( x, y, 0 ) ); 00205 Configuration r = RepulsiveVector( config ); 00206 r.Normalize(); 00207 r *= 0.5; 00208 DrawArrorOverlay( config, r ); 00209 } 00210 } 00211 */ 00212 semaphore.Unlock(); 00213 } 00214 00215 //============================================================================= 00216 // PL_Neural::EdgeInCollision 00217 //============================================================================= 00218 int PL_Neural::EdgeInCollision() const 00219 { 00220 int i; 00221 int size = m_Path.Size() - 1; 00222 int returnMe = -1; 00223 for( i = 0; i < size; ++i ) 00224 { 00225 const Configuration& c0 = m_Path[ i + 0 ]; 00226 const Configuration& c1 = m_Path[ i + 1 ]; 00227 bool collision = collisionDetector->IsInterferingLinear( c0, c1 ); 00228 if( collision ) 00229 { 00230 Configuration c = collisionDetector->GetLastIntersection(); 00231 AddObstaclePoint( c ); 00232 returnMe = i; 00233 } 00234 } 00235 return returnMe; 00236 } 00237 00238 //============================================================================= 00239 // PL_Neural::GenerateRandomConfig 00240 //============================================================================= 00241 Configuration PL_Neural::EdgeRepulsion( const unsigned int edgeNum ) const 00242 { 00243 Configuration repulsion = m_Path[ 0 ] * 0.0; 00244 Configuration c0 = m_Path[ edgeNum + 0 ]; 00245 Configuration c1 = m_Path[ edgeNum + 1 ]; 00246 00247 int i; 00248 int size = m_ObstacleLocations.size(); 00249 for( i = 0; i < size; ++i ) 00250 { 00251 Configuration obstacleLocation = m_ObstacleLocations[ i ]; 00252 VectorN closestPoint = ClosestPoint( c0, c1, obstacleLocation ); 00253 closestPoint -= obstacleLocation; 00254 double magSquared = closestPoint.MagSquared(); 00255 if( magSquared == 0.0 ) 00256 { 00257 closestPoint *= 0.0; 00258 } 00259 else 00260 { 00261 closestPoint /= magSquared; 00262 } 00263 repulsion += closestPoint; 00264 } 00265 00266 return repulsion; 00267 } 00268 00269 //============================================================================= 00270 // PL_Neural::GenerateRandomConfig 00271 //============================================================================= 00272 Configuration PL_Neural::GenerateRandomConfig () const 00273 { 00274 Configuration returnMe = GetStartConfig(); 00275 int i; 00276 int size = returnMe.Size(); 00277 for( i = 0; i < size; ++i ) 00278 { 00279 double max = collisionDetector->JointMax( i ); 00280 double min = collisionDetector->JointMin( i ); 00281 double random = rand() / static_cast< double >( RAND_MAX ); 00282 random = min + random * ( max - min ); 00283 returnMe[ i ] = random; 00284 } 00285 return returnMe; 00286 } 00287 00288 //============================================================================= 00289 // PL_Neural::NodesInCollision 00290 //============================================================================= 00291 int PL_Neural::NodesInCollision() const 00292 { 00293 int nodeInCollision = -1; 00294 int i; 00295 int size = m_Path.Size(); 00296 for( i = 1; i < size - 1; ++i ) 00297 { 00298 const Configuration& c = m_Path[ i ]; 00299 bool collision = collisionDetector->IsInterfering( c ); 00300 if( collision ) 00301 { 00302 AddObstaclePoint( c ); 00303 nodeInCollision = i; 00304 } 00305 } 00306 return nodeInCollision; 00307 } 00308 00309 //============================================================================= 00310 // PL_Neural::Perturb 00311 //============================================================================= 00312 void PL_Neural::Perturb( const unsigned int pointNum ) 00313 { 00314 if( pointNum == 0 ) 00315 { 00316 return; 00317 } 00318 unsigned int size = m_Path.Size(); 00319 if( pointNum == size - 1 ) 00320 { 00321 return; 00322 } 00323 00324 Configuration randomDirection = GenerateRandomConfig(); 00325 m_Path[ pointNum ] += randomDirection * 0.5; 00326 } 00327 00328 //============================================================================= 00329 // PL_Neural::Plan 00330 //============================================================================= 00331 bool PL_Neural::Plan() 00332 { 00333 // 00334 // Initialize the planner 00335 // 00336 const Configuration& start = GetStartConfig(); 00337 const Configuration& goal = GetGoalConfig(); 00338 00339 int i; 00340 int size = 10; 00341 for( i = 0; i <= size; ++i ) 00342 { 00343 double percent = static_cast< double >( i ) / size; 00344 m_Path.AppendPoint( start + ( goal - start ) * percent ); 00345 } 00346 00347 for( i = 0; i <= size; ++i ) 00348 { 00349 Perturb( i ); 00350 } 00351 00352 00353 StartTimer(); 00354 while( !HasTimeLimitExpired() ) 00355 { 00356 Semaphore semaphore( guid ); 00357 semaphore.Lock(); 00358 RelaxUntilSettled(); 00359 bool obstaclesPresent = CheckPathForObstacles(); 00360 semaphore.Unlock(); 00361 00362 if( !obstaclesPresent ) 00363 { 00364 path = m_Path; 00365 return true; 00366 } 00367 else 00368 { 00369 int i; 00370 int size = m_Path.Size() - 1; 00371 for( i = 1; i < size; ++i ) 00372 { 00373 //Perturb( i ); 00374 } 00375 } 00376 } 00377 return false; 00378 } 00379 00380 //============================================================================= 00381 // PL_Neural::Relax 00382 //============================================================================= 00383 void PL_Neural::Relax( const unsigned int pointNum ) 00384 { 00385 if( pointNum == 0 ) 00386 { 00387 return; 00388 } 00389 unsigned int size = m_Path.Size(); 00390 if( pointNum == size - 1 ) 00391 { 00392 return; 00393 } 00394 00395 double length = m_Path.PhysicalLength(); 00396 length /= size; 00397 length *= 0.8; 00398 00399 const Configuration& p0 = m_Path[ pointNum - 1 ]; 00400 const Configuration& p1 = m_Path[ pointNum - 0 ]; 00401 const Configuration& p2 = m_Path[ pointNum + 1 ]; 00402 00403 const Configuration v0 = p1 - p0; 00404 const Configuration v1 = p1 - p2; 00405 00406 double d0 = ( v0 ).Magnitude(); 00407 double d1 = ( v1 ).Magnitude(); 00408 d0 -= length; 00409 d1 -= length; 00410 Configuration repulsiveVector = v0 * ( -d0 ) + v1 * ( -d1 ); 00411 //const Configuration repulsiveForce = RepulsiveVector( p1 ) * 0.0; 00412 //Configuration attractionForce = 0.5 * p0 - p1 + 0.5 * p2; 00413 Configuration offset = 0.01 * repulsiveVector; 00414 m_Path[ pointNum ] += offset; 00415 } 00416 00417 //============================================================================= 00418 // PL_Neural::RelaxUntilSettled 00419 //============================================================================= 00420 void PL_Neural::RelaxUntilSettled() 00421 { 00422 // 00423 // relax all the nodes until they settle down 00424 // 00425 int count; 00426 for( count = 0; count < 20; ++count ) 00427 { 00428 ClampAllPointsToJointLimits(); 00429 int size = m_Path.Size(); 00430 int i; 00431 for( i = 1; i < size; ++i ) 00432 { 00433 Relax( i ); 00434 } 00435 00436 size = m_Path.Size() - 1; 00437 for( i = 1; i < size; ++i ) 00438 { 00439 Configuration repulsion = EdgeRepulsion( i ) * 0.01; 00440 double repusiveForce = repulsion.Magnitude(); 00441 if( i != 0 ) 00442 { 00443 m_Path[ i + 0 ] += repulsion; 00444 } 00445 if( i != size - 1 ) 00446 { 00447 m_Path[ i + 1 ] += repulsion; 00448 } 00449 } 00450 } 00451 } 00452 00453 //============================================================================= 00454 // PL_Neural::RepulsiveVector 00455 //============================================================================= 00456 Configuration PL_Neural::RepulsiveVector( const Configuration& c ) const 00457 { 00458 Configuration returnMe = c * 0.0; 00459 int size = m_ObstacleLocations.size(); 00460 int i; 00461 for( i = 0; i < size; ++i ) 00462 { 00463 Configuration ob = m_ObstacleLocations[ i ]; 00464 ob -= c; 00465 ob *= -1; 00466 double mag = ob.MagSquared(); 00467 if( mag != 0.0 ) 00468 { 00469 ob /= mag; 00470 } 00471 returnMe += ob; 00472 } 00473 return returnMe; 00474 }