planners/sequential/PL_Sequential.cpp

Go to the documentation of this file.
00001 #include< math/math2.h>
00002 #include < assert.h>
00003 
00004 // PL_Sequential
00005 #include "PL_Sequential.h"
00006 #include "sp3dstct.h"
00007 #include "spfiles.h"
00008 #include "gdefs.h"
00009 #include "sp3dgl.h"
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include "opengl/glos.h"
00013 #include <gl/gl.h>
00014 #include "smoothers\SmootherBase.h"
00015 
00016 #pragma warning( disable : 4786 )
00017 
00018 const int UNDONE = -1 ;
00019 //## end module%3752D78501D0.additionalDeclarations
00020 
00021 
00022 // Class PL_Sequential 
00023 
00024 PL_Sequential::~PL_Sequential()
00025 {
00026   //## begin PL_Sequential::~PL_Sequential%.body preserve=yes
00027         free( orig_initial_config ) ;   
00028         free( orig_final_config ) ;     
00029 
00030         int i;
00031         for( i = 0; i < arm_degree; i++ )
00032         {
00033                 free( lnkcps[ i ].d );
00034                 lnkcps->d = NULL;
00035         }
00036         free( lnkcps );
00037         free2D( ( void** )globalpath );
00038         free( tqcs.tqlink );
00039         free( bkwdpath.d );
00040         free( frwdpath.d );
00041         free( combpath.d );
00042         free( mainpath.d );
00043         free( wall );
00044   //## end PL_Sequential::~PL_Sequential%.body
00045 }
00046 
00047 //=========================================================================================
00048 // DrawExplicit
00049 //
00050 // Draws the plannmer to the output window
00051 //
00052 //=========================================================================================
00053 bool PL_Sequential::DrawExplicit () const
00054 {
00055 /*              for (int a = 0; a < ptqlink->dimt; a++) 
00056                 {
00057                         for (int b = 0; b < ptqlink->dimq; b++)
00058                         {
00059                                 if ((a==pinitial.x) && (b==pinitial.y))
00060                                 {
00061                                         //fprintf(stream, ";");
00062                                         bitmap.PutPixel(a, b, 0);
00063                                 }
00064                                 else if ((a==pfinal.x) && (b==pfinal.y))
00065                                 {
00066                                         //fprintf(stream, ";");
00067                                         bitmap.PutPixel(a, b, 0);
00068                                 }
00069                                 else if (ptqlink->bitmap[a][b] == OBSTACLE) 
00070                                 //if (ptqlink->bitmap[a][b] == OBSTACLE) 
00071                                 {
00072                                         bitmap.PutPixel( a, b, 0 );
00073                                         //fprintf(stream, ";");
00074                                 }
00075                                 else if (ptqlink->bitmap[a][b] == FREESPACE) 
00076                                 {
00077                                         bitmap.PutPixel( a, b, 1 );
00078                                         //fprintf(stream, "|");
00079                                 }       
00080                         }               
00081                         //fprintf( stream, "\n" ) ;
00082                 } 
00083 */
00084         if( this->tqcs.tqlink->bitmap == NULL )
00085         {
00086                 //draw a test pattern
00087                 //fill the pixel array with some data
00088                 const int xRes = 128;
00089                 const int yRes = 128;
00090                 char pixels[ yRes ][ xRes ];
00091                 int i;
00092                 int j;
00093                 for( i = 0; i < xRes; i++ )
00094                 {
00095                         for( j = 0; j < yRes; j++ )
00096                         {
00097                                 pixels[ j ][ i ] = i;
00098                         }
00099                 }
00100 
00101 
00102                 ::glDrawPixels
00103                 (
00104                         128,    //width
00105                         128,    //height
00106                         GL_LUMINANCE,
00107                         GL_BYTE,
00108                         &pixels
00109                 );
00110         }
00111         else
00112         {
00113                 //draw a test pattern
00114                 //fill the pixel array with some data
00115                 const int xRes = tqcs.tqlink->dimt;
00116                 const int yRes = tqcs.tqlink->dimq;
00117 
00118                 ::glDrawPixels
00119                 (
00120                         xRes,   //width
00121                         yRes,   //height
00122                         GL_LUMINANCE,
00123                         GL_BYTE,
00124                         tqcs.tqlink->bitmap
00125                 );
00126         }
00127         return true;
00128 }
00129 
00130 //## Other Operations (implementation)
00131 bool PL_Sequential::Plan ()
00132 {
00133   //## begin PL_Sequential::Plan%928173143.body preserve=yes
00134 
00135         
00136         //create the output window
00137 /*#ifdef PC_PROTO       
00138         bitmap.StartOutput() ;          //IMPROVE: remember to end output somewhere
00139 
00140         //this is how you draw a bitmap
00141         bitmap.NameDialog( "Started Planning" ) ;
00142         bitmap.SetResolution( 100, 100 ) ;
00143         for( int x = 0; x < 100; x++ )
00144         {
00145                 for( int y = 0; y < 100; y++ )
00146                 {
00147                         double intensity = Max( x, y ) / 100.0 ;
00148                         bitmap.PutPixel( x, y, intensity ) ;            
00149                 }
00150         }
00151         bitmap.Display() ;
00152 #endif  */
00153 
00154         int     i,j;
00155         int     blen;
00156         int     BT_flag, Block_flag, Narrow_flag, on_BT_max;
00157         int     current_link, path_link, path_final=SP_PLANNING, on_BT, linkno;
00158         int back_to_link;
00159         int     BT_Number[7][7], BT_Number_Record[7];
00160         TQConfig        block[100], block_last[1];
00161 
00162         // obtain joint limits of all links of robot
00163         for (linkno=0; linkno<arm_degree; linkno++) {
00164                 original_joint_limit[linkno].status = 1;
00165                 original_joint_limit[linkno].start = RADIAN(collisionDetector->JointMin(linkno));
00166                 original_joint_limit[linkno].end = RADIAN(collisionDetector->JointMax(linkno));
00167         }
00168         
00169         // get start config 
00170         for( int loop = 0; loop < arm_degree; loop++ )
00171         {
00172                 orig_initial_config[ loop ] = RADIAN(GetStartConfig()[ loop ]) ;
00173         }
00174 
00175         // get goal config 
00176         for( loop = 0; loop < arm_degree; loop++ )
00177         {
00178                 orig_final_config[ loop ] = RADIAN(GetGoalConfig()[ loop ]) ;
00179         }
00180          
00181     // Convert all angles into look-up index            
00182     convert_angle_to_index();
00183 
00184         // planning for link0 
00185         allocate_space_for_link_cs(0);
00186 
00187         //deactivate all the frame-frame collison checking
00188         collisionDetector->DeactivateAllFrames() ;
00189 
00190         // activates frame-to-frame collision check between frame 0 and 1
00191         collisionDetector->ActivateFrames(0,1);  
00192         path_link = plan_path_for_first_link(); 
00193         if (path_link != SP_TQ_OK) 
00194         {
00195                 return false;
00196         }
00197 
00198         //If path exists for link0, then proceeds to Main Path Search Scheme, Includes Backtracking             
00199         current_link = 1;   
00200         path_final= SP_PLANNING;
00201         on_BT = FALSE; 
00202         BT_level_test = 1;      // bt level of current backtracking. 
00203         BT_flag = 0;            // sign of maximum bt reached. 
00204         Block_flag = 0;         // sign of same blocks. 
00205         Narrow_flag = 0;        // sign of that goal is in narrow region 
00206         on_BT_max = 0;
00207 
00208         block_last[0].t = 0;
00209         block_last[0].q = 0;
00210 
00211         //IMPROVE: BT_Number_Record[7] and BT_Number[7][7] limiting dof
00212         for (i=0; i<=max_level; i++) {
00213             BT_Number_Record[i] = 0;
00214             for (j=0; j<=arm_degree; j++) {
00215                 BT_Number[j][i] = 0;
00216             }
00217         } 
00218 
00219         current_link++; 
00220 
00221         // Main Loop of link path planning from link 2 to link n, link by link,
00222         // and backtracking to permitted level if neccesary     
00223         while ((current_link <= arm_degree) && (path_link == SP_TQ_OK)) {
00224                 blen = 0;
00225                 path_link = plan_path_for_nth_link(current_link,
00226                                 &(tqcs.tqlink[current_link-1]), 
00227                                 block, block_last, &blen, 
00228                                 &BT_flag, &Block_flag, &Narrow_flag);
00229 
00230                 if (path_link == SP_IF_NOT_OK){
00231                         return false ;
00232                 }
00233                 if (path_link == SP_STOPPING) {
00234                         return false ;
00235                 }
00236                 if (path_link == SP_TQ_OK) { //if path is found for current_link
00237                         on_BT = FALSE;
00238                         BT_level_test = 1;
00239                         current_link++;         //increment current_link 
00240                 } 
00241                 else // prepare for backtracking         
00242                 { 
00243                     on_BT = TRUE;
00244                     BT_flag = 0;
00245                         // narrow region case 
00246                         if(Narrow_flag == 1) {
00247                                 blen = 1;
00248                         }
00249                         // Determine if reached the MAXIMUM number 
00250                         if(BT_Number[current_link][BT_level_test]>=max_bt_no){
00251                                 BT_Number_Record[BT_level_test] += max_bt_no;
00252                                 BT_Number[current_link][BT_level_test] = 0;
00253                                 BT_level_test++;
00254                                 // Check if MAXIMUM BT LEVEL is reached 
00255                                 if(BT_level_test > max_level){
00256                                         path_final = SP_FAILED;
00257                                         return false ;
00258                                 }
00259                                 BT_flag = 1;
00260                                 blen = 1;
00261                         }
00262                 } //end of else
00263 
00264                 // If no path found for the current link, backtracking  
00265                 while ((on_BT == TRUE) && (BT_level_test >= 1) && (BT_level_test <= max_level )) {
00266                         BT_Number[current_link][BT_level_test]++;
00267                     while(BT_Number[current_link][BT_level_test]>max_bt_no){
00268                                 BT_Number_Record[BT_level_test] += max_bt_no;
00269                                 BT_Number[current_link][BT_level_test] = 0;
00270                                 BT_level_test++;
00271                                 // Check if MAXIMUM BT LEVEL is reached 
00272                                 if(BT_level_test>max_level){
00273                                     path_final = SP_FAILED;
00274                                         return false ;
00275                                         break;
00276                                 }
00277                                 BT_Number[current_link][BT_level_test]++;
00278                                 BT_flag = 1;
00279                                 blen = 1;
00280                         }
00281         
00282                         back_to_link = current_link - BT_level_test;
00283 
00284                         // There is no backtracking for link 1  
00285                         if (back_to_link < 2) {
00286                                 return false;
00287                         }
00288 
00289                 // Plan path for the link backtracked to        
00290                         path_link =     plan_path_for_nth_link(back_to_link,
00291                                                 &(tqcs.tqlink[back_to_link-1]),
00292                                                 block, block_last, &blen, 
00293                                                 &BT_flag, &Block_flag, &Narrow_flag);
00294                         
00295                         if (path_link == SP_IF_NOT_OK) {
00296                                 return false ;
00297                         }
00298                         if (path_link == SP_STOPPING) {
00299                                 return false ;
00300                         }
00301                         if (path_link == SP_TQ_OK) {
00302                                 BT_level_test--;
00303                         } 
00304                         else if (path_link == SP_TQ_NOT_OK) {
00305                                 //prepare for continuous backtracking
00306                                 BT_level_test++;
00307                                 if(Narrow_flag == 1)
00308                                         blen = 1;
00309                         } 
00310                         else {
00311                                 return false ;  //something's wrong with the SP
00312                         }
00313                         continue;
00314                 } //end of while (for backtracting)
00315                 
00316                 BT_level_test = 1;
00317                 continue;
00318         } //end of while (of main planner)
00319 
00320         // sum up backtracking numbers
00321         /*
00322         on_BT_max = 0;
00323         for (i=1; i<= max_level; i++) {
00324             for (j=1; j<=arm_degree; j++) {
00325                         if (BT_Number[j][i] > 0) {
00326                             BT_Number_Record[i] += BT_Number[j][i];
00327                                 BT_Number_Record[0] += BT_Number_Record[i];
00328                                 on_BT_max = i;
00329                         }
00330             }
00331             if (BT_Number_Record[i] > 0) {
00332                 printf("\t%4d Times on Level %d\n",
00333                                 BT_Number_Record[i],i);
00334                 //fprintf(resultfile,"\t%4d Times on Level %d\n", 
00335                 //              BT_Number_Record[i],i);
00336             }
00337         }
00338         */
00339         
00340         // compute global path - modified version (07/15)
00341         if ( path_final != SP_FAILED ) 
00342         {
00343                 globaldim = lnkcps[ arm_degree - 1 ].dim + 2;
00344                 globalpath = ( double** ) malloc2D( globaldim, arm_degree, sizeof( double ) );
00345 
00346                 retrieve_global_path(globalpath, globaldim, orig_initial_config, orig_final_config);
00347 
00348                 path.Clear() ;
00349                 Configuration config ;
00350                 config.SetNumDOF( arm_degree ) ;
00351                 for( i = 0; i < globaldim; i++ )
00352                 {
00353                         for( int j = 0; j < arm_degree; j++ )
00354                         {
00355                                 config[ j ] = (globalpath[i][j]*180.0/PI);
00356                         }
00357                         path.AppendPoint( config ) ;
00358                 }
00359                 // for optimization 
00360                 //smoothpath(arm_degree, globaldim, globalpath, &globaldim);
00361 
00362                 //smooth the path
00363                 if( this->m_Smoother != NULL )
00364                 {
00365                         this->m_Smoother->SetPath( &this->path );
00366                         this->m_Smoother->SetCollisionDetector( this->collisionDetector );
00367                         m_Smoother->Smooth();
00368                         this->path = m_Smoother->GetPath();
00369                         m_Smoother->SetPath( NULL );
00370                 }
00371         }
00372         else {
00373                 return (false);
00374         }
00375     
00376         return true ;
00377     
00378   //## end PL_Sequential::Plan%928173143.body
00379 }
00380 
00381 void PL_Sequential::initialize_parameters ()
00382 {
00383   //## begin PL_Sequential::initialize_parameters%930592279.body preserve=yes
00384 
00385         // Assign default sequential planner debug level 
00386         sp_debug_level = 1; 
00387 
00388         // Default distance detect range 
00389         //distance_detect_range = 0.5;
00390 
00391         // Assigning default values     
00392         //dimx = DIMX;
00393         //dimy = DIMY;
00394         //dimz = DIMZ;
00395 
00396         dimt[0] = DIMT;  //resolution of tq map
00397         dimq[0] = DIMQ;  //resolution of tq map
00398 
00399         // maximum backtracking level allowed   
00400         max_level = MAX_BACKTRACKING_LEVEL;
00401 
00402         // maximum backtracking number in a level       
00403         max_bt_no = MAX_BACKTRACKING_NUMBER;
00404 
00405         COEFD_Q = dimq[0]/(2*PI);  //constant set for rad_to_index conversion
00406         COEFQ_D = (2*PI)/dimq[0];  //constant set for index_to_rad conversion
00407 
00408         for (int i=1; i<= arm_degree; i++)
00409         {
00410                 dimq[i] = dimq[0];
00411         }
00412   //## end PL_Sequential::initialize_parameters%930592279.body
00413 }
00414 
00415 void PL_Sequential::SetCollisionDetector (CD_BasicStyle* collisionDetector)
00416 {
00417   //## begin PL_Sequential::SetCollisionDetector%933360621.body preserve=yes
00418         PL_Boolean_Output::SetCollisionDetector( collisionDetector ) ;
00419 
00420         arm_degree = collisionDetector->DOF() ; 
00421         
00422         //set the collision detector so that nothing collides with anything
00423         for( int i = 0; i <= arm_degree; i++ )
00424         {
00425                 for( int j = 0; j <= arm_degree; j++ )
00426                 {
00427                         collisionDetector->DeactivateFrames( i, j ) ; 
00428                 }
00429         }
00430 
00431         tqcs.nlinks = arm_degree;
00432 
00433         initialize_parameters();
00434 
00435         orig_initial_config = (double *) malloc(arm_degree*sizeof(double));
00436         assert( orig_initial_config != NULL );
00437         orig_final_config = (double *) malloc(arm_degree*sizeof(double));
00438     assert( orig_final_config != NULL );
00439     tqcs.tqlink = (TQLinkCSpace *) calloc(arm_degree, sizeof(TQLinkCSpace));
00440         assert( tqcs.tqlink != NULL );
00441     lnkcps = (LinkPath *) calloc(arm_degree, sizeof(LinkPath)); 
00442     assert( lnkcps != NULL );
00443         wall = (unsigned char *) calloc(dimq[0], sizeof(unsigned char) ) ;
00444     assert( wall != NULL );
00445     
00446         for (i=0; i<dimq[0];i++) {
00447                 wall[i] = OBSTACLE;
00448         }
00449 
00450     for (i=0; i<arm_degree; i++) {
00451        lnkcps[i].d = NULL;
00452         }
00453     
00454     // allocate memory for the global path        
00455         allocate_space_for_working_tq_path();     
00456     globalpath = NULL;
00457 
00458   //## end PL_Sequential::SetCollisionDetector%933360621.body
00459 }
00460 
00461 // Additional Declarations
00462   //## begin PL_Sequential%3752D78501D0.declarations preserve=yes
00463 
00464 //=========================================================================================
00465 //int PL_Sequential::insert()
00466 //called by: int PL_Sequential::voro_heuristic2d()
00467 //input:        - int xx
00468 //                      - int yy
00469 //                      - IntPoint **FRONT
00470 //                      - IntPoint *PFRONT
00471 //                      - int nbfront
00472 //                      - short int **V
00473 //functions: to insert latest results into array when computing heuristic map of link
00474 //output: returns incremented nbfront
00475 //=========================================================================================
00476 int PL_Sequential::insert (int xx, int yy, IntPoint **FRONT, IntPoint *PFRONT, int nbfront, 
00477                                                    short int **V)
00478 {
00479         int icur,ipere;
00480         IntPoint *temp;
00481 
00482         nbfront++; 
00483         FRONT[nbfront] = PFRONT++;
00484         FRONT[nbfront]->x = (xx); 
00485         FRONT[nbfront]->y = (yy); 
00486         icur = nbfront;
00487         while(icur > 1){
00488                 ipere = icur/2;
00489                 if(V[FRONT[icur]->x][FRONT[icur]->y] <= V[FRONT[ipere]->x][FRONT[ipere]->y]) 
00490                         break;
00491                 temp = FRONT[icur];
00492                 FRONT[icur] = FRONT[ipere];
00493                 FRONT[ipere] = temp;
00494                 icur = ipere;
00495         }
00496         return (nbfront);
00497 }
00498 
00499 
00500 //=========================================================================================
00501 //int PL_Sequential::deletemin()
00502 //input:        - int xx
00503 //                      - int yy
00504 //                      - IntPoint **FRONT
00505 //                      - int nbfront
00506 //                      - short int **V
00507 //function: ??
00508 //output: returns modified nbfront
00509 //=========================================================================================
00510 int PL_Sequential::deletemin (int xx, int yy, IntPoint **FRONT, int nbfront, short int **V)
00511 {
00512         int icur, inew, ifilsd, ifilsg; 
00513         IntPoint *temp;
00514         
00515         xx = FRONT[1]->x; 
00516         yy = FRONT[1]->y;
00517         FRONT[1] = FRONT[nbfront];
00518         nbfront--;
00519         icur = 1;
00520 
00521         while(icur <= nbfront / 2){
00522                 ifilsg = 2 * icur; 
00523                 ifilsd = 2 * icur + 1;
00524                 if(V[FRONT[ifilsg]->x][FRONT[ifilsg]->y] > V[FRONT[ifilsd]->x][FRONT[ifilsd]->y] || nbfront == ifilsg)
00525                         inew = ifilsg;
00526                 else 
00527                         inew = ifilsd;
00528 
00529                 if(V[FRONT[icur]->x][FRONT[icur]->y] < V[FRONT[inew]->x][FRONT[inew]->y]){
00530                         temp = FRONT[icur];
00531                         FRONT[icur] = FRONT[inew];      
00532                         FRONT[inew] = temp;
00533                         icur = inew;
00534                 }
00535                 else break;
00536         }
00537         return (nbfront);
00538 }
00539 
00540 
00541 //=========================================================================================
00542 //int PL_Sequential::plan_path_for_first_link()
00543 //input: none
00544 //function: plan path for link0; lnkcps[0] includes the max. reachable free space of link0
00545 //output: returns a flag to indicate if path for link0 can be found
00546 //=========================================================================================
00547 int PL_Sequential::plan_path_for_first_link( void )
00548 {
00549         int     col_rc, i, j, iminable, imaxable, fminable, fmaxable, connect_case;
00550         int     blocked;
00551         unsigned char   **map;
00552         TQConfig        start, end;
00553         double          ft;
00554         TQConfig        *para;
00555 
00556         //determine if boundary of t and q exist
00557     tqcs.tqlink[0].t_bound = FALSE;                     // No t boundary for first link 
00558     if (!(joint_limit[0].status))
00559         tqcs.tqlink[0].q_bound = FALSE;         // Boundary for q    
00560     else
00561         tqcs.tqlink[0].q_bound = TRUE;          // No boundary for q    
00562 
00563         //assign map to be tq-map (bitmap) of link0
00564         map = tqcs.tqlink[0].bitmap;  
00565         
00566         //a dummy variable
00567         para = (TQConfig *) malloc (sizeof(TQConfig));
00568         para[0].t = 0;
00569         para[0].q = 0;
00570 
00571         //t is irrevalent for link0; compute a column of tq-map for link0
00572         col_rc = compute_a_column_for_link_cspace(tqcs.tqlink, 1, 0, para);
00573     if (col_rc == SP_STOPPING) {
00574                 return(false);
00575     }
00576         
00577         free(para);  //free dummy variable
00578 
00579     // determine if tq-space is blocked horizontally
00580     blocked = false;
00581     for (j=0; j<tqcs.tqlink[0].dimq; j++) { 
00582         if ( map[0][j] == OBSTACLE) {
00583             blocked = true;
00584             break;
00585         }
00586         } 
00587         
00588         // since t is irrevalent for link0, all columns of tq-map for link0 are identical;
00589         // copy column for all t in order to complete tq-map for link0
00590         for (j=1; j<tqcs.tqlink[0].dimt; j++) {
00591                 for (i=0; i<tqcs.tqlink[0].dimq; i++) { 
00592             map[j][i] = map[0][i];
00593                 } 
00594         }
00595 
00596         // Find the reachable space range in cspace
00597     // look for lowest reachable bound from start
00598     iminable = initial_config[0];
00599         while ((iminable>=0) || blocked)
00600         {
00601             if (map[0][(iminable+dimq[0])%dimq[0]]==FREESPACE)
00602                 {
00603                         iminable--;
00604                 }
00605         else
00606                 {
00607                         break;
00608                 }
00609         }
00610     iminable++;    // Found the low reachable bound from start    
00611 
00612         // look for highest reachable bound from start
00613     imaxable = initial_config[0];
00614     while ((imaxable<tqcs.tqlink[0].dimq) || blocked)
00615         {
00616                 if (map[0][imaxable%dimq[0]]==FREESPACE)
00617                 {
00618                         imaxable++;
00619                 }
00620         else 
00621                 {
00622                         break;
00623                 }
00624         }
00625     imaxable--;    // Found the high reachable bound from start    
00626 
00627         // look for lowest reachable bound from goal
00628     fminable = final_config[0];
00629     while ((fminable>=0) || blocked) 
00630         {
00631                 if (map[0][(fminable+dimq[0])%dimq[0]]==FREESPACE)
00632                 {
00633                         fminable--;
00634                 }
00635         else 
00636                 {
00637                         break;
00638                 }
00639         }
00640     fminable++;    // Found the low reachable bound from goal    
00641 
00642         // look for highest reachable bound from goal
00643     fmaxable = final_config[0];
00644     while ((fmaxable<tqcs.tqlink[0].dimq) || blocked)
00645         {
00646                 if (map[0][fmaxable%dimq[0]]==FREESPACE)
00647                 {
00648                         fmaxable++;
00649                 }
00650         else
00651                 {
00652                         break;
00653                 }
00654         }
00655     fmaxable--;    // Found the high reachable bound from goal    
00656 
00657     // The simplest case in tq-map of link0:            
00658     //    obstacle area
00659     //   *  **********************************
00660     //   *  ssssssssssssssssssssssssssssssssss
00661     // ^ *             
00662     // | *                              free space
00663     // q *  gggggggggggggggggggggggggggggggggg                      
00664     //   *  **********************************
00665     //     obstacle area
00666         //              t ->
00667  
00668         if (((initial_config[0]>fminable)&&(initial_config[0]<fmaxable))
00669                 || ((final_config[0]>iminable)&&(final_config[0]<imaxable))
00670                 || (initial_config[0]==final_config[0]))
00671         connect_case = 0;
00672         // I and F are seperated by a middle obstacle   
00673     else {            
00674         if (tqcs.tqlink[0].q_bound)
00675             return (false);  //no path exists for lnk1
00676         if ( ((iminable<=0) && (fmaxable>=(tqcs.tqlink[0].dimq-1)) ) 
00677                         || ((fminable <=0) && (imaxable>=(tqcs.tqlink[0].dimq-1) ) ) )
00678           connect_case = 1;
00679         else
00680             return (false);  //no path exists for lnk1
00681     }
00682 
00683     // build a path for each connection case        
00684     start.t = 0;                //initial t of path for link0
00685     end.t = dimt[0]-1;  //final t of path for link0
00686 
00687         allocate_space_for_Link_tq_path(0, dimt[0]);
00688         
00689     // determine start and end q according to the connection case    
00690     if (connect_case == 0) {
00691         if (initial_config[0] <= final_config[0]) {
00692             start.q = iminable;    end.q = fmaxable;
00693         }
00694         else {
00695             start.q = imaxable;    end.q = fminable;
00696         }
00697         lnkcps[0].dim = dimt[0];
00698     }
00699     else if (connect_case == 1) {
00700         if (initial_config[0] <= final_config[0]) {
00701             start.q = imaxable;
00702             end.q = fminable-dimq[0];  // mod modification for a path
00703         }
00704         else {
00705             start.q = iminable;
00706             end.q = fmaxable+dimq[0];  // mod modification for a path
00707         }
00708     }
00709     else {
00710                 return (false);  
00711         }
00712 
00713     // Determine if q bound exits        
00714     if ((start.q==((end.q+1)%dimq[0])) || ((end.q%dimq[0])==((start.q+1)%dimq[0])))
00715         tqcs.tqlink[0].q_bound = FALSE;
00716     else
00717         tqcs.tqlink[0].q_bound = TRUE;
00718 
00719     // Determine path bound for next link path plan    
00720     if ( !(tqcs.tqlink[0].t_bound) && !(tqcs.tqlink[0].q_bound) )
00721         tqcs.tqlink[0].p_bound = FALSE;
00722     if ( tqcs.tqlink[0].p_bound ) {
00723         lnkcps[0].d[0].t = start.t;
00724         lnkcps[0].d[0].q = ROUND(start.q);
00725         lnkcps[0].d[dimq[0]-1].t = end.t;
00726         lnkcps[0].d[dimq[0]-1].q = ROUND(end.q);
00727         start.t += 1; end.t -= 1;  // Leave a column for bounding        
00728     }
00729 
00730     // generate a linear path for link0, starting from lowest reachable from start,
00731         // to highest reachable from goal
00732         for (i = start.t, ft = start.t; i <= end.t; i++, ft++) {
00733         lnkcps[0].d[i].t = i;  
00734         lnkcps[0].d[i].q = ROUND(ft*(end.q-start.q)/(double)dimt[0]+start.q);
00735         lnkcps[0].d[i].q = (lnkcps[0].d[i].q +dimq[0]) %dimq[0];
00736         // record t,q initial and final in link path        
00737         if (lnkcps[0].d[i].q % dimq[0] == initial_config[0]) {
00738             initial_tq[0].t = i;
00739             initial_tq[0].q = lnkcps[0].d[i].q;
00740                 }
00741         if (lnkcps[0].d[i].q % dimq[0] == final_config[0]) {
00742             final_tq[0].t = i;
00743             final_tq[0].q = lnkcps[0].d[i].q;
00744                 }
00745     }
00746 
00747         // ensure q in lnkcps[0] are incremental (i.e. relative to its previous step)
00748         if (sp_debug_level >0) {
00749                 for (i=0; i< dimt[0]; i++) {
00750             lnkcps[0].d[i].q = lnkcps[0].d[i].q % dimq[0];
00751         }
00752         }
00753 
00754         //programmer outputs
00755         /*
00756     if (sp_debug_level >0) {
00757         printf("Initial and final tq configuration at link 1 are:\n");
00758         printf("\t\t(%d, %d)->(%d, %d).\n", initial_tq[0].t, initial_tq[0].q,
00759             final_tq[0].t, final_tq[0].q);
00760             write_map("DATA/link1obs.map", TQ_CSpace_Obs,
00761             (char **) tqcs.tqlink[0].bitmap, dimt[0], dimq[0],
00762             sizeof(unsigned char));
00763         write_linkpath("DATA/link1path.dat", TQ_CSpace_Path,
00764             (char *) lnkcps[0].d, dimt[0], sizeof(TQConfig) );
00765         write_linkpathtxt("DATA/link1path.txt", lnkcps[0].d, dimt[0]);
00766         write_tqif("DATA/link1if.dat", initial_tq[0], final_tq[0]);
00767     }
00768         */
00769         
00770     // prepare the dimensions for next link    
00771         dimt[1] = lnkcps[0].dim;     
00772        
00773     free_space_for_link_cs(0);  // free memory
00774 
00775     return(SP_TQ_OK); // return flag to indicate path found for link0
00776 
00777 } // plan_path_for_first_link()    
00778 
00779 
00780 //=========================================================================================
00781 //int PL_Sequential::path_path_for_nth_link()
00782 //input:        - int lnkno
00783 //                      - TQLinkCSpace *ptqlink
00784 //                      - TQConfig *pblock
00785 //                      - TQConfig *pblock_last
00786 //                      - int *bl (not used)
00787 //                      - int *BT_Flag
00788 //                      - int *block_flag
00789 //                      - int *narrow_flag
00790 //functions: find plan for nth link
00791 //output: returns a flag to indicate if path is found for linkn
00792 //=========================================================================================
00793 int PL_Sequential::plan_path_for_nth_link(      int lnkno, 
00794                                 TQLinkCSpace *ptqlink, 
00795                                 TQConfig *pblock,
00796                                 TQConfig *pblock_last, 
00797                                 int *bl, 
00798                                 int *BT_Flag, 
00799                                 int *block_flag,
00800                                 int *narrow_flag)
00801 {
00802         int     tq_rc, i, j ;
00803         int lnkno1, path_found; 
00804         int     ipos, fpos;
00805         IntPoint        pinitial, pfinal;
00806         TQConfig        tqi, tqf;
00807         int blockwidth = 0;
00808         
00809         // activate frame_to_frame collision detection
00810         for (i = 0; i < lnkno; i++)
00811         {
00812                 collisionDetector->ActivateFrames(i, lnkno);
00813         }
00814         
00815     lnkno1 = lnkno - 1 ;        //array indexing convention
00816 
00817         // determine the initial TxQ position in TxQ space        
00818     tqi.t = pinitial.x = initial_tq[lnkno-2].t;
00819     tqi.q = pinitial.y = initial_config[lnkno1]; 
00820 
00821     // determine the final TxQ position in TxQ space        
00822     tqf.t = pfinal.x = final_tq[lnkno-2].t;
00823     tqf.q = pfinal.y = final_config[lnkno1];
00824 
00825         // Allocate space for link c-space    
00826         allocate_space_for_link_cs(lnkno1);
00827 
00828         //compute obstacle map for link n
00829         tq_rc = compute_cspace_obstacle_map(lnkno);
00830         if (tq_rc == SP_STOPPING) {
00831                 free_space_for_link_cs(lnkno1);
00832                 return(tq_rc);
00833         }
00834         
00835         if (*bl) //in backtracking
00836         {
00837                 blockwidth = *bl;
00838                 const int RESERVED_SIZE = 2;
00839 
00840                 for (i = 0; i < blockwidth; i++) 
00841                 {
00842                         for (int k = pblock[i].t - blockwidth; k < pblock[i].t + blockwidth; k++) 
00843                                 {
00844                                         for (j = pblock[i].q - blockwidth; j < pblock[i].q + blockwidth; j++)
00845                                         {
00846                                                 if ((ABS(tqi.t - k) > RESERVED_SIZE)
00847                                                         && (ABS(tqi.q - j) > RESERVED_SIZE)
00848                                                 && (ABS(tqf.t - k) > RESERVED_SIZE)
00849                                                         && (ABS(tqf.q - j) > RESERVED_SIZE))
00850                                                 {
00851                                                                 ptqlink->bitmap[(k+dimt[lnkno1]) % dimt[lnkno1]]
00852                                                                         [(j+dimq[lnkno1]) % dimq[lnkno1]] 
00853                                                                         = OBSTACLE;
00854                                                 }
00855                                         }
00856                                 }
00857                 }
00858                         
00859                 // Collision Check
00860                 if (ptqlink->bitmap[pinitial.x][pinitial.y] == OBSTACLE) {
00861                         pblock[0].t = lnkcps[lnkno1-1].d[pinitial.x].t;
00862                         pblock[0].q = lnkcps[lnkno1-1].d[pinitial.x].q;
00863                         *bl = 1;
00864                         free_space_for_link_cs(lnkno1);
00865                         return(SP_TQ_NOT_OK);   //requires further backtracking
00866                 }
00867 
00868                 // test if goal is in obstacle    
00869                 if (ptqlink->bitmap[pfinal.x][pfinal.y] == OBSTACLE) {
00870                 pblock[0].t = lnkcps[lnkno1-1].d[pfinal.x].t;
00871                     pblock[0].q = lnkcps[lnkno1-1].d[pfinal.x].q;
00872                         *bl = 1;
00873                         free_space_for_link_cs(lnkno1);
00874                         return(SP_TQ_NOT_OK);  //requires further backtracking
00875                 }
00876         }
00877         else 
00878         {
00879                 // Collision Check
00880             // test if start is in obstacle   
00881                 if (ptqlink->bitmap[pinitial.x][pinitial.y] == OBSTACLE) {
00882                         free_space_for_link_cs(lnkno1);
00883                         return(SP_IF_NOT_OK);   
00884                 }
00885 
00886                 // test if goal is in obstacle    
00887                 if (ptqlink->bitmap[pfinal.x][pfinal.y] == OBSTACLE) {
00888                 free_space_for_link_cs(lnkno1);
00889                         return(SP_IF_NOT_OK);
00890                 }
00891         }
00892         
00893                 //GILL: added for debugging (07/15)
00894 /*#ifdef PC_PROTO               
00895                 bitmap.SetResolution( ptqlink->dimt, ptqlink->dimq );
00896                 bitmap.Clear();
00897                 char namedialog[ 300 ];
00898                 sprintf( namedialog, "obstacle map for link %d", lnkno ) ;
00899                 bitmap.NameDialog( namedialog ) ;
00900                 bitmap.Display();
00901 
00902                 for (int a = 0; a < ptqlink->dimt; a++) 
00903                 {
00904                         for (int b = 0; b < ptqlink->dimq; b++)
00905                         {
00906                                 if ((a==pinitial.x) && (b==pinitial.y))
00907                                 {
00908                                         //fprintf(stream, ";");
00909                                         bitmap.PutPixel(a, b, 0);
00910                                 }
00911                                 else if ((a==pfinal.x) && (b==pfinal.y))
00912                                 {
00913                                         //fprintf(stream, ";");
00914                                         bitmap.PutPixel(a, b, 0);
00915                                 }
00916                                 else if (ptqlink->bitmap[a][b] == OBSTACLE) 
00917                                 //if (ptqlink->bitmap[a][b] == OBSTACLE) 
00918                                 {
00919                                         bitmap.PutPixel( a, b, 0 );
00920                                         //fprintf(stream, ";");
00921                                 }
00922                                 else if (ptqlink->bitmap[a][b] == FREESPACE) 
00923                                 {
00924                                         bitmap.PutPixel( a, b, 1 );
00925                                         //fprintf(stream, "|");
00926                                 }       
00927                         }               
00928                         //fprintf( stream, "\n" ) ;
00929                 } 
00930                 //fclose(stream);  
00931                 //end of Gill outputs
00932                 bitmap.Display();
00933 #endif          
00934 */
00935     // determine whether bounds exist for t, q parameters        
00936     if (joint_limit[lnkno1].status)
00937         ptqlink->q_bound = TRUE;
00938     else
00939         ptqlink->q_bound = FALSE;
00940 
00941     if ((tqcs.tqlink[lnkno-2].p_bound) || (tqcs.tqlink[lnkno-2].q_bound))
00942         ptqlink->t_bound = TRUE;
00943     else
00944         ptqlink->t_bound = FALSE;
00945 
00946     if (ptqlink->t_bound || ptqlink->q_bound)
00947         ptqlink->p_bound = TRUE;
00948 
00949     // Block both end of the TxQ space if t bound exist        
00950     if (ptqlink->t_bound) {
00951         for (j=0; j<dimq[lnkno1]; j++)
00952             ptqlink->bitmap[0][j]
00953                 = ptqlink->bitmap[dimt[lnkno1]-1][j] = OBSTACLE;
00954     }
00955 
00956     // Find the main path of the whole path, ie. from initial to final  
00957         path_found = find_main_path(lnkno, &pinitial, &pfinal,
00958                                 ptqlink, &mainpath, narrow_flag);
00959 
00960     if (!path_found) {
00961                 if((pblock_last[0].t == mainpath.d[0].t) && (pblock_last[0].q == mainpath.d[0].q))
00962                 {
00963                         *block_flag = 1;
00964                         pblock_last[0].t = 0;
00965                         pblock_last[0].q = 0;
00966                 } 
00967                 else 
00968                 {
00969                         *block_flag = 0;
00970                         pblock_last[0].t = mainpath.d[0].t;
00971                         pblock_last[0].q = mainpath.d[0].q;
00972                 }
00973                 if (lnkno > 2) { // Note, there is no backtracking for link 1 and 2 
00974          for (i = 0 ; i < MIN(mainpath.dim, 99) ; i++) {
00975                            pblock[i].t = lnkcps[lnkno1-1].d[mainpath.d[i].t].t;
00976                pblock[i].q = lnkcps[lnkno1-1].d[mainpath.d[i].t].q;
00977                         }
00978                 }
00979  
00980                 *bl = MIN(mainpath.dim, 99); // store block width 
00981 
00982             free_space_for_link_cs(lnkno1);
00983    
00984                 return(SP_TQ_NOT_OK);  //flag to indicate back tracking
00985         }
00986         
00987     // Find the forward extention path, ie. final to  ??????    
00988     if (lnkno != arm_degree)
00989         find_forward_extension(lnkno, &pinitial, &pfinal, ptqlink, &frwdpath);
00990     else
00991         frwdpath.dim = 0;
00992 
00993     // Find the backward extention path, ie. initial to  ?????? 
00994     if (lnkno != arm_degree)
00995         find_backward_extension(lnkno, &pinitial, &pfinal, ptqlink, &bkwdpath);
00996     else
00997         bkwdpath.dim = 0;
00998 
00999     // Connect the three parts of path into a whole path        
01000     combine_three_paths(&combpath, &mainpath, &frwdpath, &bkwdpath, &ipos, &fpos);
01001 
01002         if (NO_PATH_COMPRESS) {
01003         if (ptqlink->p_bound && (lnkno != arm_degree)) {
01004             dimt[lnkno] = combpath.dim+2;
01005             allocate_space_for_Link_tq_path(lnkno1, dimt[lnkno]);  // Allocate memory for link TQ path     
01006             reparameterize_path(ptqlink->p_bound, &combpath, &(lnkcps[lnkno1]), 
01007                                 &ipos, &fpos, lnkno);
01008         }
01009         else {
01010             if (ptqlink->p_bound)
01011                         {
01012                                 dimt[lnkno] = combpath.dim+2;
01013                         }
01014             else
01015             {
01016                                 dimt[lnkno] = combpath.dim;
01017                         }
01018             allocate_space_for_Link_tq_path(lnkno1, dimt[lnkno]);
01019             reparameterize_path(ptqlink->p_bound, &combpath, &(lnkcps[lnkno1]), 
01020                                 &ipos, &fpos, lnkno);
01021         }
01022     }
01023     else {
01024                 dimt[lnkno] = dimt[0];
01025                 allocate_space_for_Link_tq_path(lnkno1, dimt[lnkno]);  // Allocate memory for link TQ path     
01026         // Reparameterize the whole path to pre-defined dimension  
01027         reparameterize_path(ptqlink->p_bound, &combpath, &(lnkcps[lnkno1]), 
01028                         &ipos, &fpos, lnkno);
01029     }
01030 
01031     // mark the initial and final position on the path        
01032     initial_tq[lnkno1].t = ipos;
01033     initial_tq[lnkno1].q = lnkcps[lnkno1].d[ipos].q;
01034 
01035     final_tq[lnkno1].t = fpos;
01036     final_tq[lnkno1].q = lnkcps[lnkno1].d[fpos].q;
01037     *bl = 0;
01038 
01039     dimt[lnkno] = lnkcps[lnkno1].dim;  // dimension of t for current link
01040 
01041         // ensure q in lnkcps[n] is incremental (i.e. relative to its previous step)
01042         if (sp_debug_level > 0) {
01043                 for (i=0; i<dimt[lnkno]; i++) {
01044             lnkcps[lnkno1].d[i].q = lnkcps[lnkno1].d[i].q % dimq[lnkno1];
01045                 }                       
01046         }
01047 
01048         // programmer outputs
01049         //outputs heuristic map, distance map, and voronoi map to file 
01050         /*
01051         if (sp_debug_level>0) {
01052                 sprintf(fname,"link%dheur.map", lnkno);
01053                 write_map(fname, TQ_CSpace_Heuristic_Map, ptqlink->potential, dimt[lnkno1], dimq[lnkno1], sizeof(short int) );
01054                 sprintf(fname,"link%dvoro.map", lnkno);
01055                 write_map(fname, TQ_CSpace_Voronoi_Map, ptqlink->voro, dimt[lnkno1], dimq[lnkno1], sizeof(unsigned char) );
01056         }
01057 
01058     // generate tq space distance bitmap file name. 
01059         sprintf(fname,"link%1ddis.map",lnkno);
01060     write_distance_map(fname, TQ_CSpace_Distance_Map, (short int **) ptqlink->distmap, dimt[lnkno1], dimq[lnkno1], sizeof(short int) );
01061         
01062         if (sp_debug_level>0) {
01063         sprintf(fname,"DATA/link%dobs.map", lnkno);
01064         write_map(fname, TQ_CSpace_Obs, ptqlink->bitmap,
01065             dimt[lnkno1], dimq[lnkno1], sizeof(unsigned char) );
01066         sprintf(fname, "DATA/link%1dpath.dat", lnkno);
01067         write_linkpath(fname, TQ_CSpace_Path,
01068              (char *) lnkcps[lnkno1].d, dimt[lnkno], sizeof(TQConfig) );
01069         sprintf(fname, "DATA/link%1dpath.txt", lnkno);
01070         write_linkpathtxt(fname, lnkcps[lnkno1].d, dimt[lnkno]);
01071     }
01072         */
01073         
01074     free_space_for_link_cs(lnkno1);  // free memory
01075 
01076     return(SP_TQ_OK);  // return flag to indicate path found for link n
01077 
01078 } // plan_path_for_nth_link()    
01079 
01080 
01081 //=========================================================================================
01082 //int PL_Sequential::compute_a_column_for_link_cspace()
01083 //intputs:      - TQLinkCSpace *tqlcs
01084 //                      - int lnkno
01085 //                      - TQConfig *para
01086 //functions: compute a column of tq-map for link n, where t is fixed, while q varies
01087 //               in the range of link's upper and lower limits
01088 //output: flag to indicate success  (not necessary ?)
01089 //=========================================================================================
01090 int PL_Sequential::compute_a_column_for_link_cspace(TQLinkCSpace        *tqlcs,
01091                                                                                                     int         lnkno, 
01092                                                                                                     int         col, 
01093                                                                                                         TQConfig        *para)
01094                                                                         
01095 {
01096         int is, ie, lnkno1, k;
01097         unsigned char   *row;
01098         Configuration config;
01099         config.SetNumDOF( arm_degree ) ;
01100         
01101         lnkno1 = lnkno - 1;             // array indexing convention
01102 
01103         row = tqlcs->bitmap[col];       // assign row to be linkn tq-map at fixed t
01104 
01105     if (joint_limit[lnkno1].status) {
01106                 is = joint_limit[lnkno1].start+1;    // linkn's lower limit    
01107         ie = joint_limit[lnkno1].end;        // linkn's upper limit    
01108                  
01109         is = MAX(0,is); 
01110                 ie = MIN(tqlcs->dimq, ie); 
01111 
01112                 for (int i = 0; i < is; i++) {  //mark the unreachable in cspace obstacle
01113             row[i] = OBSTACLE;
01114                 }
01115         for (i = ie; i < tqlcs->dimq; i++) { 
01116                         row[i] = OBSTACLE;
01117                 }
01118 
01119                 for( i = is; i < ie; i++ )
01120                 {
01121                         row[ i ] = FREESPACE ;          //IAN added this for initialization purposes
01122                 }
01123         }
01124     else {
01125         is = 0;
01126         ie = tqlcs->dimq;
01127     }
01128 
01129         //ian added this for initialization purposes
01130         config = GetStartConfig();
01131 
01132         // copies the previous joints variables for collision detection
01133         for( int j = 0; j < lnkno1; j++ )
01134         {
01135                 config[ j ] = (index_to_rad(para[j].q))*180/PI ;                
01136         }
01137 
01138         // at the instance of t (at given configs of link n-1...0), determine if the present
01139         // config of link n is colliding with an obstacle
01140         k = is;
01141     while ( k < ie) 
01142         {
01143                 double joint1Config = index_to_rad( k ) * 180.0 / PI ;  //IMPROVE: use a function to convert to degrees
01144                 config[lnkno1] = joint1Config; 
01145                 if ( !collisionDetector->IsInterfering( config ) ){
01146             row[k] = FREESPACE;
01147                 }
01148         else {
01149             row[k] = OBSTACLE;
01150                 }
01151                 k++;
01152     } 
01153 
01154         return(SP_TQ_OK);  // return a flag to indicate success
01155 
01156 } // compute_a_column_for_link_cspace() 
01157 
01158 
01159 //=========================================================================================
01160 //int PL_Sequential::compute_cspace_obstacle_map()
01161 //intput:       - int lnkno
01162 //function: computes tq obstacle map for link n
01163 //output: flag to indicate success
01164 //=========================================================================================
01165 int PL_Sequential::compute_cspace_obstacle_map(int lnkno)
01166 {
01167         int     tq_rc=SP_TQ_OK, lnkno1;
01168         TQConfig    para[MAX_DEGREE];
01169         
01170     lnkno1 = lnkno - 1;        // array indexing convention
01171         
01172         // For every column of tq-map    
01173     for (int i = 0; i < dimt[lnkno1]; i++) {
01174         // find q for link n-1 
01175             para[lnkno1-1].q = lnkcps[lnkno1-1].d[i].q;
01176         para[lnkno1-1].t = lnkcps[lnkno1-1].d[i].t;
01177         
01178                 // find q for all previous links link n-2...0    
01179                 for (int j=lnkno1-2; j>=0; j--) {
01180                    para[j].t = lnkcps[j].d[ para[j+1].t].t; 
01181                    para[j].q = lnkcps[j].d[ para[j+1].t].q;
01182                 }
01183 
01184                 // Obtain the absolute angles 
01185                 //for (int k=1; k<lnkno1; k++) {
01186                 //  para[k].q = (para[k].q+para[k-1].q+dimq[lnkno1]/2)%dimq[lnkno1];
01187                 //}
01188                 
01189                 // compute each column of the tq-map        
01190                 tq_rc = compute_a_column_for_link_cspace(&(tqcs.tqlink[lnkno1]),
01191               lnkno, i, para); 
01192                 if (tq_rc == SP_STOPPING) {
01193                         break;
01194                 }
01195     }
01196 
01197     return(tq_rc);  // returns flag to indicate success
01198 
01199 } // compute_cspace_obstacle_map()      
01200 
01201 
01202 //=========================================================================================
01203 //void PL_Sequential::convert_angle_to_index()
01204 //input: none
01205 //function: convert link configs into lookup table
01206 //=========================================================================================
01207 void PL_Sequential::convert_angle_to_index(void)
01208 {
01209     // For each angle, plus 180 offset. the 0.5 is for the roundup      
01210     for (int i=0; i<arm_degree; i++) {
01211       initial_config[i] = rad_to_index(orig_initial_config[i]);
01212       final_config[i]   = rad_to_index(orig_final_config[i]);
01213       joint_limit[i].status = original_joint_limit[i].status;
01214       joint_limit[i].start = rad_to_index(original_joint_limit[i].start);
01215       joint_limit[i].end = rad_to_index(original_joint_limit[i].end);
01216     }
01217 } // convert_angle_to_index()   
01218 
01219 
01220 //=========================================================================================
01221 //int PL_Sequential::rad_to_index()
01222 //input: double angle
01223 //function:     convert link config (in radian) into an index 
01224 //output: corresponding index 
01225 //note: modify this function if robot has prismatic joints
01226 //=========================================================================================
01227 int PL_Sequential::rad_to_index( double angle ) 
01228 {
01229     return((int)(COEFD_Q*(angle+PI)+0.5));
01230 } 
01231 
01232 
01233 //=========================================================================================
01234 //double PL_Sequential::index_to_rad()
01235 //input: int index
01236 //function: convert an index into the corresponding link config (in radian)
01237 //output: corresponding link config
01238 //=========================================================================================
01239 double PL_Sequential::index_to_rad( int index )
01240 {
01241      return((double)(COEFQ_D*index - PI));
01242 } 
01243 
01244 
01245 //=========================================================================================
01246 //void PL_Sequential::modify_cspace_obstacle_map()
01247 //note: 
01248 //=========================================================================================
01249 void PL_Sequential::modify_cspace_obstacle_map(TQLinkCSpace     *ptqlink, 
01250                                 TQConfig        *tqi,
01251                                 TQConfig        *tqf, 
01252                                 TQConfig        *pblock,
01253                 int             len, 
01254                                 int             L1, 
01255                                 int             *BT_FLAG, 
01256                                 int             *narrow_flag)
01257 
01258 {
01259 /*
01260     int i, j, k, pblock_extral;
01261         int blockwidth;
01262         int d_max, d_max1, d_count_max, d_count, L1_half;
01263     int d_max_t[100];
01264     int initial_t, final_t;
01265 
01266 
01267         const int RESERVED_SIZE = 2;
01268 
01269     // the resolution of tq space is reduced to 4 degree 
01270     blockwidth = dimq[L1]/32;
01271 
01272     pblock_extral = 0;
01273 
01274         // place a virtual obstacle into tq map of (n-2)th link or
01275         // (n-1)th link if max bt is reached or goal is in narrow
01276         // region respectively.
01277         //
01278 
01279         if(*BT_FLAG == 1 || *narrow_flag == 1) 
01280         {
01281                 if(*BT_FLAG) 
01282                 {
01283                         *BT_FLAG = 0;
01284                 }
01285             
01286                 if(*narrow_flag)
01287                 {
01288                 *narrow_flag = 0;
01289                 }
01290 
01291             L1_half = (final_tq[L1].t - initial_tq[L1].t)/2;
01292             d_count = 1;
01293 
01294             d_max_t[d_count] = initial_tq[L1].t + 2;
01295 
01296             initial_t = initial_tq[L1].t + 2;
01297             final_t = final_tq[L1].t - 2;
01298 
01299             d_max = ptqlink->distmap[lnkcps[L1].d[initial_t].t][lnkcps[L1].d[initial_t].q];
01300 
01301             for(j = initial_t + 1; j <= final_t; j++) 
01302                 {
01303                 d_max1 = ptqlink->distmap[lnkcps[L1].d[j].t][lnkcps[L1].d[j].q];
01304                 if (d_max1 > d_max)
01305                         {
01306                                 d_max = d_max1;
01307                                 d_count = 1;
01308                                 d_max_t[d_count] = j;
01309                 } 
01310                 else if (d_max1 == d_max) 
01311                         {
01312                                 d_count ++;
01313                                 d_max_t[d_count] = j;
01314                 }
01315             }
01316 
01317             d_count_max = d_max_t[1];
01318 
01319             for (j=1; j<d_count; j++) {
01320               if ((initial_t + L1_half - d_max_t[j]) >= (d_max_t[j+1] - L1_half - initial_t))
01321                                 d_count_max = d_max_t[j+1]; 
01322             }
01323 
01324             len = 1;
01325 
01326             pblock[0].t = lnkcps[L1].d[d_count_max].t;
01327             pblock[0].q = lnkcps[L1].d[d_count_max].q;
01328         } // end of outer if
01329 
01330     for (i = 0; i < MIN(len, dimt[L1]/30); i++)
01331         {
01332                 for (k = pblock[i].t + dimt[L1] - blockwidth; 
01333                 k < pblock[i].t + dimt[L1] + blockwidth; k++)
01334                 {
01335                         for (j = pblock[i].q + dimq[L1] - blockwidth;
01336                 j < pblock[i].q + dimq[L1] + blockwidth; j++)
01337                                 {
01338                                         if ( (ABS(tqi->t + dimt[L1] - k) > RESERVED_SIZE)
01339                                         && (ABS(tqi->q + dimq[L1] - j) > RESERVED_SIZE)
01340                                 && (ABS(tqf->t + dimt[L1] - k) > RESERVED_SIZE)
01341                                         && (ABS(tqf->q + dimq[L1] - j) > RESERVED_SIZE) )
01342                                         {
01343                                                 ptqlink->bitmap[(k+dimt[L1])%dimt[L1]][(j+dimq[L1])%dimq[L1]] = OBSTACLE;
01344                                         }
01345                                 }
01346                 
01347                 }
01348             
01349     }
01350         */
01351 } // modify_cspace_obstacle_map
01352 
01353 
01354 //=========================================================================================
01355 //PL_Sequential::find_main_path()
01356 //inputs:       - int lnkno
01357 //                      - IntPoint *tqinitial
01358 //                      - IntPoint *tqfinal
01359 //                      - TQLinkCSpace *ptqlink
01360 //                      - LinkPath *result
01361 //                      - int *narrow_flag
01362 //functions: find main path for link n by computing distance map, voronoi map, and
01363 //                       heuristic map                          
01364 //outputs: flag to indicate if a path is found for link n
01365 //=========================================================================================
01366 PL_Sequential::find_main_path(  int                             lnkno, 
01367                                                                 IntPoint                *tqinitial, 
01368                                                                 IntPoint                *tqfinal, 
01369                                                                 TQLinkCSpace    *ptqlink, 
01370                                                                 LinkPath                *result, 
01371                                                                 int                             *narrow_flag)
01372 {
01373         int     i, j, k, wallpos, mid, t1, t2, width, lnkno1, found; 
01374         unsigned char   *wtmp;
01375 
01376         lnkno1 = lnkno - 1;  //array indexing convention
01377         
01378         // use a wall to block the possible circle in main path 
01379         if ((tqinitial->x !=0 ) && (tqfinal->x != 0))
01380             wallpos =0;
01381         else
01382             wallpos = dimt[lnkno1]-1;
01383         
01384         wtmp = ptqlink->bitmap[wallpos];
01385         ptqlink->bitmap[wallpos] = wall;
01386 
01387         // Computing the distance map and voronoi diagram in TxQ cspace 
01388         distance2d(ptqlink->bitmap, dimt[lnkno1], dimq[lnkno1],
01389                         ptqlink->distmap, ptqlink->voro);
01390 
01391         // Check if final position is valid; if not return final position to replan     
01392         if ((ptqlink->distmap[tqfinal->x][tqfinal->y] < 1 ) 
01393                 || (ptqlink->distmap[tqfinal->x][tqfinal->y] == MAXSHORTINT)) 
01394         {
01395                 result->d[0].t = tqfinal->x;
01396                 result->d[0].q = tqfinal->y;
01397                 result->dim = 1;
01398                 // remove the block wall                
01399                 ptqlink->bitmap[wallpos] = wtmp;
01400                 return(false);
01401         }
01402 
01403         // compute the heuristics in the TQ space       
01404         voro_heuristic2d(ptqlink->bitmap, dimt[lnkno1],
01405                         dimq[lnkno1], *tqfinal,
01406                         ptqlink->distmap,  ptqlink->voro, 
01407                         ptqlink->potential, narrow_flag);
01408 
01409         // check if a path can be found, i.e., heuristic has reached the
01410         // intial position, if not find the place where the block could
01411         // occured, return for replanning
01412 
01413         int startpot = 0;
01414 
01415         startpot = ptqlink->potential[tqinitial->x][tqinitial->y]; // Potential at I 
01416 
01417         if ((startpot < 1) || (startpot >= MAXSHORTINT)) {
01418             if((tqinitial->x == tqfinal->x) && (tqinitial->y == tqfinal->y)) {
01419                         result->d[0].t = tqinitial->x;
01420                         result->d[0].q = tqinitial->y;
01421                         result->dim = 1;
01422                         ptqlink->bitmap[wallpos] = wtmp;
01423                         return(true);  
01424             } // end of if
01425 
01426                 else if (tqinitial->x != tqfinal->x)
01427                 {
01428                         found = false; 
01429                 
01430                         for (i = tqinitial->x + 2; i < tqfinal->x - 2; i++) 
01431                         {
01432                                 width = (i - tqinitial->x) / 2;
01433                                 width = MAX(1, width);
01434                                 width = MIN(dimq[lnkno1]/10, width);
01435 
01436                                 mid = tqinitial->y + (tqfinal->y - tqinitial->y) * (i - tqinitial->x)
01437                                 / (tqfinal->x - tqinitial->x);
01438                                 j = k = mid;
01439                                 
01440                                 while ((k >= 0) || (j < dimq[lnkno1])) 
01441                                 {
01442                                         t1 = i;
01443                                         if ((k >= 0) && ( (mid - k) <= width))
01444                                         {
01445                                                 if ((ptqlink->potential[t1][k] > 0)
01446                                                         && (ptqlink->potential[t1][k] < MAXSHORTINT)) 
01447                                                 {
01448                                                         found = true;
01449                                                         result->d[0].t = t1;
01450                                                         result->d[0].q = k;
01451                                                         result->dim = 1;
01452                                                         break;
01453                                                 }
01454                                         }
01455                                         k--;
01456                                         t2 = i;
01457                                         if ((j < dimq[lnkno1]) && !found && ((j - mid) <= width))
01458                                         {
01459                                                 if ((ptqlink->potential[t2][j] > 0)
01460                                                         &&(ptqlink->potential[t2][j] < MAXSHORTINT)) 
01461                                                 {
01462                                                   found = true;
01463                                                   result->d[0].t = t2;
01464                                                   result->d[0].q = j; 
01465                                                   result->dim = 1; 
01466                                                   break;
01467                                                 }
01468                                         }
01469                                         j++;
01470                                 }  //end of while
01471                                 if (found) break;
01472                         } //end of for
01473 
01474                         // locate the pixel most close to initial position 
01475                         // which is reachable from goal inside for loop,      
01476                         // stored at result->d[0]                             
01477                         i = result->d[0].t-1;
01478                         j = result->d[0].q;
01479                         k = result->dim;
01480                 
01481                         // determine the block width from the pixel found  
01482                         // inside above for loop to the left. k is the width  
01483                         // finally determined and stored in result->dim below 
01484 
01485                         //while (((ptqlink->bitmap[i][j] == OBSTACLE) && (k < MAXBLOCKLENGTH)) 
01486                         //      || ( k < MAXBLOCKLENGTH / 4)) 
01487                         while ((((ptqlink->potential[i][j] < 0) || (ptqlink->potential[i][j] == MAXSHORTINT))
01488                                 && (k < MAXBLOCKLENGTH)) 
01489                                 || ( k < MAXBLOCKLENGTH / 4)) 
01490                         {
01491                                 result->d[k].t = i;
01492                                 result->d[k].q = j;
01493                                 i--; k++;
01494                         }
01495                         
01496                         result->dim = k;
01497 
01498                         // remove the block wall                
01499                         ptqlink->bitmap[wallpos] = wtmp;        
01500                         
01501                         return(false);
01502 
01503                 }  //end of else if
01504 
01505                 else //tqinitial->x == tqfinal->x
01506                 {
01507                         found = false;
01508                         int pos1, pos2, pos3, pos4;
01509                         int cur_x = tqinitial->x;
01510                         int cur_y = ROUND((tqinitial->y + tqfinal->y) / 2);
01511 
01512                         for (i = 0; ((cur_x + i) < dimt[lnkno1]) 
01513                                 && ((cur_x - i) >= 0) 
01514                                 && ((cur_y + i) < dimq[lnkno1]) 
01515                                 && ((cur_y - i) >= 0); i++) 
01516                         {
01517                                 pos1 = (cur_x + i + dimt[lnkno1]) % dimt[lnkno1];
01518                                 pos2 = (cur_x - i + dimt[lnkno1]) % dimt[lnkno1];
01519                                 pos3 = (cur_y + i + dimq[lnkno1]) % dimq[lnkno1];
01520                                 pos4 = (cur_y - i + dimq[lnkno1]) % dimq[lnkno1];
01521 
01522                                 if ((ptqlink->potential[pos1][pos3] > 0)
01523                                         && (ptqlink->potential[pos1][pos3] < MAXSHORTINT))
01524                                 {
01525                                         found = true;
01526                                         result->d[0].t = pos1;
01527                                         result->d[0].q = pos3; 
01528                                         result->dim = 1; 
01529                                         break;
01530                                 }
01531                                 
01532                                 if ((ptqlink->potential[pos2][pos3] > 0)
01533                                         && (ptqlink->potential[pos2][pos3] < MAXSHORTINT)) 
01534                                 {
01535                                         found = true;
01536                                         result->d[0].t = pos2;
01537                                         result->d[0].q = pos3; 
01538                                         result->dim = 1; 
01539                                         break;
01540                                 }
01541                         
01542                                 if ((ptqlink->potential[pos1][pos4] > 0)
01543                                         && (ptqlink->potential[pos1][pos4] < MAXSHORTINT)) 
01544                                 {
01545                                         found = true;
01546                                         result->d[0].t = pos1;
01547                                         result->d[0].q = pos4; 
01548                                         result->dim = 1; 
01549                                         break;
01550                                 }
01551 
01552                                 if ((ptqlink->potential[pos2][pos4] > 0)
01553                                         && (ptqlink->potential[pos2][pos4] < MAXSHORTINT)) 
01554                                 {
01555                                         found = true;
01556                                         result->d[0].t = pos2;
01557                                         result->d[0].q = pos4; 
01558                                         result->dim = 1; 
01559                                         break;
01560                                 }
01561 
01562                                 if ((ptqlink->potential[pos1][cur_y] > 0)
01563                                         && (ptqlink->potential[pos1][cur_y] < MAXSHORTINT)) 
01564                                 {
01565                                         found = true;
01566                                         result->d[0].t = pos1;
01567                                         result->d[0].q = cur_y; 
01568                                         result->dim = 1; 
01569                                         break;
01570                                 }
01571                                 if ((ptqlink->potential[pos2][cur_y] > 0)
01572                                         && (ptqlink->potential[pos2][cur_y] < MAXSHORTINT)) 
01573                                 {
01574                                         found = true;
01575                                         result->d[0].t = pos2;
01576                                         result->d[0].q = cur_y; 
01577                                         result->dim = 1; 
01578                                         break;
01579                                 }
01580                                 if (found) {
01581                                         break;  
01582                                 }
01583                         }
01584                         if (!found) 
01585                         {
01586                                 result->d[0].t = tqinitial->x;
01587                                 result->d[0].q = tqinitial->y;
01588                                 result->dim = 1;
01589                         }
01590                         
01591                         // remove the block wall                
01592                         ptqlink->bitmap[wallpos] = wtmp;        
01593                         
01594                         return(false);
01595                         
01596                 } //end of else
01597 
01598 }//end of outer if
01599 
01600         // Find path by following heuristic     
01601         find_path_by_heuristic(result, ptqlink->potential,
01602                 dimt[lnkno1], dimq[lnkno1], tqinitial, tqfinal);
01603         
01604         // remove the block wall                
01605         ptqlink->bitmap[wallpos] = wtmp;
01606 
01607         return(true);
01608 
01609 } // find_main_path()   
01610 
01611 
01612 //=========================================================================================
01613 //PL_Sequential::find_forward_extension()
01614 //inputs:       - int lnkno
01615 //                      - IntPoint *tqinitial
01616 //                      - IntPoint *tqfinal
01617 //                      - TQLinkCSpace *ptqlink
01618 //                  - LinkPath *result
01619 //function: computes extension from goal to collision-free cspace of link n 
01620 //=========================================================================================
01621 void PL_Sequential::find_forward_extension(int  lnkno, 
01622                                                                 IntPoint        *tqinitial, 
01623                                                                 IntPoint        *tqfinal, 
01624                                                                 TQLinkCSpace    *ptqlink, 
01625                                                                 LinkPath        *result)
01626 {
01627         int     i, j, lnkno1, changesign, found, t, q;
01628         unsigned char   *wtmp;
01629         IntPoint        tqp1, fstart;
01630         int narrow_flag1 = 0;
01631 
01632         lnkno1 = lnkno - 1 ;    // array indexing convension
01633         
01634         // Block the possible circle in forward path    
01635         wtmp = ptqlink->bitmap[(tqinitial->x+1)%dimt[lnkno1]];
01636         ptqlink->bitmap[(tqinitial->x+1)%dimt[lnkno1]] = wall;
01637 
01638         // Computing the distance map and voronoi diagram in TxQ cspace 
01639         distance2d(ptqlink->bitmap, dimt[lnkno1], dimq[lnkno1],
01640                         ptqlink->distmap, ptqlink->voro);
01641   
01642         // compute the heuristics in the TQ space       
01643         voro_heuristic2d(ptqlink->bitmap, dimt[lnkno1], 
01644                         dimq[lnkno1], *tqfinal,
01645                         ptqlink->distmap,  ptqlink->voro, 
01646                         ptqlink->potential, &narrow_flag1);
01647 
01648         // remove the block             
01649         ptqlink->bitmap[(tqinitial->x+1)%dimt[lnkno1]] = wtmp;
01650 
01651         // determine the forward end            
01652         //if (ptqlink->t_bound)
01653                 tqp1.x = dimt[lnkno1]-1;
01654         //else
01655         //      tqp1.x = tqinitial->x;
01656 
01657         if (tqinitial->y < tqfinal->y) {
01658                 changesign = -1;
01659                 if (joint_limit[lnkno-1].status)
01660                         tqp1.y = joint_limit[lnkno-1].end;
01661                 else
01662                         tqp1.y = dimq[lnkno1]-1;
01663         }
01664         else {
01665                 changesign = 1;
01666                 if (joint_limit[lnkno-1].status) 
01667                         tqp1.y = joint_limit[lnkno-1].start;
01668                 else
01669                         tqp1.y = 0;
01670         }
01671 
01672         // determine the false start point              
01673         found = FALSE;
01674         i=0;    
01675         do {
01676                 for (j = i; j >= 0; j--) {
01677                         t = (tqp1.x - j + dimt[lnkno1]) % dimt[lnkno1];
01678                         q = (tqp1.y + ((i-j)*changesign) + dimq[lnkno1]) % dimq[lnkno1];
01679                         if ( ( ptqlink->potential[t][q] > SAFETY_DISTANCE)
01680                                 && ( ptqlink->potential[t][q] != MAXSHORTINT))
01681                         {       
01682                                 found = TRUE; 
01683                                 break; 
01684                         }
01685                 }
01686                 i++;
01687         } while (!found);
01688 
01689         fstart.x = t; fstart.y = q;
01690 
01691         // Find path by following heuristic     
01692         find_path_by_heuristic(result, ptqlink->potential,
01693                         dimt[lnkno1], dimq[lnkno1], tqfinal, &fstart);
01694         
01695 } // find_forward_extension()   
01696 
01697 
01698 
01699 //=========================================================================================
01700 //PL_Sequential::find_backward_extension()
01701 //inputs:       - int lnkno
01702 //                      - IntPoint *tqinitial
01703 //                      - IntPoint *tqfinal
01704 //                      - TQLinkCSpace *ptqlink
01705 //                  - LinkPath *result
01706 //function: computes extension from start to collision-free cspace of link n 
01707 //=========================================================================================
01708 void PL_Sequential::find_backward_extension(    int                     lnkno, 
01709                                                                 IntPoint        *tqinitial, 
01710                                                                 IntPoint        *tqfinal, 
01711                                                                 TQLinkCSpace    *ptqlink, 
01712                                                                 LinkPath        *result)
01713 {
01714         int     i, j, lnkno1, changesign, found, t, q;
01715         unsigned char   *wtmp;
01716         IntPoint        tqp1, fstart;
01717         int narrow_flag2 = 0;
01718 
01719         lnkno1 = lnkno - 1 ;
01720         
01721         // Block the posible circle in forward path     
01722         wtmp = ptqlink->bitmap[(tqfinal->x+dimt[lnkno1]-1)%dimt[lnkno1]];
01723         ptqlink->bitmap[(tqfinal->x+dimt[lnkno1]-1)%dimt[lnkno1]] = wall;
01724 
01725         // Computing the distance map and voronoi diagram in TxQ cspace 
01726         distance2d(ptqlink->bitmap, dimt[lnkno1], dimq[lnkno1],
01727                         ptqlink->distmap, ptqlink->voro);
01728   
01729         // compute the heuristics in the TQ space       
01730         voro_heuristic2d(ptqlink->bitmap, dimt[lnkno1], 
01731                         dimq[lnkno1], *tqinitial, 
01732                         ptqlink->distmap,  ptqlink->voro, 
01733                         ptqlink->potential, &narrow_flag2);
01734 
01735         // remove the block             
01736         ptqlink->bitmap[(tqfinal->x+dimt[lnkno1]-1)%dimt[lnkno1]] = wtmp;
01737 
01738         // determine the backward end           
01739         //if (ptqlink->t_bound)
01740                 tqp1.x = 0;
01741         //else
01742         //      tqp1.x = tqfinal->x;
01743 
01744         if (tqinitial->y < tqfinal->y) {
01745                 changesign = 1;
01746                 if (joint_limit[lnkno1].status)
01747                         tqp1.y = joint_limit[lnkno1].start;
01748                 else
01749                         tqp1.y = 0;
01750         }
01751         else {
01752                 changesign = -1;
01753                 if (joint_limit[lnkno1].status)
01754                         tqp1.y = joint_limit[lnkno1].end;
01755                 else
01756                         tqp1.y = dimq[lnkno1]-1;
01757         }
01758 
01759         // determine the false start point              
01760         found = FALSE;
01761         i=0;    
01762         do {
01763                 for (j=0; j<=i; j++) {
01764                         t = (tqp1.x + j)%dimt[lnkno1];
01765                         q = (tqp1.y + (i-j)*changesign +dimq[lnkno1])%dimq[lnkno1];
01766                         if ( ( ptqlink->potential[t][q] > SAFETY_DISTANCE)
01767                                 && ( ptqlink->potential[t][q] != MAXSHORTINT))
01768                                 { found = TRUE; break; }
01769                 }
01770                 i++;
01771         } while (!found);
01772 
01773         fstart.x = t; fstart.y = q;
01774 
01775         // Find path by following heuristic     
01776         find_path_by_heuristic(result, ptqlink->potential,
01777                         dimt[lnkno1], dimq[lnkno1], &fstart, tqinitial);
01778         
01779 } // find_backward_extension()  
01780 
01781 
01782 
01783 //=========================================================================================
01784 //PL_Sequential::combine_three_paths()
01785 //inputs:       - LinkPath *combpath
01786 //                      - LinkPath *mainpath
01787 //                      - LinkPath *frwdpath
01788 //                      - LinkPath *bkwdpath
01789 //                      - int *iposition
01790 //                      - int *fposition
01791 //function: combine backward-extended, main, and forward-extended paths for link n
01792 //=========================================================================================
01793 void PL_Sequential::combine_three_paths(        LinkPath                *combpath, 
01794                                                         LinkPath                *mainpath, 
01795                                                         LinkPath                *frwdpath, 
01796                                                         LinkPath                *bkwdpath,
01797                                                         int                             *iposition, 
01798                                                         int                             *fposition)
01799 {
01800         int     dim, i;
01801    
01802         dim = 0;
01803 
01804         // Backward path        
01805         for (i=0; i<bkwdpath->dim-1; i++) {
01806                 combpath->d[dim].t = bkwdpath->d[i].t;
01807                 combpath->d[dim].q = bkwdpath->d[i].q;
01808                 dim++;
01809         }
01810 
01811         *iposition = dim;       // record initial position index        
01812 
01813         // Main path, ignore duplicate  
01814         for (i=0; i<mainpath->dim; i++) {
01815                 combpath->d[dim].t = mainpath->d[i].t;
01816                 combpath->d[dim].q = mainpath->d[i].q;
01817                 dim++;
01818         }
01819 
01820         *fposition = dim-1;     // record final position index          
01821 
01822         // Forward path 
01823         for (i=frwdpath->dim-2; i>=0; i--) {
01824                 combpath->d[dim].t = frwdpath->d[i].t;
01825                 combpath->d[dim].q = frwdpath->d[i].q;
01826                 dim++;
01827         }
01828 
01829         combpath->dim = dim;
01830 
01831         // Check path length limit      
01832         if (combpath->dim > combpath->maxdim)
01833                 printf("***** Warning, Combined path limit over.*****\n");
01834 
01835 } //combine_three_paths()       
01836 
01837 
01838 
01839 //=========================================================================================
01840 //void PL_Sequential::distance2d()
01841 //inputs:       - unsigned char **in
01842 //                      - int dimx
01843 //                      - int dimy
01844 //                      - short int **V
01845 //                      - unsigned char **voro
01846 //function: computes distance map and voronoi map 
01847 //=========================================================================================
01848 void PL_Sequential::distance2d(unsigned char **in,      int dimx, int dimy,     short int **V, 
01849                                                            unsigned char **voro)
01850 {
01851         int i, dimx1, dimy1;
01852         register int x,y;
01853         Int2DPoint *FRONT,*NEXT,*TEMP;
01854         Int2DPoint *MFRONT, *MNEXT;
01855         int nbfront = 0, nbnext = 0 , nbskele = 0;
01856         Int2DPoint ***pere,*pepere; 
01857         Int2DPoint *Mpepere; 
01858         int px, py;
01859 
01860         dimx1 = dimx - 1;       // array indexing convension
01861         dimy1 = dimy - 1;       // All (x-1)%dimx and (y-1)%dimy are replaced by
01862                                                 // (x+dimx1)%dimx and (y+dimy1)%dimy               
01863 
01864         // Cells in the current distance-wave front will be stored in FRONT, the 
01865         // next-front cells (neighbors of FRONT's cells with distance greater by 1) 
01866         // will be stored in NEXT 
01867 
01868         MFRONT= FRONT = (Int2DPoint *)malloc(100*(dimx+dimy)*sizeof(Int2DPoint));
01869         MNEXT= NEXT  = (Int2DPoint *)malloc(100*(dimx+dimy)*sizeof(Int2DPoint));
01870 
01871         // To detect collision of two "distinct" L1-distance fronts (which determine 
01872         // a voronoi cell), the (x,y) coordinates of every "source" cell (one whose 
01873         // L1 distance is 1) are recorded in pepere[]. Then, every cell encountered 
01874         // by the wave originated at this cell gets a pointer (stored in pere[][]) 
01875         // to the cell in pere[] containing the (x,y) coordinates of the source cell 
01876         // (note that pepere[] stores only source cells).
01877         //
01878         Mpepere= pepere = (Int2DPoint *)malloc(100*(dimx+dimy)*sizeof(Int2DPoint));
01879         pere = (Int2DPoint ***)malloc2D(dimx,dimy,sizeof(Int2DPoint *));
01880 
01881         // Put '1' in any obstacle-free workspace cell that has a 1-neighbor which
01882         // is an obstacle cell, store its (x,y) coordinates in pepere[], put a pointer
01883         // to this pepere[] cell in pere[][].
01884         
01885         for(x=0;x<dimx;++x) {
01886                 for(y=0;y<dimy;++y) {
01887                         if(in[x][y] == OBSTACLE)
01888                                 {
01889                                   V[x][y] = 0;
01890                                   continue;
01891                                 }
01892                         if(in[(x+1)%dimx][y] == OBSTACLE || 
01893                            in[(x+dimx1)%dimx][y] == OBSTACLE ||
01894                            in[x][(y+1)%dimy] == OBSTACLE ||
01895                            in[x][(y+dimy1)%dimy] == OBSTACLE) 
01896                         {
01897                                 V[x][y] = 1; 
01898                                 FRONT[nbfront].x = pepere->x = x;
01899                                 FRONT[nbfront].y = pepere->y = y; 
01900                                 nbfront++;
01901                 pere[x][y] = pepere++; 
01902                         } 
01903                         else {
01904                                 V[x][y] = MAXSHORTINT;
01905                                 // free cells whose L1 distance * is > 1 
01906                         }
01907                 }
01908         } //end of outer for
01909 
01910         // There are nbfront cells marked by '1' in V[][], their coordinates were 
01911         // chronologically stored in FRONT[].
01912 
01913         for(i = 0; i < nbfront; ++i){
01914                 x = FRONT[i].x;
01915                 y = FRONT[i].y;
01916 
01917             if(in[(x+1)%dimx][y] == OBSTACLE ) 
01918                 pere[(x+1)%dimx][y] = pere[x][y];
01919 
01920                 if(in[(x+dimx1)%dimx][y] == OBSTACLE ) 
01921             pere[(x+dimx1)%dimx][y] = pere[x][y];
01922 
01923             if(in[x][(y+1)%dimy] == OBSTACLE ) 
01924                 pere[x][(y+1)%dimy] = pere[x][y];
01925 
01926                 if(in[x][(y+dimy1)%dimy] == OBSTACLE ) 
01927             pere[x][(y+dimy1)%dimy] = pere[x][y];
01928 
01929             if(in[(x+1)%dimx][(y+1)%dimy] == OBSTACLE ) 
01930             pere[(x+1)%dimx][(y+1)%dimy] = pere[x][y];
01931 
01932             if(in[(x+1)%dimx][(y+dimy1)%dimy] == OBSTACLE ) 
01933                 pere[(x+1)%dimx][(y+dimy1)%dimy] = pere[x][y];
01934 
01935                 if(in[(x+dimx1)%dimx][(y+1)%dimy] == OBSTACLE ) 
01936                         pere[(x+dimx1)%dimx][(y+1)%dimy] = pere[x][y];
01937 
01938             if(in[(x+dimx1)%dimx][(y+dimy1)%dimy] == OBSTACLE ) 
01939                 pere[(x+dimx1)%dimx][(y+dimy1)%dimy] = pere[x][y];
01940         }
01941 
01942         // This is the main loop. Each of FRONT's cells, (x,y), acts as a wave source.
01943         // Its 1-neighbors are explored, the ones which are obstacle-free and unmarked
01944         // are marked by V[x][y]+1 and added to NEXT. The coordinates of their
01945         // original source are recorded in pere[][]. If a neighbor is already marked,
01946         // the neighbor's source cell is compared to the source of the current cell.
01947         // If the two sources are "sufficiently" apart, the neighbor is added to the
01948         // voronoi diagram. This process is repeated on NEXT's cells
01949  
01950         for (x = 0; x < dimx; x++)   // initialize the voronoi diagram  
01951         {
01952                 for (y = 0; y < dimy; y++)
01953                 {
01954                         voro[x][y] = 0;
01955                 }
01956         }
01957         
01958         while(nbfront > 0) {
01959         nbnext = 0;
01960    
01961                 for(i = 0; i < nbfront; ++i) 
01962                 {
01963                   x = FRONT[i].x;
01964           y = FRONT[i].y;
01965 
01966                   px = pere[x][y]->x;
01967           py = pere[x][y]->y;
01968 
01969                   if(V[(x+1)%dimx][y] >= MAXSHORTINT )  {
01970                 V[(x+1)%dimx][y] = V[x][y] + 1;
01971                 nbnext++;
01972                 NEXT[nbnext-1].x = (x+1)%dimx;
01973                 NEXT[nbnext-1].y = y;
01974             pere[(x+1)%dimx][y] = pere[x][y]; 
01975                   }
01976                   else if(ABS(pere[(x+1)%dimx][y]->x - px) + ABS(pere[(x+1)%dimx][y]->y - py)> 3) {
01977                         voro[(x+1)%dimx][y] = 1; 
01978                         nbskele++;
01979                   }
01980           if(V[(x+dimx1)%dimx][y] >= MAXSHORTINT )  {
01981                 V[(x+dimx1)%dimx][y] = V[x][y] + 1;
01982                 nbnext++;
01983                 NEXT[nbnext-1].x = (x+dimx1)%dimx;
01984                 NEXT[nbnext-1].y = y;
01985                 pere[(x+dimx1)%dimx][y] = pere[x][y];
01986                   } 
01987                   else if(ABS(pere[(x+dimx1)%dimx][y]->x - px) + ABS(pere[(x+dimx1)%dimx][y]->y - py)> 3) {
01988                         voro[(x+dimx1)%dimx][y] = 1; 
01989                         nbskele++;
01990                   }
01991                   if(V[x][(y+1)%dimy] >= MAXSHORTINT )  {
01992                 V[x][(y+1)%dimy] = V[x][y] + 1;
01993                 nbnext++;
01994                 NEXT[nbnext-1].x = x;
01995                 NEXT[nbnext-1].y = (y+1)%dimy;
01996                 pere[x][(y+1)%dimy] = pere[x][y];
01997                   } 
01998                   else if(ABS(pere[x][(y+1)%dimy]->x - px) + ABS(pere[x][(y+1)%dimy]->y - py)> 3) { 
01999                         voro[x][(y+1)%dimy] = 1;
02000                         nbskele++;
02001                   }
02002 
02003                   if(V[x][(y+dimy1)%dimy] >= MAXSHORTINT )  {
02004                 V[x][(y+dimy1)%dimy] = V[x][y] + 1;
02005                 nbnext++;
02006                 NEXT[nbnext-1].x = x;
02007                 NEXT[nbnext-1].y = (y+dimy1)%dimy;
02008                 pere[x][(y+dimy1)%dimy] = pere[x][y];
02009                   } 
02010                   else if(ABS(pere[x][(y+dimy1)%dimy]->x - px) + ABS(pere[x][(y+dimy1)%dimy]->y - py)> 3) {
02011                         voro[x][(y+dimy1)%dimy] = 1;
02012                         nbskele++;
02013                   }
02014                 }
02015 
02016                 TEMP = FRONT;
02017                 FRONT = NEXT;
02018                 NEXT = TEMP;
02019 
02020                 nbfront = nbnext;
02021         }
02022 
02023         free2D( ( void** )pere );
02024         free( Mpepere );
02025         free( MNEXT );
02026         free( MFRONT );
02027 
02028 } // distance2d() 
02029 
02030 
02031 
02032 //=========================================================================================
02033 //void PL_Sequential::voro_heuristic2d()
02034 //inputs:       - unsigned char **in
02035 //                      - int dimx
02036 //                      - int dimy
02037 //                      - IntPoint goal
02038 //                      - short int **V
02039 //                      - unsigned char **voro
02040 //                      - short int     **heurpot
02041 //                      - int *flag
02042 //function: constructs heuristic map corresponding to voronoi map
02043 //=========================================================================================
02044 void PL_Sequential::voro_heuristic2d(unsigned char              **in, 
02045                                                                          int                            dimx, 
02046                                                                          int                            dimy, 
02047                                                                          IntPoint                       goal, 
02048                                                                          short int                      **V, 
02049                                                                          unsigned char          **voro, 
02050                                                                          short int                      **heurpot, 
02051                                                                          int                            *flag)
02052 {
02053         int k, l, dimx1, dimy1;
02054         int x, y, i;
02055         int nbvoid, nbfront, nbsavofront, nbsavonext;
02056         IntPoint **FRONT, *PFRONT, *SAVOFRONT, *SAVONEXT, *TEMP;
02057         IntPoint **MFRONT, *MPFRONT, *MSAVOFRONT, *MSAVONEXT; 
02058         int xnew,ynew;
02059         short int value;
02060         short int Vmax;
02061         int narrow_flag = 0;
02062 
02063         dimx1 = dimx - 1;       // array indexing convension
02064         dimy1 = dimy - 1;
02065 
02066         //allocates memory for local arrays
02067         MFRONT = FRONT = (IntPoint **)calloc(50*(dimx+dimy),sizeof(IntPoint *));
02068         MPFRONT = PFRONT = (IntPoint *)calloc(50*(dimx+dimy),sizeof(IntPoint));
02069 
02070         MSAVOFRONT = SAVOFRONT = (IntPoint *)calloc(50*(dimx+dimy),sizeof(IntPoint));
02071         MSAVONEXT = SAVONEXT = (IntPoint *)calloc(50*(dimx+dimy),sizeof(IntPoint));
02072 
02073     // First mark by 'MAXSHORTINT' the obstacle cells in heupot[][]
02074         // and count the number of free cells 
02075         nbvoid = 0;
02076         for ( x=0 ; x < dimx ; ++x ) {
02077                 for ( y=0 ; y < dimy ; ++y ) {
02078                         if(in[x][y] == OBSTACLE) {
02079                                 heurpot[x][y] = MAXSHORTINT;
02080                         }
02081                 else {
02082                                 heurpot[x][y] = UNDONE;
02083                                 nbvoid++;
02084                         }
02085                 }
02086         }
02087 
02088         // assign goal in heuristic map to be 0
02089         heurpot[goal.x][goal.y] = 0;
02090         *flag = narrow_flag; 
02091 
02092     // proceed from the goal along increasing L1 distance from the 
02093     // obstacles until the voronoi diagram is met 
02094         x = goal.x;
02095         y = goal.y;
02096 
02097         if(voro[x][y] == 0) {
02098             narrow_flag = 1;
02099         }
02100 
02101         // try to connect the goal to the voronoi diagram.
02102         while(voro[x][y] == 0) {
02103                 Vmax = V[x][y];
02104 
02105                 xnew = x;
02106                 ynew = y;
02107  
02108                 for ( k = dimx-1 ; k <= dimx+1 ; ++k){
02109                     for ( l = dimy-1 ; l <= dimy+1 ; ++l){
02110                                 if ( Vmax < V[(x+k)%dimx][(y+l)%dimy] ) {
02111                                     Vmax = V[(x+k)%dimx][(y+l)%dimy];
02112                                     xnew = (x+k)%dimx;
02113                                     ynew = (y+l)%dimy;
02114                                 }
02115                     }
02116                 }
02117                 if ((xnew == x) && (ynew == y)) {
02118                     if(narrow_flag == 1) {
02119                         *flag = narrow_flag;  
02120                     }                           
02121                 }
02122                 voro[x][y] = 1;         // record path goal->voronoi 
02123                 x = xnew; y = ynew; 
02124         } //end of while
02125     
02126         FRONT[1] = PFRONT++;
02127         FRONT[1]->x = goal.x;
02128         FRONT[1]->y = goal.y;
02129         nbfront = 1;
02130 
02131         // Compute heurpot[][] along the voronoi diagram. Starting at the goal,
02132         // "expand" the visited voronoi cell with the largest L1 distance from the 
02133         // obstacles. This heuristic creates a (discontinuous) saddle at the narrowest
02134         // region in the workspace, thus eliminating the most likely local minimum
02135         // once the actual robot is guided "along" this potential. 
02136         // Remark: It seems that this heuristic can be greatly improved. It is possible
02137         // to store the voronoi cells in several disjoint heaps, one for each 
02138         // workspace obstacle, and then to "expand" cells obstacle by obstacle. 
02139         
02140         // If the goal is in a narrow region, then it won't be connected to the
02141         // voronoi diagram. Then, none of the voronoi cells will be assigned a
02142         // potential value. 
02143 
02144         x = goal.x;
02145         y = goal.y;
02146  
02147         nbsavofront = 0;
02148         while(nbfront > 0) {
02149                 SAVOFRONT[nbsavofront].x = FRONT[1]->x; // Save all the voronoi cells for the next paragraph 
02150                 SAVOFRONT[nbsavofront].y = FRONT[1]->y;
02151                 nbsavofront++;
02152             nbfront = deletemin(x, y, FRONT, nbfront, V); // (+,+) Get (x,y) with the largest L1 distance 
02153                 value = heurpot[x][y] + 1;
02154         // Add to the heap all unmarked neighbors on the voronoi diagram 
02155                 for (k = dimx-1 ; k <= dimx+1 ; ++k) {
02156                 for (l = dimy-1 ; l <= dimy+1 ; ++l) {                          
02157                 if ( voro[(x+k)%dimx][(y+l)%dimy] == 0 ) 
02158                                         continue;
02159                 if ( heurpot[(x+k)%dimx][(y+l)%dimy] == UNDONE ) {
02160                                         heurpot[(x+k)%dimx][(y+l)%dimy] = value;
02161                                 nbfront = insert((x+k)%dimx, (y+l)%dimy, FRONT, PFRONT, nbfront, V);
02162                                 }
02163                         }
02164                 }
02165         } // end of while 
02166 
02167         // follows the expansion from the voronoi diagram to the remaining free
02168         // workspace. We proceed by simultounasly advancing an L1-distance "wave" 
02169         // from the voronoi diagram. All the voronoi cells are stored in SAVOFRONT. 
02170 
02171         // In the case of the narrow region, the following while loop will still
02172         // try to expand the wave from goal and assign the potential values to 
02173         // the neighbors of the goal until the whole free space where the goal is
02174         // is explored. If the initial is in the same free space as the goal is,
02175         // a path exists. Otherwise, backtracking is needed.
02176         
02177         while (nbsavofront) {
02178                 nbsavonext = 0;
02179         // Assign cost to the 1-neighbors of all the nbsavofront 
02180         // cells stored in SAVOFRONT. 
02181                 for (i = 0 ; i < nbsavofront ; ++i) {
02182 
02183                         x = SAVOFRONT[i].x;
02184                         y = SAVOFRONT[i].y;
02185 
02186                         value = heurpot[x][y] + 1;
02187 
02188                         if(heurpot[(x+1)%dimx][y] == UNDONE){
02189                                 nbsavonext++;
02190                                 heurpot[(x+1)%dimx][y] = value;
02191                                 SAVONEXT[nbsavonext-1].x = (x+1)%dimx;
02192                                 SAVONEXT[nbsavonext-1].y = y;
02193                         }
02194 
02195                 if(heurpot[(x+dimx1)%dimx][y] == UNDONE){
02196                                 nbsavonext++;
02197                                 heurpot[(x+dimx1)%dimx][y] = value;
02198                                 SAVONEXT[nbsavonext-1].x = (x+dimx1)%dimx;
02199                                 SAVONEXT[nbsavonext-1].y = y;
02200                 }
02201 
02202                 if(heurpot[x][(y+1)%dimy] == UNDONE){
02203                                 nbsavonext++;
02204                                 heurpot[x][(y+1)%dimy] = value;
02205                                 SAVONEXT[nbsavonext-1].x = x;
02206                                 SAVONEXT[nbsavonext-1].y = (y+1)%dimy;
02207                 }
02208 
02209                 if(heurpot[x][(y+dimy1)%dimy] == UNDONE){
02210                                 nbsavonext++;
02211                                 heurpot[x][(y+dimy1)%dimy] = value;
02212                                 SAVONEXT[nbsavonext-1].x = x;
02213                                 SAVONEXT[nbsavonext-1].y = (y+dimy1)%dimy;
02214                 }
02215                 } // "expanded" all the cells in SAVOFRONT 
02216 
02217                 TEMP = SAVOFRONT;
02218                 SAVOFRONT = SAVONEXT;
02219                 SAVONEXT = TEMP;
02220 
02221                 nbsavofront = nbsavonext;
02222         } // visited all the free workspace cells 
02223 
02224         // Free all memory allocated 
02225         free(MFRONT);
02226         free(MPFRONT);
02227         free(MSAVOFRONT);
02228         free(MSAVONEXT); 
02229 
02230 } // voro_heuristic() 
02231 
02232 
02233 
02234 //=========================================================================================
02235 //PL_Sequential::find_path_by_heuristic()
02236 //inputs:       - LinkPath *result
02237 //                      - short int **heurpot
02238 //                      - int dimx
02239 //                      - int dimy
02240 //                      - IntPoint *start
02241 //                      - IntPoint *goal
02242 //function: find main path for link n along heuristic map
02243 //=========================================================================================
02244 void PL_Sequential::find_path_by_heuristic(     LinkPath                *result, 
02245                                                                 short int       **heurpot, 
02246                                                                 int                     dimx, 
02247                                                                 int                     dimy, 
02248                                                                 IntPoint                *start, 
02249                                                                 IntPoint                *goal)
02250 {
02251         int     value, x, y, xnew, ynew, i, found;
02252 
02253         // Start from the initial position      
02254         x = start->x;
02255         y = start->y;
02256         value = heurpot[x][y];
02257         result->d[0].t = start->x;
02258         result->d[0].q = start->y;
02259         i = 1;
02260 
02261         // Search for the path by following the gradient of heurpot
02262         while ((heurpot[x][y] > 1) && (i < result->maxdim)) {
02263                 for ( xnew = x+dimx-1 ; xnew <= x+dimx+1 ; xnew++ ) {
02264                         found = FALSE;
02265                         for ( ynew = y + dimy - 1 ; ynew <= y + dimy + 1; ynew++ )
02266                         {
02267                                 if (heurpot[xnew % dimx][ynew % dimy] < value) {
02268                                         //if a neighbor's heuristics lower, find a new point    
02269                                         result->d[i].t = x = xnew % dimx;
02270                                         result->d[i].q = y = ynew % dimy;
02271                                         i++;
02272                                         found = TRUE;
02273                                         // prepare for next following   
02274                                         value = heurpot[xnew % dimx][ynew % dimy];
02275                                         break;
02276                                 }
02277                         }       
02278                         if (found) break;
02279                 }
02280         }
02281 
02282         // Check maximum dimension overflow in result path      
02283         if (i >= result->maxdim)
02284                 printf("**** Warning, Path is not correct, overflow ! ****\n");
02285 
02286         // Add the final position on the path   
02287         if (heurpot[x][y] > 0) {
02288                 result->d[i].t = goal->x;
02289                 result->d[i].q = goal->y;
02290                 i++;
02291         }
02292 
02293         // record dimension of mainpath
02294         result->dim = i;  
02295 
02296 } // find_path_by_heuristic()   
02297 
02298 
02299 
02300 //=========================================================================================
02301 //void PL_Sequential::retrieve_global_path()
02302 //inputs:       - double **globalpath
02303 //                      - int pathlen
02304 //                      - double *startdof
02305 //                      - double *goaldof
02306 //function: converts link paths from t-q array into absolute angles in radian
02307 //=========================================================================================
02308 void PL_Sequential::retrieve_global_path(double **globalpath, int pathlen,
02309                                                                                  double *startdof, double *goaldof)
02310 {
02311         int     i, j, lnkno1;
02312         TQConfig        para[MAX_DEGREE];
02313         
02314         lnkno1 = arm_degree - 1;                // array indexing convension
02315         
02316         // First config is start node 
02317         for (j = 0; j < arm_degree; j++)
02318             globalpath[0][j] = startdof[j];
02319 
02320         // For every column of TxQ map  
02321         for (i = 0; i < pathlen-2; i++) {
02322                 // retrieve q for link (n - 1)  
02323                 para[lnkno1].q = lnkcps[lnkno1].d[i].q;
02324                 para[lnkno1].t = lnkcps[lnkno1].d[i].t;
02325 
02326                 // retrieve q for link (n - 2)...1      
02327                 for (j = lnkno1-1; j >= 0; j--) {
02328                         para[j].t = lnkcps[j].d[ para[j+1].t].t; 
02329                         para[j].q = lnkcps[j].d[ para[j+1].t].q;
02330                 }
02331 
02332                 // convert index to angle and store into global path    
02333                 for (j = 0; j < arm_degree; j++) {
02334                         globalpath[i+1][j] = index_to_rad(para[j].q); 
02335                 }
02336         }
02337 
02338         // append goal to last point of globalpath 
02339         for (j = 0; j < arm_degree; j++) 
02340         {       
02341                 globalpath[pathlen-1][j] = goaldof[j];
02342         }
02343             
02344 } //retrieve_global_path()
02345 
02346 
02347 
02348 //=========================================================================================
02349 //void PL_Sequential::reparameterize_path()
02350 //inputs:       - int bound
02351 //                      - LinkPath *whole_path
02352 //                      - LinkPath *result
02353 //                      - int *ipos
02354 //                      - int *fpos
02355 //                      - int L1
02356 //function: reparameterize path of link n in terms of t of link (n+1)
02357 //=========================================================================================
02358 void PL_Sequential::reparameterize_path(int             bound,
02359                                                                         LinkPath        *whole_path, 
02360                                                                         LinkPath        *result, 
02361                                                                         int             *ipos, 
02362                                                                         int             *fpos, 
02363                                                                         int             L1)
02364 {
02365         double  lold, lnew;
02366         int     i, j;
02367 
02368         if (bound)
02369                 lnew = dimt[L1]-3;
02370         else
02371                 lnew = dimt[L1]-1;
02372         lold = whole_path->dim-1;
02373 
02374         if (bound) {
02375                 (*ipos)++;      // shift 1 for the initial and final position
02376                 (*fpos)++;
02377                 result->d[0].t = whole_path->d[0].t;
02378                 result->d[0].q = whole_path->d[0].q;
02379                 result->d[dimt[L1]-1].t = whole_path->d[whole_path->dim-1].t;
02380                 result->d[dimt[L1]-1].q = whole_path->d[whole_path->dim-1].q;
02381                 for (i=1; i<dimt[L1]-1; i++) {
02382                         if (NO_PATH_COMPRESS) j = i-1;
02383                         else j = ROUND( lold*(i-1)/lnew);
02384                         result->d[i].t = whole_path->d[j].t;
02385                         result->d[i].q = whole_path->d[j].q;
02386                 }
02387         }
02388         else
02389                 for (i =0; i<dimt[L1]; i++) {
02390                         if (NO_PATH_COMPRESS) j = i;
02391                         else j = ROUND(lold * (i-1) / lnew);
02392                         result->d[i].t = whole_path->d[j].t;
02393                         result->d[i].q = whole_path->d[j].q;
02394                 }
02395 
02396         result->dim = dimt[L1];
02397 
02398 } //reparameterize_path()       
02399 
02400 
02401 
02402 //=========================================================================================
02403 //void PL_Sequential::allocate_space_for_Link_tq_path()
02404 //input:        - int link1
02405 //                      - int length
02406 //function: initializes constants for link path; allocates memory for link path array
02407 //=========================================================================================
02408 void PL_Sequential::allocate_space_for_Link_tq_path(int link1, int length)
02409 
02410 {
02411         lnkcps[link1].maxdim = length;
02412         lnkcps[link1].dim = length;
02413         lnkcps[link1].d = (TQConfig *) malloc (length * sizeof(TQConfig));
02414         assert( lnkcps[link1].d != NULL );
02415 } //allocate_space_for_Link_tq_path()
02416 
02417 
02418 //=========================================================================================
02419 //void PL_Sequential::free_space_for_link_cs()
02420 //input: int L
02421 //function: free space allocated for link n's obstacle map, distance map, voronoi map, and
02422 //                  potential map
02423 //=========================================================================================
02424 void PL_Sequential::free_space_for_link_cs(int L)
02425 
02426 {
02427         // Obstacle map 
02428         if (tqcs.tqlink[L].bitmap)
02429                 free2D((void **)tqcs.tqlink[L].bitmap);
02430 
02431         // Distance map 
02432         if (tqcs.tqlink[L].distmap)
02433                 free2D((void **)tqcs.tqlink[L].distmap );
02434 
02435         // Voronoi map  
02436         if (tqcs.tqlink[L].voro)
02437                 free2D((void **)tqcs.tqlink[L].voro );
02438 
02439         // Potential map        
02440         if (tqcs.tqlink[L].potential)
02441                 free2D((void **)tqcs.tqlink[L].potential );
02442 } //free_space_for_link_cs()
02443 
02444 
02445 
02446 //=========================================================================================
02447 //void PL_Sequential::allocate_space_for_link_cs()
02448 //input: int L
02449 //function: allocate space for link n's obstacle map, distance map, voronoi map, and
02450 //                  potential map
02451 //=========================================================================================
02452 void PL_Sequential::allocate_space_for_link_cs(int L)
02453 {
02454 
02455         tqcs.tqlink[L].dimt = dimt[L];
02456         tqcs.tqlink[L].dimq = dimq[L];
02457 
02458         // Obstacle map 
02459         tqcs.tqlink[L].bitmap = (unsigned char **)
02460                         malloc2D(dimt[L], dimq[L], sizeof(unsigned char));
02461         assert( tqcs.tqlink[L].bitmap != NULL );
02462 
02463         tqcs.tqlink[L].distmap = (short int **)
02464                 malloc2D(dimt[L], dimq[L], sizeof(short int));
02465         assert( tqcs.tqlink[L].distmap != NULL );
02466 
02467         // Voronoi map  
02468         tqcs.tqlink[L].voro = (unsigned char **)
02469                 malloc2D(dimt[L], dimq[L], sizeof(unsigned char));
02470         assert( tqcs.tqlink[L].voro != NULL );
02471         
02472         // Potential map        
02473         tqcs.tqlink[L].potential = (short int **)
02474                 malloc2D(dimt[L], dimq[L], sizeof(short int));
02475         assert( tqcs.tqlink[L].potential != NULL );
02476         
02477 } //allocate_space_for_link_cs()
02478 
02479 
02480 
02481 //=========================================================================================
02482 //void PL_Sequential::allocate_space_for_working_tq_path()
02483 //input: none
02484 //function: allocates space for links' backward extention, main, forward extention, and
02485 //                  combined paths
02486 //=========================================================================================
02487 void PL_Sequential::allocate_space_for_working_tq_path()
02488 {
02489         // allocate space for working pathes in each link planning stage    
02490         bkwdpath.maxdim = MAX_PART_PATH;
02491         bkwdpath.d = (TQConfig *)malloc(bkwdpath.maxdim*sizeof(TQConfig));
02492         assert( bkwdpath.d != NULL );
02493 
02494         frwdpath.maxdim = MAX_PART_PATH;
02495         frwdpath.d = (TQConfig *)malloc(frwdpath.maxdim*sizeof(TQConfig));
02496         assert( frwdpath.d != NULL );
02497 
02498         mainpath.maxdim = MAX_PART_PATH;
02499         mainpath.d = (TQConfig *)malloc(mainpath.maxdim*sizeof(TQConfig));
02500         assert( mainpath.d != NULL );
02501 
02502         combpath.maxdim = MAX_CS_PATH_LEN;
02503         combpath.d = (TQConfig *)malloc(combpath.maxdim*sizeof(TQConfig));
02504         assert( combpath.d != NULL );
02505 } //allocate_space_for_working_tq_path()
02506 
02507 
02508 
02509 //=========================================================================================
02510 //char** PL_Sequential::malloc2D ()
02511 //inputs:       - int dy
02512 //                      - int dz
02513 //                      - int oc
02514 //function: allocates 2D arrays
02515 //=========================================================================================
02516 char** PL_Sequential::malloc2D (int dy,int dz,int oc)
02517 {
02518 
02519         char *bv;
02520         char **v;
02521         char *p_bv;
02522         char **p_v;
02523 
02524         bv = ( char* )malloc( dz * dy * sizeof( char ) * oc );
02525         assert( bv != NULL );
02526         v = ( char** )malloc( dy * sizeof( char* ) );
02527         assert ( v != NULL );
02528         
02529         p_bv = bv;
02530         p_v = v;
02531 
02532         for( p_bv = bv; p_bv - bv < dz * dy * oc; p_bv += dz * oc )
02533         {
02534                 *p_v++ = p_bv;
02535         }
02536 
02537         return(v);
02538 } // malloc2D() 
02539 
02540 
02541 
02542 //=========================================================================================
02543 //void PL_Sequential::write_map()
02544 //inputs:       - char *flnm
02545 //                      - FileType filetype
02546 //                      - char **map
02547 //                      - int dimx
02548 //                      - int dimy
02549 //                      - int bitsize
02550 //function: writes 2D array (map) to file (never used)
02551 //=========================================================================================
02552 void PL_Sequential::write_map(char *flnm, FileType filetype,
02553                 char **map, int dimx, int dimy, int bitsize)
02554 {
02555 
02556         FileDescript    fdt;
02557         int     i;
02558         FILE *fout;
02559 
02560         fout = fopen(flnm, "w");
02561         assert( fout != NULL );
02562 
02563         fdt.ftype = filetype;
02564         i=0;
02565         while ( (fdt.comment[i]=flnm[i]) != '\0' ) i++;
02566 
02567         fdt.octet = bitsize;
02568         fdt.dimx = dimx;
02569         fdt.dimy = dimy;
02570         fdt.dimz = 0;
02571 
02572         fwrite(&fdt, sizeof(FileDescript), 1, fout);
02573         fwrite(&(map[0][0]), bitsize, dimx*dimy, fout);
02574 
02575         fclose(fout);
02576 
02577 } //write_map()
02578 
02579 
02580 
02581 //=========================================================================================
02582 //void PL_Sequential::write_global_path()
02583 //inputs:       - char *flnm
02584 //                      - int length
02585 //                      - int degree
02586 //                      - double **gpath
02587 //functions: outputs globalpath to file (never used)
02588 //=========================================================================================
02589 void PL_Sequential::write_global_path(char *flnm, int length, int degree, double **gpath)
02590 {
02591         int     i, j;
02592         FILE    *fout;
02593 
02594     fout=fopen(flnm, "w");
02595         assert( fout != NULL );
02596 
02597     fprintf(fout, "%d\n",degree);
02598     fprintf(fout, "%d\n",length);
02599 
02600     for (i = 0; i < length; i++) {
02601         fprintf(fout, "  Step %3d:\t", i); 
02602         for (j = 0; j < degree; j++) {
02603             fprintf(fout, "%8.3f  ",gpath[i][j]);
02604         }
02605         fprintf(fout,"\n");
02606     }
02607     fprintf(fout,"\n");
02608     fclose(fout);
02609 } // write_global_path()
02610 
02611 
02612         
02613 //=========================================================================================
02614 //int PL_Sequential::smoothpath()
02615 //inputs:       - int nb_degree
02616 //                      - int intervals
02617 //                      - double **dofpath
02618 //                      - int *pathlen
02619 //functions: optimizes and shortens globalpath (never used)
02620 //note: MUST modify line_free() before use!
02621 //=========================================================================================
02622 int PL_Sequential::smoothpath(int nb_degree, int intervals, double **dofpath, int *pathlen)
02623 {
02624         int path_len, prev_path_len; 
02625         int pt, radius, delta;
02626         int intervals2;
02627         int pt1, pt2 ;
02628         double factor;
02629 
02630         double  **gpath;         //Storage for the generated straght line 
02631 
02632     gpath = (double **) malloc2D(*pathlen, arm_degree,
02633                                 sizeof(double) );
02634         assert( gpath != NULL );
02635 
02636     factor = 1.0;
02637     path_len = *pathlen;
02638     prev_path_len=path_len;
02639     
02640         // Attempt subdivisions until delta is 2, in which case we are back
02641     // at the unsmoothed path.
02642  
02643     do {    // while (delta > 2)    
02644 
02645         delta = intervals / 3;
02646         pt = delta;
02647 
02648         // Do every segment on the path   
02649         do {    // while (pt < path_len)    
02650             
02651                         // radius is the segment len of subdivision,
02652             radius=(int)((factor*path_len)/2);
02653             pt1=MAX(0,pt-radius);
02654             pt2=MIN(path_len-1,pt+radius);
02655         
02656                     intervals2 = pt2-pt1;
02657 
02658             // If a straight line segment [pt1,pt2] is collision
02659             // free, replace the portion of the unsmoothed path
02660             // from pt1 to pt2 by this line segment.
02661 
02662                         //WARNING: must modify line_free() before use
02663             if (line_free(dofpath, intervals2, pt1, pt2, gpath, &path_len))
02664                         {
02665                 path_len = shift_dofpath(dofpath,path_len, gpath, intervals2,
02666                                                         pt1,pt2);
02667             }
02668 
02669             pt += delta;
02670         } while (pt < path_len);
02671 
02672         factor /= 2;
02673         intervals /= 2;
02674 
02675     } while (delta > 2);
02676 
02677     if ((sp_debug_level > 0) && ( prev_path_len != path_len))
02678         printf("Global Path shorten from %d to %d\n",
02679                 prev_path_len, path_len);
02680 
02681     free(gpath);
02682         
02683     *pathlen = path_len;
02684 
02685     return(path_len);
02686 
02687 } //smoothpath()
02688 
02689 
02690 
02691 //=========================================================================================
02692 //void PL_Sequential::write_linkpath()
02693 //inputs:       - char *flnm
02694 //                      - FileType filetype
02695 //                      - char *map
02696 //                      - int dim
02697 //                      - int bitsize
02698 //function: outputs link path to file (never used)
02699 //=========================================================================================
02700 void PL_Sequential::write_linkpath(char *flnm, FileType filetype,
02701                     char *map, int dim, int bitsize)
02702 
02703 {
02704 FileDescript    fdt;
02705 int     i;
02706 FILE    *fout;
02707 
02708     fout = fopen(flnm, "w");
02709     if ( fout==0) {
02710         printf("Inside write_linkpath()\n");
02711         printf("File Open Failed for file %s.\n", flnm);
02712                 assert(false);
02713     }
02714  
02715     fdt.ftype = filetype;
02716     i=0;
02717     while ( (fdt.comment[i]=flnm[i]) != '\0' ) i++;
02718     fdt.octet = bitsize;
02719     fdt.dimx = dim;
02720     fdt.dimy = 1;
02721     fdt.dimz = 0;
02722 
02723     fwrite(&fdt, sizeof(FileDescript), 1, fout);
02724     fwrite(&(map[0]), bitsize, dim, fout);
02725 
02726     fclose(fout);
02727 } // write_linkpath()    
02728 
02729 
02730 
02731 //=========================================================================================
02732 //void PL_Sequential::write_linkpathtxt()
02733 //inputs:       - char *flnm
02734 //                      - TQConfig *map
02735 //                      - int dim
02736 //function: write text output about link path to file (never used)
02737 //=========================================================================================
02738 void PL_Sequential::write_linkpathtxt(char *flnm, TQConfig *map, int dim)
02739 {
02740     int i;
02741     FILE    *fout;
02742 
02743 
02744     fout = fopen(flnm, "w");
02745     if ( fout==0 ) {
02746         printf("Inside write_linkpathtxt()\n");
02747         printf("File Open Failed for file %s.\n", flnm);
02748                 assert(false);
02749     }
02750 
02751     fprintf(fout,"\n\t*** Link %s TxQ Config Path ***\n\n", flnm);
02752     fprintf(fout,"Index\tT\tQ\t\n");
02753 
02754     for (i=0; i <dim; i++) 
02755         fprintf(fout,"%d\t%d\t%d\t\n",i,map[i].t, map[i].q);
02756 
02757     fclose(fout);
02758 
02759 } //write_linkpathtxt()
02760 
02761 
02762 
02763 //=========================================================================================
02764 //void PL_Sequential::write_tqif()
02765 //inputs:       - char *flnm
02766 //                      - TQConfig tqi
02767 //                      - TQConfig tqf
02768 //function:     outputs starts and goals of links (never used)
02769 //=========================================================================================
02770 void PL_Sequential::write_tqif(char *flnm, TQConfig tqi, TQConfig tqf)
02771 {
02772         FILE *fout;
02773 
02774     fout = fopen(flnm, "w");
02775     if ( fout==0 ) {
02776         printf("Inside write_tqif()\n");
02777         printf("File Open Failed for file %s.\n", flnm);
02778                 assert(false);
02779     }
02780 
02781     fwrite(&tqi, sizeof(TQConfig), 1, fout);
02782     fwrite(&tqf, sizeof(TQConfig), 1, fout);
02783     fclose(fout);
02784 
02785 }  //write_tqif()
02786 
02787 
02788 
02789 
02790 //=========================================================================================
02791 //int PL_Sequential::line_free()
02792 //inputs:       - double **dofpath
02793 //                      - int intervals
02794 //                      - int start
02795 //                      - int end
02796 //                      - double **tmppath
02797 //                      - int *path_len
02798 //function: ???
02799 //note: used ONLY if we wish to optimize path
02800 //=========================================================================================
02801 int PL_Sequential::line_free(double **dofpath, int intervals, int start, int end,
02802                 double  **tmppath, int *path_len)
02803 {
02804         return(true); //dummy return
02805 } // line_free() 
02806 
02807 
02808 
02809 //=========================================================================================
02810 //int PL_Sequential::shift_dofpath()
02811 //inputs:       - double **dofpath
02812 //                      - int pathlen
02813 //                      - double **gpath
02814 //                      - int npathlen
02815 //                      - int pt1
02816 //                      - int pt2
02817 //function: ???
02818 //note: used ONLY if we wish to optimize path
02819 //=========================================================================================
02820 int     PL_Sequential::shift_dofpath(double             **dofpath, 
02821                                   int                   pathlen, 
02822                                   double                **gpath, 
02823                                   int                   npathlen, 
02824                                   int                   pt1, 
02825                                   int                   pt2)
02826 {
02827         int     i, iold, j, pathdiff;
02828         double diff, min_motion;
02829 
02830         // A minimum motion is required when testing if the neighbor
02831         // points on the new path are distinct
02832          
02833         min_motion = 0.9*(2*PI)/dimq[0];
02834 
02835         // Copy the straight line over the path         
02836         iold = 1; 
02837         pathdiff = 0;
02838         for (i = 1; i < npathlen; i++) {        // Skip first one       
02839                 diff = qdist(dofpath[pt1+iold-1], gpath[i]);
02840                 // if the new point not the same as last one, copy it
02841                 // otherwise, skip it
02842                  
02843                 if (diff > min_motion) {
02844                         for (j=0; j<arm_degree; j++) {
02845                                 dofpath[iold+pt1][j] = gpath[i][j];
02846                         }
02847                         iold++;
02848                 }
02849                 else {
02850                         pathdiff++;
02851                 }
02852         }
02853 
02854         // Shift old path       
02855         pathdiff = pt2-pt1 - iold;
02856 
02857         if (pathdiff > 0) {
02858                 for (i=pt2; i< pathlen; i++ ) { // Skip first one       
02859                         for (j=0; j<arm_degree; j++)
02860                                 dofpath[i-pathdiff][j] = dofpath[i][j];
02861                 }
02862                 pathlen = pathlen- pathdiff;
02863         }
02864 
02865         return(pathlen);
02866 } // shift_dofpath() 
02867 
02868 
02869 
02870 //=========================================================================================
02871 //void PL_Sequential::free2D()
02872 //input: void **pp
02873 //function: free 2D arrays
02874 //=========================================================================================
02875 void PL_Sequential::free2D(void **pp)
02876 {
02877         if( pp == NULL )
02878         {
02879                 return;         //tried to free nothing
02880         }
02881         if( pp[ 0 ] != NULL ) 
02882         {
02883                 free(pp[0]);
02884                 pp[0] = NULL;
02885         }
02886         free(pp);
02887         pp = NULL;
02888 } //free2D
02889 
02890 
02891 
02892 //=========================================================================================
02893 //double PL_Sequential::qdist()
02894 //input:        - double *q1
02895 //                      - double *q2
02896 //function: determines distance between two q's
02897 //note: used ONLY with smooth_path()
02898 //=========================================================================================
02899 double PL_Sequential::qdist(double      *q1, double     *q2)
02900 {
02901 int     i;
02902 double  dist;
02903 
02904         dist = 0.0;
02905         for (i=0; i<arm_degree; i++)
02906                 dist = dist + ABS(q1[i]-q2[i]);
02907 
02908         return(dist);
02909 
02910 } //qdist()
02911 
02912   //## end PL_Sequential%3752D78501D0.declarations
02913 //## begin module%3752D78501D0.epilog preserve=yes
02914 //## end module%3752D78501D0.epilog

Generated on Sat Apr 1 21:30:47 2006 for Motion Planning Kernel by  doxygen 1.4.6-NO