00001 #include <synchronization/semaphore.h> 00002 #include "PL_Range_Sensor.h" 00003 #include <gl\gl.h> 00004 00005 00006 00007 PL_Range_Sensor::~PL_Range_Sensor() 00008 { 00009 } 00010 00011 void PL_Range_Sensor::SetCollisionDetector (CD_BasicStyle* collisionDetector) 00012 { 00013 const CD_Range_Sensor * cd_range_sensor = dynamic_cast< const CD_Range_Sensor * >( collisionDetector ) ; 00014 if( cd_range_sensor != NULL ) 00015 { 00016 //set up the ACA planner which will be used for path planning through free space 00017 PL_HasCollisionDetector::SetCollisionDetector(collisionDetector); 00018 pl_juan.PL_HasCollisionDetector::SetCollisionDetector(collisionDetector); 00019 return; 00020 } 00021 //PL_Range_Sensor won't work without CD_Range_Sensor. 00022 assert(false); 00023 } 00024 00025 bool PL_Range_Sensor::Plan () 00026 { 00027 int i; 00028 Semaphore semaphore( guid ); 00029 00030 //TRACE("\nPL_Range_Sensor::Plan called"); 00031 00032 std::vector<Configuration> prevconfigs; 00033 Configuration current = GetStartConfig(); 00034 Configuration offset ; 00035 Configuration loopstartconfig; 00036 00037 //we will return the path given by pl_juan 00038 path.Clear() ; 00039 00040 SetTimeLimitInSeconds(120); 00041 StartTimer(); 00042 00043 prevconfigs.push_back( GetStartConfig() ); 00044 Configuration intermediate = GetGoalConfig(); 00045 00046 //needed to display the local octree vcollide mesh 00047 dynamic_cast< CD_Range_Sensor* >(collisionDetector)->isMultiThreaded = this->isMultiThreaded; 00048 dynamic_cast< CD_Range_Sensor* >(collisionDetector)->cWindow_ptr = this->cWindow_ptr; 00049 dynamic_cast< CD_Range_Sensor* >(collisionDetector)->hglrc_var = this->hglrc_var; 00050 00051 //utility feature: just take a picture if we're already at the goal 00052 if( GetStartConfig() == GetGoalConfig() ) 00053 { 00054 //TRACE("\nstartConfig == goalConfig, just taking a picture"); 00055 collisionDetector->SetConfiguration( GetStartConfig() ) ; 00056 //take a picture which deletes the planner window information for a time, so grab semaphore 00057 semaphore.Lock(); 00058 dynamic_cast< CD_Range_Sensor * >(collisionDetector)->Take_Picture( GetStartConfig() ); 00059 semaphore.Unlock(); 00060 return false; 00061 } 00062 00063 while (1) 00064 { 00065 //try to make it from startConfig to goalConfig, using PL_Juan; 00066 if (pl_juan.Plan() == true) 00067 { 00068 //if made it to goal successfully, exit 00069 PA_Points* pathp; 00070 //copy path known by pl_juan to our returned path 00071 pathp = dynamic_cast<PA_Points*>(const_cast<PathBase*>(pl_juan.GetPath())); 00072 assert(pathp != NULL); 00073 path = *pathp; 00074 return true; 00075 } 00076 00077 //else, move arm to midpoint between current spot and collision, using PL_Linear's method 00078 00079 //these finite # steps will simulate movement untill we hit occupied/unknown space 00080 const long int steps = 50 ; 00081 00082 //on 1st run, current == startConfig; 00083 loopstartconfig = current; 00084 offset = intermediate - current ; //IMPROVE: joint limits mean that it won't be as simple as this 00085 for( i = 0; i <= steps; i++ ) 00086 { 00087 if( collisionDetector->IsInterfering( current ) ) 00088 { 00089 break; 00090 } 00091 00092 current += ( offset * (1.0 / steps ) ) ; 00093 } 00094 00095 //if we hit something, move to halfway point between hit and loop start configs 00096 if (i <= steps) 00097 { 00098 current = (current + loopstartconfig) / 2; 00099 } 00100 00101 //we better not be hitting anything at this halfway point. 00102 //if we are, then grab another random point and try again. 00103 if (collisionDetector->IsInterfering( current ) == false) 00104 { 00105 collisionDetector->SetConfiguration( current ) ; 00106 00107 //take a picture which deletes the planner window information for a time, so grab semaphore 00108 semaphore.Lock(); 00109 dynamic_cast< CD_Range_Sensor * >(collisionDetector)->Take_Picture( current ); 00110 semaphore.Unlock(); 00111 } else 00112 { 00113 current = loopstartconfig; 00114 //TRACE("\nHalfway point interferrence detected"); 00115 } 00116 00117 //GenerateRandomConfig 00118 intermediate = GenerateRandomConfig() ; 00119 //check the timer 00120 //if not timeout, return to start of the loop 00121 if( HasTimeLimitExpired() == true ) 00122 { 00123 return false ; 00124 } 00125 } 00126 00127 //control should never get here 00128 assert (false); 00129 return false ; 00130 } 00131 00132 void PL_Range_Sensor::SetStartConfig (const Configuration& configuration) 00133 { 00134 PL_HasCollisionDetector::SetStartConfig( configuration ); 00135 pl_juan.SetStartConfig( configuration ) ; 00136 } 00137 00138 void PL_Range_Sensor::SetGoalConfig (const Configuration& configuration) 00139 { 00140 PL_HasCollisionDetector::SetGoalConfig( configuration ); 00141 pl_juan.SetGoalConfig( configuration ) ; 00142 } 00143 00144 Configuration PL_Range_Sensor::GenerateRandomConfig () const 00145 { 00146 int dof = GetStartConfig().DOF() ; 00147 Configuration returnme ; 00148 returnme.SetLength( dof ) ; 00149 00150 //TRACE("\nPL_Range_Sensor::GenerateRandomConfig"); 00151 00152 //a chance for intermediate config to be set to goal config 00153 if (rand() > RAND_MAX*0.8) 00154 { 00155 //TRACE("\nIntermediate config set to goal config"); 00156 return GetGoalConfig(); 00157 } 00158 00159 //generate a random value for all joint variables 00160 for( int i = 0; i < dof; i++ ) 00161 { 00162 double max = collisionDetector->JointMax( i ) ; 00163 double min = collisionDetector->JointMin( i ) ; 00164 double random = double( rand() ) / RAND_MAX ; //this is a random number between [0..1] 00165 returnme[ i ] = min + ( max - min ) * random ; 00166 } 00167 00168 return returnme ; 00169 } 00170 00171 bool PL_Range_Sensor::DrawExplicit () const 00172 { 00173 Semaphore semaphore( this->guid ); 00174 semaphore.Lock(); 00175 CD_Range_Sensor* cdRangeSensor = dynamic_cast< CD_Range_Sensor* >( this->collisionDetector ); 00176 //use dataFuser to display contents of collision detector 00177 cdRangeSensor->dataFuser.GL_Display_Octree(); 00178 semaphore.Unlock(); 00179 return true; 00180 };