Component.cc
Go to the documentation of this file.
00001 
00012 #include <pthread.h>
00013 #include <purepursuit_planner/Component.h>
00014 
00015 
00020 void *AuxControlThread(void *threadParam){
00021         Component *ComponentThread = (Component *)threadParam;
00022         ComponentThread->ControlThread();
00023     pthread_detach(pthread_self());
00024         return NULL;
00025 }
00026 
00031 Component::Component(double desired_hz){
00032         // Set main flags to false
00033         bInitialized = bRunning = false;
00034         threadData.dRealHz = 0.0;
00035         if(desired_hz <= 0.0)
00036                 desired_hz = DEFAULT_THREAD_DESIRED_HZ;
00037         threadData.dDesiredHz = desired_hz;
00038         iState = SHUTDOWN_STATE;
00039         // Realizar para cada una de las clases derivadas
00040         sComponentName.assign("Component");
00041         
00042         // mutex intitialization
00043         pthread_mutex_init(&mutexThread, NULL);
00044         // Real-Time parameters
00045         threadData.pthreadPar.prio = 25;                                // Priority level 0[min]-80[max]
00046         threadData.pthreadPar.clock= CLOCK_REALTIME;    // 0-CLOCK_MONOTONIC 1-CLOCK_REALTIME
00047 }
00048 
00052 Component::~Component(){
00053         
00054         pthread_mutex_destroy(&mutexThread);
00055 }
00056 
00063 ReturnValue Component::Setup(){
00064         // Checks if has been initialized
00065         if(bInitialized){
00066                 ROS_INFO("%s::Setup: Already initialized",sComponentName.c_str());
00067                 
00068                 return INITIALIZED;
00069         }
00070         
00071         //
00073         // Setups another subcomponents if it's necessary //
00075 
00077         // Allocates memory
00078         if(Allocate() != OK){
00079                 ROS_ERROR("%s::Setup: Error in Allocate",sComponentName.c_str());
00080                 return ERROR;
00081         }
00082         // Opens devices used by the component
00083         if(Open() != OK){
00084                 ROS_ERROR("%s::Setup: Error in Open",sComponentName.c_str());
00085                 
00086                 return ERROR;
00087         }       
00088         //
00089         // Configure the component
00090         if(Configure() != OK){
00091                 ROS_ERROR("%s::Setup: Error in Configure",sComponentName.c_str());
00092                 return ERROR;
00093         }
00094 
00095         bInitialized = true;
00096 
00097         return OK;
00098 }
00099 
00107 ReturnValue Component::ShutDown(){
00108         
00109         if(bRunning){
00110                 ROS_INFO("%s::ShutDown: Impossible while thread running, first must be stopped",sComponentName.c_str());
00111                 return THREAD_RUNNING;
00112         }
00113         if(!bInitialized){
00114                 ROS_INFO("%s::ShutDown: Impossible because of it's not initialized", sComponentName.c_str());
00115                 return NOT_INITIALIZED;
00116         }
00117 
00118         //
00120         // ShutDowns another subcomponents if it's necessary //
00122                 
00123         if(Close() != OK){
00124                 ROS_ERROR("%s::ShutDown: Error Closing", sComponentName.c_str());
00125                 return ERROR;
00126         }
00127         if(Free() != OK){
00128                 ROS_ERROR("%s::ShutDown: Error in Free", sComponentName.c_str());
00129                 return ERROR;
00130         }
00131 
00132         bInitialized = false;
00133 
00134         return OK;
00135 }
00136 
00142 ReturnValue Component::Configure(){
00143 
00144         return OK;
00145 }
00146 
00151 ReturnValue Component::Allocate(){
00152 
00153         return OK;
00154 }
00155 
00160 ReturnValue Component::Free(){
00161 
00162         return OK;
00163 }
00164 
00170 ReturnValue Component::Open(){
00171 
00172         return OK;
00173 }
00174 
00180 ReturnValue Component::Close(){
00181 
00182         return OK;
00183 }
00184 
00191 ReturnValue Component::Start(){
00192         
00193         pthread_attr_t attr;    // Thread attributed for the component threads spawned in this function
00194 
00195         // If the component is not initialized, we can't start
00196         if(!bInitialized){
00197                 ROS_INFO("%s::Start: the component is not initialized", sComponentName.c_str());
00198                 return NOT_INITIALIZED;
00199         }
00200         //
00202         // Starts another subcomponents if it's necessary //
00204         //
00205         if(!bRunning) {
00206                 ROS_INFO("%s::Start: launching the thread", sComponentName.c_str());
00207                 
00208 
00209                 pthread_attr_init(&attr);
00210                 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00211                 bRunning = true;
00212                 // Creation of the main thread
00213                 if(pthread_create(&threadData.pthreadId, &attr, AuxControlThread, this) != 0)   {
00214                         ROS_ERROR("%s::Start: Could not create ControlThread", sComponentName.c_str());
00215                         
00216                         pthread_attr_destroy(&attr);
00217                         bRunning = false;
00218                         return ERROR;
00219                 }
00220 
00221                 pthread_attr_destroy(&attr);
00222                 return OK;
00223 
00224         }else {
00225                 ROS_INFO("%s::Start: the component's thread is already running", sComponentName.c_str());
00226                 return THREAD_RUNNING;
00227         }
00228 
00229 }
00230 
00237 ReturnValue Component::Stop(){
00238         
00239         if(!bRunning){
00240                 ROS_INFO("%s::Stop: Thread not running", sComponentName.c_str());
00241         
00242                 return THREAD_NOT_RUNNING;
00243         }
00244         //
00246         // Stops another subcomponents, if it's necessary //
00248         //
00249         ROS_INFO("%s::Stop: Stopping the thread", sComponentName.c_str());
00250         
00251         bRunning = false;
00252 
00253         usleep(100000);
00254 
00255         return OK;
00256 }
00257 
00261 void Component::ControlThread(){
00262         struct sched_param schedp;
00263         int policy = threadData.pthreadPar.prio? SCHED_FIFO : SCHED_OTHER;
00264         struct timespec now, next, interval;
00265         struct timespec last_time;  // Necesarry to calculates real frec
00266         long diff;
00267         unsigned long sampling_period_us;
00268         
00269         // Robotnik thread priority and timing management
00270         memset(&schedp, 0, sizeof(schedp));
00271         schedp.sched_priority = threadData.pthreadPar.prio;
00272         sched_setscheduler(0, policy, &schedp);
00273         clock_gettime(threadData.pthreadPar.clock, &now);
00274         last_time = next = now;
00275         next.tv_sec++;  // start in next second?
00276         sampling_period_us =  (long unsigned int) (1.0 / threadData.dDesiredHz * 1000000.0);
00277         interval.tv_sec = sampling_period_us / USEC_PER_SEC;  // interval parameter in uS
00278         interval.tv_nsec = (sampling_period_us % USEC_PER_SEC)*1000;
00279 
00280         //sprintf(cAux, "%s::ControlThread: Starting the thread", sComponentName.c_str());
00281         //rlcLog->AddEvent((char *)cAux);
00282         // Begin thread execution on init state
00283         SwitchToState(INIT_STATE);
00284 
00285         while(bRunning) { // Executes state machine code while bRunning flag is active
00286                 clock_nanosleep(threadData.pthreadPar.clock, TIMER_ABSTIME, &next, NULL);
00287                 clock_gettime(threadData.pthreadPar.clock, &now);
00288                 next.tv_sec += interval.tv_sec;
00289                 next.tv_nsec += interval.tv_nsec;
00290                 tsnorm(&next);
00291 
00292                 diff = calcdiff(now, last_time);
00293                 last_time = now;
00294                 // Thread frequency update
00295                 threadData.dRealHz = 1.0/(diff / 1000000.0); // Compute the update rate of this thread
00296                 // Test: controlamos que la frecuencia real no difiera de la teórica
00297                 if(threadData.dRealHz < (1.0/5.0)*threadData.dDesiredHz){
00298                         ROS_ERROR("%s:ControlThread: Delay on control loop. Desired Hz is %lf, but real is %lf", sComponentName.c_str(), threadData.dDesiredHz, threadData.dRealHz);
00299                         
00300                 }
00301 
00302                 switch (iState){
00303                         case INIT_STATE:
00304                                 InitState();
00305                         break;
00306                         case STANDBY_STATE:
00307                                 StandbyState();
00308                         break;
00309                         case READY_STATE:
00310                                 ReadyState();
00311                         break;
00312                         case EMERGENCY_STATE:
00313                                 EmergencyState();
00314                         break;
00315                         case FAILURE_STATE:
00316                                 FailureState();
00317                         break;
00318                         default:
00319                         break;
00320                 }
00321                 AllState();
00322         }
00323         SwitchToState(SHUTDOWN_STATE);
00324         
00325         ROS_INFO("%s:ControlThread: Exiting main Thread", sComponentName.c_str());
00326         
00327         usleep(100000); // Sleep for 100 milliseconds and then exit
00328 
00329 }
00330 
00334 void Component::InitState(){
00335 
00336 }
00337 
00341 void Component::StandbyState(){
00342 
00343 }
00344 
00348 void Component::ReadyState(){
00349 
00350 }
00351 
00355 void Component::EmergencyState(){
00356 
00357 }
00358 
00362 void Component::FailureState(){
00363 
00364 }
00365 
00369 void Component::AllState(){
00370 
00371 }
00372 
00377 double Component::GetUpdateRate(){
00378         return threadData.dRealHz;
00379 }
00380 
00384 States Component::GetState(){
00385         return iState;
00386 }
00387 
00391 char *Component::GetStateString(){
00392         switch(iState){
00393                 case INIT_STATE:
00394                         return (char *)"INIT";
00395                 break;
00396                 case STANDBY_STATE:
00397                         return (char *)"STANDBY";
00398                 break;
00399                 case READY_STATE:
00400                         return (char *)"READY";
00401                 break;
00402                 case EMERGENCY_STATE:
00403                         return (char *)"EMERGENCY";
00404                 break;
00405                 case FAILURE_STATE:
00406                         return (char *)"FAILURE";
00407                 break;
00408                 case SHUTDOWN_STATE:
00409                         return (char *)"SHUTDOWN";
00410                 break;
00411                 default:
00412                         return (char *)"UNKNOWN";
00413                 break;
00414         }
00415 }
00416 
00420 char *Component::GetStateString(States state){
00421         switch(state){
00422                 case INIT_STATE:
00423                         return (char *)"INIT";
00424                 break;
00425                 case STANDBY_STATE:
00426                         return (char *)"STANDBY";
00427                 break;
00428                 case READY_STATE:
00429                         return (char *)"READY";
00430                 break;
00431                 case EMERGENCY_STATE:
00432                         return (char *)"EMERGENCY";
00433                 break;
00434                 case FAILURE_STATE:
00435                         return (char *)"FAILURE";
00436                 break;
00437                 case SHUTDOWN_STATE:
00438                         return (char *)"SHUTDOWN";
00439                 break;
00440                 default:
00441                         return (char *)"UNKNOWN";
00442                 break;
00443         }
00444 }
00445 
00446 
00451 void Component::SwitchToState(States new_state){
00452         
00453         if(new_state == iState)
00454                 return;
00455 
00456 
00457         ROS_INFO("%s::SwitchToState: %s -> %s", sComponentName.c_str(), GetStateString(iState), GetStateString(new_state));     
00458         iState = new_state;
00459 
00460 }
00461 
00467 ReturnValue Component::GetThreadData(thread_data *data){
00468     pthread_t auxId = pthread_self();
00469     ReturnValue ret = ERROR;
00470     // Main thread
00471     if(auxId == threadData.pthreadId){
00472         *data = threadData;
00473         ROS_INFO("Component::GetThreadData: Main thread");
00474         return OK;
00475     }
00476     // Search the Id in the list
00477     pthread_mutex_lock(&mutexThread);
00478         for(unsigned int i = 0; i < vThreadData.size(); i++){
00479             
00480             if(auxId == vThreadData[i].pthreadId){  // Encontrado
00481                 *data = vThreadData[i];
00482                 ret = OK;
00483                 break;
00484             }
00485         }
00486     pthread_mutex_unlock(&mutexThread);
00487 
00488     return ret;
00489 }
00490 
00500 ReturnValue Component::CreateTask(int prio, double frec, void *(*start_routine)(void*)){
00501         pthread_attr_t attr;    // Thread attributed for the component threads spawned in this function
00502     thread_data new_thread;
00503     if(frec <= 0.0)
00504         frec = DEFAULT_THREAD_DESIRED_HZ;
00505     if(prio < 0)
00506         prio = DEFAULT_THREAD_PRIORITY;
00507     //
00508         // If the component is not initialized, we can't start
00509         if(!bRunning){
00510                 ROS_INFO("%s::CreateTask: the component is not running", sComponentName.c_str());
00511                 return THREAD_NOT_RUNNING;
00512         }
00513 
00514     pthread_attr_init(&attr);
00515     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00516     // Protect the creation and modification of threads with a mutex
00517     pthread_mutex_lock(&mutexThread);
00518 
00519         // Creation of the main thread
00520         if(pthread_create(&new_thread.pthreadId, &attr, start_routine, this) != 0)      {
00521             ROS_ERROR("%s::CreateTask: Could not create new thread", sComponentName.c_str());
00522             pthread_attr_destroy(&attr);
00523             pthread_mutex_unlock(&mutexThread);
00524             return ERROR;
00525         }
00526         pthread_attr_destroy(&attr);
00527         new_thread.dDesiredHz = frec;
00528         new_thread.dRealHz = 0.0;
00529         new_thread.pthreadPar.prio = prio;
00530         new_thread.pthreadPar.clock = CLOCK_REALTIME;
00531         // Adds information for the new thread
00532         vThreadData.push_back(new_thread);
00533         
00534     pthread_mutex_unlock(&mutexThread);
00535 
00536     return OK;
00537 }


purepursuit_planner
Author(s): Román Navarro
autogenerated on Thu Aug 27 2015 12:08:42