From c5f47bcce189b4e34229a7adeef0b9d1a1029272 Mon Sep 17 00:00:00 2001 From: BlackCoder <blackcoder@laptop.blackcoder.dyndns.org> Date: Tue, 15 Jun 2010 09:57:24 +1000 Subject: [PATCH] - attempt to replace ICP with CSM, CSM is still giving weird output, very different from ICP. --- sm/csm/laser_data.c | 4 +- sm/csmpp/csmpp.cpp | 16 +- sm/csmpp/csmpp.h | 2 +- sm/drivers/playerstage/mricp/CMakeLists.txt | 2 + .../playerstage/mricp/src/mricp_driver.cpp | 837 +++++++++--------- .../mricp/stage_test/stage_mricp.cfg | 4 +- 6 files changed, 439 insertions(+), 426 deletions(-) diff --git a/sm/csm/laser_data.c b/sm/csm/laser_data.c index 7f47fb7..ec909ff 100644 --- a/sm/csm/laser_data.c +++ b/sm/csm/laser_data.c @@ -206,8 +206,8 @@ int ld_valid_fields(LDP ld) { return 0; } if(fabs(ld->max_theta - ld->theta[ld->nrays-1]) > 1e-8) { - sm_error("Min_theta (%f) should be theta[0] (%f)\n", - ld->max_theta, ld->theta[ld->nrays-1]); + sm_error("Max_theta (%f) should be theta[%d] (%f)\n", + ld->max_theta,ld->nrays-1, ld->theta[ld->nrays-1]); return 0; } /* Check that there are valid rays */ diff --git a/sm/csmpp/csmpp.cpp b/sm/csmpp/csmpp.cpp index 019a623..8693172 100644 --- a/sm/csmpp/csmpp.cpp +++ b/sm/csmpp/csmpp.cpp @@ -20,11 +20,17 @@ CanonicalScanMatcher::~CanonicalScanMatcher() { } -bool CanonicalScanMatcher::scanMatch(LDP refScan, LDP secondScan) +sm_result CanonicalScanMatcher::scanMatch(LDP refScan, LDP laserScan) { params.setLaserRef(refScan); - params.setLaserSen(secondScan); + params.setLaserSen(laserScan); + double odometry[3]; + double ominus_laser[3], temp[3]; + pose_diff_d(laserScan->odometry, refScan->odometry, odometry); + ominus_d(params.getParams()->laser, ominus_laser); + oplus_d(ominus_laser, odometry, temp); + oplus_d(temp, params.getParams()->laser, params.getParams()->first_guess); switch(matchingAlgorithm) { @@ -39,10 +45,10 @@ bool CanonicalScanMatcher::scanMatch(LDP refScan, LDP secondScan) break; default: sm_error("Unknown algorithm to run: %d.\n",matchingAlgorithm); - return false; + return matchingResult; } - - return true; + oplus_d(refScan->estimate, matchingResult.x, laserScan->estimate); + return matchingResult; } void CanonicalScanMatcher::setShowDebug(bool state) diff --git a/sm/csmpp/csmpp.h b/sm/csmpp/csmpp.h index 0c2b1ce..5509b97 100644 --- a/sm/csmpp/csmpp.h +++ b/sm/csmpp/csmpp.h @@ -282,7 +282,7 @@ public: void setSMParameters(SMParameters parameters); void setShowDebug(bool); void setRecoverFromError(bool); - bool scanMatch(LDP refScan, LDP secondScan); + sm_result scanMatch(LDP refScan, LDP laserScan); private: int matchingAlgorithm; bool showDebug; diff --git a/sm/drivers/playerstage/mricp/CMakeLists.txt b/sm/drivers/playerstage/mricp/CMakeLists.txt index a5e745a..b846355 100644 --- a/sm/drivers/playerstage/mricp/CMakeLists.txt +++ b/sm/drivers/playerstage/mricp/CMakeLists.txt @@ -49,6 +49,8 @@ TARGET_LINK_LIBRARIES(mricp ${GTK_LIBRARIES} ${GDKPIXBUF_LIBRARIES} ${CSM_LIBRARY_DIRS} + /home/blackcoder/workspace/csm-git/sm/csmpp/libcsmpp.so + /home/blackcoder/workspace/csm-git/sm/libcsm.so ) INCLUDE_DIRECTORIES( diff --git a/sm/drivers/playerstage/mricp/src/mricp_driver.cpp b/sm/drivers/playerstage/mricp/src/mricp_driver.cpp index b7fbc10..53e2b36 100644 --- a/sm/drivers/playerstage/mricp/src/mricp_driver.cpp +++ b/sm/drivers/playerstage/mricp/src/mricp_driver.cpp @@ -245,7 +245,6 @@ typedef struct laser_range } laser_ranges_t; bool is_file(string fname) { - //cout<<fname<<endl; struct stat stat_buf; if (stat(fname.c_str(),&stat_buf) != 0) return false; return (stat_buf.st_mode & S_IFMT) == S_IFREG; @@ -256,92 +255,15 @@ bool is_directory(string fname) if (stat(fname.c_str(),&stat_buf) != 0) return false; return (stat_buf.st_mode & S_IFMT) == S_IFDIR; } -/* -LDP PlayerLaserSet2LDP(vector<Point> laserSet) -{ - int nrays=laserSet.size(); - LDP ld = ld_alloc_new(nrays); - double fov = M_PI; - double min_reading = 0; - double max_reading = 80; - - if(nrays == 769) - { - min_reading = 0.001; - max_reading = 4; - fov = deg2rad(270.0); - } - ld->min_theta = -fov/2; - ld->max_theta = +fov/2; - - for(int i=0;i<nrays;i++) - { - double reading; - ld->valid[i] = (reading > min_reading) && (reading < max_reading); - ld->readings[i] = ld->valid[i] ? reading : NAN; - ld->theta[i] = ld->min_theta + i *(ld->max_theta-ld->min_theta) / (ld->nrays-1); - // bad hokuyo!! - if(nrays == 769) - { - if(i>725 || i<44) - { - ld->valid[i] = 0; - ld->readings[i] = NAN; - } - } - } - - ld->estimate[0] = ; - ld->estimate[1] = ; - ld->estimate[2] = ; - ld->odometry[0] = ; - ld->odometry[1] = ; - ld->odometry[2] = ; - - static int warn_format = 1; - - int inc; int sec=-1, usec=-1; - int res = sscanf(line + cur, "%d %s %d%n", &sec, ld->hostname, &usec, &inc); - if(3 == res) - { - ld->tv.tv_sec = sec; - ld->tv.tv_usec = usec; - if(warn_format) - sm_info("Reading timestamp as 'sec hostname usec'.\n"); - } - else - { - double v1=-1, v2=-1; - res = sscanf(line + cur, "%lf %s %lf%n", &v1, ld->hostname, &v2, &inc); - if(3 == res) - { - ld->tv.tv_sec = (int) floor(v1); - ld->tv.tv_usec = floor( (v1 - floor(v1)) * 1e6 ); - - if(warn_format) - sm_info("Reading timestamp as doubles (discarding second one).\n"); - - } - else - { - ld->tv.tv_sec = 0; - ld->tv.tv_usec = 0; - if(warn_format) - sm_info("I could not read timestamp+hostname; ignoring (I will warn only once for this).\n"); - } - } - return ld; -} -*/ -class MrIcp : public ThreadedDriver +class MRSM : public ThreadedDriver { // Must implement the following methods. public : virtual int MainSetup(); virtual void MainQuit(); virtual int ProcessMessage(QueuePointer& resp_queue, player_msghdr * hdr, void * data); - MrIcp(ConfigFile* cf, int section); + MRSM(ConfigFile* cf, int section); // Main function for device thread. private: virtual void Main(); @@ -355,12 +277,13 @@ private: Pose TransformToGlobal(Pose ,Pose p); Point ConvertToPixel(Point p); Point ConvertPixel(Point p); - int InRange(double angle,int laser_index); + bool inRange(double angle,int laser_index); void BuildMap(); - int SetupLaser(int); + int SetupLaser(int); void SetupPositionDriver(); void GenerateLocalMap(Pose pse); void ConnectPatches(); + LDP laserPointSet2LDP(vector<Point>); mapgrid_t ComputeRangeProb(double range,bool); int ProcessMapInfoReq(QueuePointer& resp_queue,player_msghdr * hdr,void * data); int ProcessMapDataReq(QueuePointer& resp_queue,player_msghdr * hdr,void * data); @@ -408,18 +331,18 @@ public : MAP *map; MricpTimer delta_t_estimation; CanonicalScanMatcher csm; - LDP refLaserScan; - LDP laserScan; + SMParameters csmParam; + LDP refLaserScan,laserScan,currentLaserScan; }; -Driver* MrIcp_Init(ConfigFile* cf, int section) // Create and return a new instance of this driver +Driver* MRSM_Init(ConfigFile* cf, int section) // Create and return a new instance of this driver { - return ((Driver*) (new MrIcp(cf, section))); + return ((Driver*) (new MRSM(cf, section))); } -void mricp_Register(DriverTable* table) +void MRSM_Register(DriverTable* table) { - table->AddDriver("mricp", MrIcp_Init); + table->AddDriver("MRSM", MRSM_Init); } /* need for this driver to be a plugin */ @@ -427,13 +350,13 @@ extern "C" { int player_driver_init(DriverTable* table) { - puts(" --->>>Initializing Pluggin Driver ==> MRICP Driver ..."); - mricp_Register(table); + puts(" --->>>Initializing Pluggin Driver ==> MRICP Driver 2 ..."); + MRSM_Register(table); return(0); } } -MrIcp::MrIcp(ConfigFile* cf, int section) : ThreadedDriver(cf, section) +MRSM::MRSM(ConfigFile* cf, int section) : ThreadedDriver(cf, section) { char config_temp[40]; this->maxr = cf->ReadFloat(section,"MAXR",7.8); @@ -560,174 +483,174 @@ MrIcp::MrIcp(ConfigFile* cf, int section) : ThreadedDriver(cf, section) return; } -int MrIcp::MainSetup() +int MRSM::MainSetup() { - char filename[40],command[40]; - printf("\n- Setting UP MRICP Plugin Driver."); - if(!is_directory(map_path)) - { - snprintf(command,40,"%s%s","mkdir ",map_path); - if(system(command)==-1) - { - perror("\n Serious Error Happened while trying to create the folder"); - exit(1); - } - else - cout<<"\nFolder Created Successfully"; - } - // allocate space for map cells - //assert(this->map_data = (char*)malloc(sizeof(char)*this->map_size*this->map_size)); - for(int i=0;i<number_of_lasers;i++) - gettimeofday(&last_time[i],NULL); - this->global_pose.p.x = this->global_pose.p.y = this->global_pose.phi = 0; - // what extra area(margine) in the stored map around the local map should be included in the ICP - this->local_map_margine = 0.5; - this->px=0; - this->py=0; - this->pa=0; - nu = 0; map_number = 1; - gchar * g_filename=g_strdup_printf("%sMAP_PATCH0",map_path); - this->map = new MAP(g_filename,this->map_resolution,this->map_size*2); - this->map->CreateMap(); - this->map->ResetProb(); - snprintf(filename,40,"%spatch_config.txt",map_path); - config_file = fopen(filename,"wb"); - // Initial Patch Settings - fprintf(config_file,"%s %.3f %.3f %.3f\n","MAP_PATCH0",0.0,0.0,0.0); - delta_pose.p.x=0; - delta_pose.p.y=0; - delta_pose.phi=0; - reset_timer= true; - sample_initialized = FALSE; - if(log) - { + char filename[40],command[40]; + printf("\n- Setting UP MRICP2 Plugin Driver."); + if(!is_directory(map_path)) + { + snprintf(command,40,"%s%s","mkdir ",map_path); + if(system(command)==-1) + { + perror("\n Serious Error Happened while trying to create the folder"); + exit(1); + } + else + cout<<"\nFolder Created Successfully"; + } + // allocate space for map cells + //assert(this->map_data = (char*)malloc(sizeof(char)*this->map_size*this->map_size)); + for(int i=0;i<number_of_lasers;i++) + gettimeofday(&last_time[i],NULL); + this->global_pose.p.x = this->global_pose.p.y = this->global_pose.phi = 0; + // what extra area(margine) in the stored map around the local map should be included in the ICP + this->local_map_margine = 0.5; + this->px=0; + this->py=0; + this->pa=0; + nu = 0; map_number = 1; + gchar * g_filename=g_strdup_printf("%sMAP_PATCH0",map_path); + this->map = new MAP(g_filename,this->map_resolution,this->map_size*2); + this->map->CreateMap(); + this->map->ResetProb(); + snprintf(filename,40,"%spatch_config.txt",map_path); + config_file = fopen(filename,"wb"); + // Initial Patch Settings + fprintf(config_file,"%s %.3f %.3f %.3f\n","MAP_PATCH0",0.0,0.0,0.0); + delta_pose.p.x=0; + delta_pose.p.y=0; + delta_pose.phi=0; + reset_timer= true; + sample_initialized = FALSE; + if(log) + { snprintf(filename,40, "%sicplog.txt",map_path); - file=fopen(filename,"wb"); - } - usleep((int)(this->start_in*1e6)); - return(0); + file=fopen(filename,"wb"); + } + usleep((int)(this->start_in*1e6)); + return(0); }; -void MrIcp::SetupPositionDriver() +void MRSM::SetupPositionDriver() { - Pose initial_pose={{0,0,0}}; - // Subscribe to the underlyin odometry device - if(!(this->position_device = deviceTable->GetDevice(this->position_in_addr))) - { - PLAYER_ERROR("unable to locate suitable position device"); - return ; - } - if(this->position_device->Subscribe(this->InQueue) != 0) - { - PLAYER_ERROR("unable to subscribe to position device"); - return ; - } - position_in_exists = true; - // Get the odometry geometry - Message* msg; - if(!(msg = this->position_device->Request(this->InQueue,PLAYER_MSGTYPE_REQ,PLAYER_POSITION2D_REQ_GET_GEOM,NULL, 0, NULL,false)) - ||(msg->GetHeader()->size != sizeof(player_position2d_geom_t))) + Pose initial_pose={{0,0,0}}; + // Subscribe to the underlyin odometry device + if(!(this->position_device = deviceTable->GetDevice(this->position_in_addr))) + { + PLAYER_ERROR("unable to locate suitable position device"); + return ; + } + if(this->position_device->Subscribe(this->InQueue) != 0) + { + PLAYER_ERROR("unable to subscribe to position device"); + return ; + } + position_in_exists = true; + // Get the odometry geometry + Message* msg; + if(!(msg = this->position_device->Request(this->InQueue,PLAYER_MSGTYPE_REQ,PLAYER_POSITION2D_REQ_GET_GEOM,NULL, 0, NULL,false)) + ||(msg->GetHeader()->size != sizeof(player_position2d_geom_t))) { PLAYER_ERROR("failed to get geometry of underlying position device"); if(msg) - delete msg; + delete msg; return; - } - memcpy(&geom,(player_position2d_geom_t *)msg->GetPayload(),sizeof(geom)); -// geom = (player_position2d_geom_t *)msg->GetPayload(); -// initial_pose = GetOdomReading(); - this->px = initial_pose.p.x; - this->py = initial_pose.p.y; - this->pa = initial_pose.phi; + } + memcpy(&geom,(player_position2d_geom_t *)msg->GetPayload(),sizeof(geom)); + // geom = (player_position2d_geom_t *)msg->GetPayload(); + // initial_pose = GetOdomReading(); + this->px = initial_pose.p.x; + this->py = initial_pose.p.y; + this->pa = initial_pose.phi; }; -int MrIcp::SetupLaser(int index) +int MRSM::SetupLaser(int index) { - // Subscribe to the Laser device - if (!(this->laser_device[index] = deviceTable->GetDevice(this->laser_addr[index]))) - { + // Subscribe to the Laser device + if (!(this->laser_device[index] = deviceTable->GetDevice(this->laser_addr[index]))) + { PLAYER_ERROR("unable to locate suitable laser device"); return -1; - } - if (this->laser_device[index]->Subscribe(this->InQueue) != 0) - { + } + if (this->laser_device[index]->Subscribe(this->InQueue) != 0) + { PLAYER_ERROR("unable to subscribe to laser device"); return -1; - } - // Ask for the laser's geometry - Message* msg; - if((msg = laser_device[index]->Request(this->InQueue,PLAYER_MSGTYPE_REQ,PLAYER_LASER_REQ_GET_GEOM,NULL, 0, NULL,false))) - { + } + // Ask for the laser's geometry + Message* msg; + if((msg = laser_device[index]->Request(this->InQueue,PLAYER_MSGTYPE_REQ,PLAYER_LASER_REQ_GET_GEOM,NULL, 0, NULL,false))) + { laser_geom = (player_laser_geom_t *)msg->GetPayload(); - // Get the laser pose relative to the robot center of Rotation - laser_pose[index].p.x = laser_geom->pose.px; - laser_pose[index].p.y = laser_geom->pose.py; - laser_pose[index].phi = laser_geom->pose.pyaw; - //if (this->debug) - cout<<"\n Laser["<<index<<"] Pose --> X="<<laser_pose[index].p.x<<" Y="<<laser_pose[index].p.y<<" Theta="<<laser_pose[index].phi; + // Get the laser pose relative to the robot center of Rotation + laser_pose[index].p.x = laser_geom->pose.px; + laser_pose[index].p.y = laser_geom->pose.py; + laser_pose[index].phi = laser_geom->pose.pyaw; + //if (this->debug) + cout<<"\n Laser["<<index<<"] Pose --> X="<<laser_pose[index].p.x<<" Y="<<laser_pose[index].p.y<<" Theta="<<laser_pose[index].phi; delete msg; return 0; - } - return -1; + } + return -1; }; -void MrIcp::ResetMap() +void MRSM::ResetMap() { - char filename[40]; - gchar * savefile; - sample_initialized = FALSE; - laser_set_1.clear(); - laser_set_2.clear(); - map_points.clear(); - //map->SavePixelBufferToFile(); - map->SavePgm(); - map->ClearData(); - snprintf(filename,40,"MAP_PATCH%d",map_number++); - savefile=g_strdup_printf("%s%s",map_path,filename); - map->Mapname = (char *)realloc(map->Mapname,strlen(savefile)*(sizeof(savefile[0]))); - strcpy(map->Mapname,savefile); - this->map->ResetProb(); - // Save Patch's Name + origin in terms of the previous Patch - fprintf(config_file,"%s %.3f %.3f %.3f\n",filename,global_pose.p.x,global_pose.p.y,global_pose.phi); - this->global_pose.p.x = this->global_pose.p.y = this->global_pose.phi = 0; + char filename[40]; + gchar * savefile; + sample_initialized = FALSE; + laser_set_1.clear(); + laser_set_2.clear(); + map_points.clear(); + //map->SavePixelBufferToFile(); + map->SavePgm(); + map->ClearData(); + snprintf(filename,40,"MAP_PATCH%d",map_number++); + savefile=g_strdup_printf("%s%s",map_path,filename); + map->Mapname = (char *)realloc(map->Mapname,strlen(savefile)*(sizeof(savefile[0]))); + strcpy(map->Mapname,savefile); + this->map->ResetProb(); + // Save Patch's Name + origin in terms of the previous Patch + fprintf(config_file,"%s %.3f %.3f %.3f\n",filename,global_pose.p.x,global_pose.p.y,global_pose.phi); + this->global_pose.p.x = this->global_pose.p.y = this->global_pose.phi = 0; } -void MrIcp::MainQuit() +void MRSM::MainQuit() { - // Stop and join the driver thread - cout<<"\n- Shutting Down MRICP Driver - Cleaning up Mess ..\n"; fflush(stdout); - for(int i=0;i<number_of_lasers;i++) - { + // Stop and join the driver thread + cout<<"\n- Shutting Down MRICP Driver - Cleaning up Mess ..\n"; fflush(stdout); + for(int i=0;i<number_of_lasers;i++) + { this->laser_device[i]->Unsubscribe(this->InQueue); this->laser_device[i] = NULL; - } - if(position_in_exists) - this->position_device->Unsubscribe(this->InQueue); + } + if(position_in_exists) + this->position_device->Unsubscribe(this->InQueue); //this->map->SavePixelBufferToFile(); this->map->SavePgm(); delete this->map; - cout<<"\n --->>> MAP Buffer Deleted->"; fflush(stdout); - this->occ_laser_set.clear(); + cout<<"\n --->>> MAP Buffer Deleted->"; fflush(stdout); + this->occ_laser_set.clear(); this->map_points.clear(); this->laser_set_1.clear(); this->laser_set_2.clear(); this->local_map.clear(); - cout<<" Vectors Cleared ->"; fflush(stdout); - if(log) - fclose(file); - fclose(config_file); - cout<<" Files Closed ->"; fflush(stdout); - //ConnectPatches(); - cout<<" Thread Killed ->"; fflush(stdout); - cout<<" ... ShutDown FINISED\n"; fflush(stdout); - + cout<<" Vectors Cleared ->"; fflush(stdout); + if(log) + fclose(file); + fclose(config_file); + cout<<" Files Closed ->"; fflush(stdout); + //ConnectPatches(); + cout<<" Thread Killed ->"; fflush(stdout); + cout<<" ... ShutDown FINISED\n"; fflush(stdout); + //ld_free(laserScan); }; // this function will run in a separate thread -void MrIcp::Main() +void MRSM::Main() { - MricpTimer loop_timer,map_timer,test; - double time_elapsed; - // Synchronously cancelable thread. - //pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); + MricpTimer loop_timer,map_timer,test; + double time_elapsed; + // Synchronously cancelable thread. + //pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); - /* To use the MricpTimer.Synch() in a loop you will have to + /* To use the MricpTimer.Synch() in a loop you will have to * reset the timer at the beginning of the loop then call * the MricpTimer.Synch(period) at the end of the loop with * period representing the synchronization time in msec, @@ -735,34 +658,37 @@ void MrIcp::Main() * this loop and then sleep the remaining period time * (if the time taken by the loop is less than the allowed period) */ - while(1) - { - loop_timer.Reset(); - test.Reset(); - pthread_testcancel(); // Thread cancellation point. - this->ProcessMessages(); - BuildMap(); // Launch the MrICP on two laser scans - RefreshData(); // Update Data - time_elapsed = loop_timer.TimeElapsed(); - if(this->debug) - cout<<"\n Min Loop took="<<time_elapsed/1e3<<"usec"; - loop_timer.Synch(this->period*1e3); - time_elapsed = map_timer.TimeElapsed(); - if( time_elapsed >= this->map_saving_period*1e6) - { - this->map->SavePgm(); - map_timer.Reset(); - } - time_elapsed = loop_timer.TimeElapsed(); - if(this->debug) - cout<<"\n Time Synch="<<time_elapsed/1e3<<"usec"; - } - pthread_exit(NULL); + while(1) + { + loop_timer.Reset(); + test.Reset(); + pthread_testcancel(); + // Thread cancellation point. + this->ProcessMessages(); + // Launch the MrICP on two laser scans + BuildMap(); + // Update Data + RefreshData(); + time_elapsed = loop_timer.TimeElapsed(); + if(this->debug) + cout<<"\n Min Loop took="<<time_elapsed/1e3<<"usec"; + loop_timer.Synch(this->period*1e3); + time_elapsed = map_timer.TimeElapsed(); + if( time_elapsed >= this->map_saving_period*1e6) + { + this->map->SavePgm(); + map_timer.Reset(); + } + time_elapsed = loop_timer.TimeElapsed(); + if(this->debug) + cout<<"\n Time Synch="<<time_elapsed/1e3<<"usec"; + } + pthread_exit(NULL); } /*! Forwards the Messeges from the messege queue to their * specific handler */ -int MrIcp::ProcessMessage(QueuePointer& resp_queue, player_msghdr * hdr, void * data) +int MRSM::ProcessMessage(QueuePointer& resp_queue, player_msghdr * hdr, void * data) { // Forward the Messages switch (hdr->type) @@ -780,7 +706,7 @@ int MrIcp::ProcessMessage(QueuePointer& resp_queue, player_msghdr * hdr, void * /*! Gets the Laser and Position Data from the underlying Devices * If they are provided. */ -int MrIcp::HandleData(QueuePointer& resp_queue, player_msghdr * hdr, void * idata) +int MRSM::HandleData(QueuePointer& resp_queue, player_msghdr * hdr, void * idata) { struct timeval currtime; double t1,t2, min_angle, scan_res,r,b,time_diff; @@ -820,14 +746,29 @@ int MrIcp::HandleData(QueuePointer& resp_queue, player_msghdr * hdr, void * idat this->scan_count = data->ranges_count; if(this->debug) cout<<"\n Scan Count="<<this->scan_count; + laserScan = ld_alloc_new(data->ranges_count); + laserScan->nrays = data->ranges_count; + laserScan->min_theta = min_angle; + laserScan->max_theta = data->max_angle; + laserScan->tv = current_time; for(int i=0;i < scan_count ;i++) { // convert to mm, then m, according to given range resolution r = data->ranges[i]; - b = min_angle + (i * scan_res); // compute bearing - //cout<<"\n Bearing:"<<RTOD(b); - if(InRange(b,index)!=0) - continue; + b = min_angle + (i * scan_res); + if(!inRange(b,index)) + { + laserScan->readings[i] = NAN; + laserScan->theta[i] = b; + laserScan->valid[i] = 0; + continue; + } + if(i==(scan_count-1)) + laserScan->max_theta = b; + laserScan->readings[i] = r; + laserScan->theta[i] = b; + laserScan->valid[i] = 1; + // Transfer from Polar to Cartesian coordinates p.x = r * cos(b); p.y = r * sin(b); @@ -860,7 +801,7 @@ int MrIcp::HandleData(QueuePointer& resp_queue, player_msghdr * hdr, void * idat return -1; }; -int MrIcp::HandleConfigs(QueuePointer &resp_queue,player_msghdr * hdr,void * data) +int MRSM::HandleConfigs(QueuePointer &resp_queue,player_msghdr * hdr,void * data) { // Handle Position REQ // I didn't like the stupid MessageMatch Method @@ -957,7 +898,7 @@ int MrIcp::HandleConfigs(QueuePointer &resp_queue,player_msghdr * hdr,void * dat } return -1; } -int MrIcp::HandleCommands(QueuePointer& resp_queue,player_msghdr * hdr,void * data) +int MRSM::HandleCommands(QueuePointer& resp_queue,player_msghdr * hdr,void * data) { if(Message::MatchMessage(hdr,PLAYER_MSGTYPE_CMD,PLAYER_POSITION2D_CMD_VEL,this->position_out_addr)) { @@ -978,7 +919,7 @@ int MrIcp::HandleCommands(QueuePointer& resp_queue,player_msghdr * hdr,void * d return -1; } // Handle map info request -int MrIcp::ProcessMapInfoReq(QueuePointer& resp_queue,player_msghdr * hdr,void * data) +int MRSM::ProcessMapInfoReq(QueuePointer& resp_queue,player_msghdr * hdr,void * data) { // Is it a request for map meta-data? cout<<"\n Processing Map Info request!!!"; fflush(stdout); @@ -1005,7 +946,7 @@ int MrIcp::ProcessMapInfoReq(QueuePointer& resp_queue,player_msghdr * hdr,void * } // Handle map data request -int MrIcp::ProcessMapDataReq(QueuePointer& resp_queue,player_msghdr * hdr,void * data) +int MRSM::ProcessMapDataReq(QueuePointer& resp_queue,player_msghdr * hdr,void * data) { if(Message::MatchMessage(hdr, PLAYER_MSGTYPE_REQ, PLAYER_MAP_REQ_GET_DATA, @@ -1130,7 +1071,7 @@ int MrIcp::ProcessMapDataReq(QueuePointer& resp_queue,player_msghdr * hdr,void * return -1; }; -void MrIcp::RefreshData() +void MRSM::RefreshData() { // Write position data// this->position_out_data.pos.px = this->px; @@ -1144,16 +1085,16 @@ void MrIcp::RefreshData() // Check if the laser beam is in the allowed range // This is useful if you have something or part of the robot obstructing the field of view // of the laser -int MrIcp::InRange(double angle,int laser_index) +bool MRSM::inRange(double angle,int laser_index) { for(int i=0;i<range_count[laser_index];i++) { - if(range[laser_index][i].begins <= RTOD(angle) && RTOD(angle) <= range[laser_index][i].ends) - return 0; + if(range[laser_index][i].begins <= RTOD(angle) && RTOD(angle) <= range[laser_index][i].ends) + return true; } - return -1; // Beam to be ignored + return false; // Beam to be ignored }; -Point MrIcp::TransformToGlobal(Point p,Pose pose) +Point MRSM::TransformToGlobal(Point p,Pose pose) { // Rotate + Translate Point temp = p; @@ -1161,7 +1102,7 @@ Point MrIcp::TransformToGlobal(Point p,Pose pose) p.y = temp.x*sin(pose.phi) + temp.y*cos(pose.phi) + pose.p.y ; return p; }; -Pose MrIcp::TransformToGlobal(Pose p,Pose pose) +Pose MRSM::TransformToGlobal(Pose p,Pose pose) { // Rotate + Translate Point temp = p.p; @@ -1171,21 +1112,68 @@ Pose MrIcp::TransformToGlobal(Pose p,Pose pose) return p; }; // transfers from Pixel to the Map coordinate -Point MrIcp :: ConvertPixel(Point p) +Point MRSM :: ConvertPixel(Point p) { p.x = ( p.x*this->map_resolution - this->map_size) ; p.y = (-p.y*this->map_resolution + this->map_size) ; return p; }; // transfers from Map into the Pixel Coordinate -Point MrIcp :: ConvertToPixel(Point p) +Point MRSM :: ConvertToPixel(Point p) { // This is a NxN Map with N = 2*map_size p.x = rint (( p.x + this->map_size)/this->map_resolution); p.y = rint ((-p.y + this->map_size)/this->map_resolution); return p; }; -mapgrid_t MrIcp::ComputeRangeProb(double range,bool free) + +LDP MRSM::laserPointSet2LDP(vector<Point> laserSet) +{ + int nrays=laserSet.size(); + LDP ld = ld_alloc_new(nrays); + double fov = M_PI; + double min_reading = 0; + double max_reading = 80; + + if(nrays == 769) + { + min_reading = 0.001; + max_reading = 4; + fov = deg2rad(270.0); + } + + ld->min_theta = -fov/2; + ld->max_theta = +fov/2; + + for(int i=0;i<nrays;i++) + { + double reading; + ld->valid[i] = (reading > min_reading) && (reading < max_reading); + ld->readings[i] = ld->valid[i] ? reading : NAN; + ld->theta[i] = ld->min_theta + i *(ld->max_theta-ld->min_theta) / (ld->nrays-1); + // bad hokuyo!! + if(nrays == 769) + { + if(i>725 || i<44) + { + ld->valid[i] = 0; + ld->readings[i] = NAN; + } + } + } +/* + ld->estimate[0] = ; + ld->estimate[1] = ; + ld->estimate[2] = ; + ld->odometry[0] = ; + ld->odometry[1] = ; + ld->odometry[2] = ; +*/ + ld->tv = current_time; + return ld; +} + +mapgrid_t MRSM::ComputeRangeProb(double range,bool free) { double bad_range=0.; mapgrid_t prob; @@ -1214,7 +1202,7 @@ mapgrid_t MrIcp::ComputeRangeProb(double range,bool free) } return prob; } -void MrIcp::AddToMap(vector<Point> laser_data,Pose pose) +void MRSM::AddToMap(vector<Point> laser_data,Pose pose) { Point p,pixel_point,d,in_p; Pose relative_laser_pose; @@ -1322,165 +1310,182 @@ void MrIcp::AddToMap(vector<Point> laser_data,Pose pose) } }; // Only get the Existing Map points that are useful for Allignement -void MrIcp::GenerateLocalMap(Pose pse) +void MRSM::GenerateLocalMap(Pose pse) { - double farest_laser_dist=0,dist,num_pixels; - Point location,grid_start,temp; - location.x = pse.p.x; - location.y = pse.p.y; - local_map.clear(); - for(int i=0;i<this->number_of_lasers;i++) - { - // Get the distance from the Robot's Origin to the Laser Position - dist = sqrt(pow(laser_pose[i].p.x,2)+pow(laser_pose[i].p.y,2)); - if( dist > farest_laser_dist ) - farest_laser_dist = dist; - } -// for (unsigned int i=0;i<map_points.size();i++) -// { -// if (sqrt (pow(pse.p.x - map_points[i].x,2) + pow(pse.p.y - map_points[i].y,2)) <= (maxr + farest_laser_dist + local_map_margine)) -// local_map.push_back(map_points[i]); -// } - num_pixels = (farest_laser_dist + this->maxr + local_map_margine) /this->map_resolution; - location = ConvertToPixel(location); - grid_start.x = location.x - num_pixels; - if(grid_start.x < 0) - grid_start.x = 0; - grid_start.y = location.y - num_pixels; - if(grid_start.y < 0) - grid_start.y = 0; + double farest_laser_dist=0,dist,num_pixels; + Point location,grid_start,temp; + location.x = pse.p.x; + location.y = pse.p.y; + local_map.clear(); + for(int i=0;i<this->number_of_lasers;i++) + { + // Get the distance from the Robot's Origin to the Laser Position + dist = sqrt(pow(laser_pose[i].p.x,2)+pow(laser_pose[i].p.y,2)); + if( dist > farest_laser_dist ) + farest_laser_dist = dist; + } + // for (unsigned int i=0;i<map_points.size();i++) + // { + // if (sqrt (pow(pse.p.x - map_points[i].x,2) + pow(pse.p.y - map_points[i].y,2)) <= (maxr + farest_laser_dist + local_map_margine)) + // local_map.push_back(map_points[i]); + // } + num_pixels = (farest_laser_dist + this->maxr + local_map_margine) /this->map_resolution; + location = ConvertToPixel(location); + grid_start.x = location.x - num_pixels; + if(grid_start.x < 0) + grid_start.x = 0; + grid_start.y = location.y - num_pixels; + if(grid_start.y < 0) + grid_start.y = 0; //cout<<"\nStart grid: "<<grid_start.x<<" y:"<<grid_start.y<<" pixels:"<<num_pixels; fflush(stdout); - for(int i= (int)(grid_start.x) ; i< (2*num_pixels + grid_start.x); i++) - for(int j=(int)(grid_start.y);j<(2*num_pixels + grid_start.y); j++) - { - // y is -2 because last row is meta data - if(i<(map->size_x - 1) && j<(map->size_y - 2)) - if (map->occ_grid[i][j].prob_occ > 0.9) - { - temp.x = i; - temp.y = j; - local_map.push_back(ConvertPixel(temp)); - } - } + for(int i= (int)(grid_start.x) ; i< (2*num_pixels + grid_start.x); i++) + for(int j=(int)(grid_start.y);j<(2*num_pixels + grid_start.y); j++) + { + // y is -2 because last row is meta data + if(i<(map->size_x - 1) && j<(map->size_y - 2)) + if (map->occ_grid[i][j].prob_occ > 0.9) + { + temp.x = i; + temp.y = j; + local_map.push_back(ConvertPixel(temp)); + } + } }; -void MrIcp::BuildMap() -{ -// double estimated_delta_d,estimated_delta_phi; - this->delta_time = delta_t_estimation.TimeElapsed()/1e6; - if(this->reset_timer) - delta_t_estimation.Reset(); - if (!sample_initialized) - { - laser_set_1 = laser_set; - if (laser_set_1.size() != 0) - sample_initialized = TRUE; - else - return; - // Read Pose if postion driver exists - if(this->position_device) pose_1 = P; - global_pose.p.x = global_pose.p.y = global_pose.phi = 0; - AddToMap(laser_set_1,global_pose); - gettimeofday(&last_delta,NULL); - return; - } - laser_set_2 = laser_set; - if (laser_set_2.size() == 0 || laser_set_1.size() == 0) - return; - if(this->debug) - cout<<"\n Laser Set 1 Size:"<<laser_set_1.size()<<" Laser Set 2 Size:"<<laser_set_2.size(); +void MRSM::BuildMap() +{ + // double estimated_delta_d,estimated_delta_phi; + this->delta_time = delta_t_estimation.TimeElapsed()/1e6; + if(this->reset_timer) + delta_t_estimation.Reset(); + if (!sample_initialized) + { + laser_set_1 = laser_set; + refLaserScan = laserScan; + if (laser_set_1.size() != 0) + sample_initialized = TRUE; + else + return; + // Read Pose if postion driver exists + if(this->position_device) + pose_1 = P; + global_pose.p.x = global_pose.p.y = global_pose.phi = 0; + laserScan->estimate[0] = 0; + laserScan->estimate[1] = 0; + laserScan->estimate[2] = 0; + AddToMap(laser_set_1,global_pose); + gettimeofday(&last_delta,NULL); + return; + } + laser_set_2 = laser_set; + currentLaserScan = laserScan; + if (laser_set_2.size() == 0 || laser_set_1.size() == 0) + return; + if(this->debug) + cout<<"\n Laser Set 1 Size:"<<laser_set_1.size()<<" Laser Set 2 Size:"<<laser_set_2.size(); + // Read Pose if position driver exists + if(this->use_odom) + { + pose_2 = P; + delta_pose.phi = NORMALIZE(pose_2.phi - pose_1.phi); + delta_pose.p.x = (pose_2.p.x - pose_1.p.x)*cos(pose_1.phi) + (pose_2.p.y - pose_1.p.y)*sin(pose_1.phi) ; + delta_pose.p.y = -(pose_2.p.x - pose_1.p.x)*sin(pose_1.phi) + (pose_2.p.y - pose_1.p.y)*cos(pose_1.phi) ; + refLaserScan->odometry[0] = pose_2.p.x; + refLaserScan->odometry[1] = pose_2.p.y; + refLaserScan->odometry[2] = pose_2.phi; + currentLaserScan->odometry[0] = pose_1.p.x; + currentLaserScan->odometry[1] = pose_1.p.y; + currentLaserScan->odometry[2] = pose_1.phi; + } + else + { + delta_pose.phi = 0; delta_pose.p.x = 0; delta_pose.p.y = 0; + refLaserScan->odometry[0] = 0; + refLaserScan->odometry[1] = 0; + refLaserScan->odometry[2] = 0; + currentLaserScan->odometry[0] = 0; + currentLaserScan->odometry[1] = 0; + currentLaserScan->odometry[2] = 0; + } + sm_result matchingResult = csm.scanMatch(refLaserScan,currentLaserScan); + if(matchingResult.valid) + { + cout<<"\nMatching result x:"<<matchingResult.x[0]<<" y:"<<matchingResult.x[1]<<" theta:"<<matchingResult.x[2];fflush(stdout); + //cout<<"\nGlobal result x:"<<currentLaserScan->estimate[0]<<" y:"<<currentLaserScan->estimate[1]<<" theta:"<<currentLaserScan->estimate[2];fflush(stdout); + } + else + { + cout<<"\nInvalid matching results";fflush(stdout); + } + if (this->debug) + { + cout<<"\n POSE 1 XYQ["<<pose_1.p.x<<"]["<<pose_1.p.y<<"]["<<pose_1.phi<<"] "; + cout<<" POSE 2 XYQ["<<pose_2.p.x<<"]["<<pose_2.p.y<<"]["<<pose_2.phi<<"]"; + } - // Read Pose if position driver exists - if(this->use_odom) - { - pose_2 = P; - delta_pose.phi = NORMALIZE(pose_2.phi - pose_1.phi); - delta_pose.p.x = (pose_2.p.x - pose_1.p.x)*cos(pose_1.phi) + (pose_2.p.y - pose_1.p.y)*sin(pose_1.phi) ; - delta_pose.p.y = -(pose_2.p.x - pose_1.p.x)*sin(pose_1.phi) + (pose_2.p.y - pose_1.p.y)*cos(pose_1.phi) ; - } - else - { - delta_pose.phi = 0; delta_pose.p.x = 0; delta_pose.p.y = 0; - } - if (this->debug) - { - cout<<"\n POSE 1 XYQ["<<pose_1.p.x<<"]["<<pose_1.p.y<<"]["<<pose_1.phi<<"] "; - cout<<" POSE 2 XYQ["<<pose_2.p.x<<"]["<<pose_2.p.y<<"]["<<pose_2.phi<<"]"; - } - // Estimate the movement based on the last linear and angular velocity - //estimated_delta_d = this->delta_time * this->speed; - //estimated_delta_phi= this->delta_time * this->turn_rate; - //cout<<"\n Delta t:"<<delta_time<<" Estimeted d:"<<estimated_delta_d<<" Estimated Phi:"<<estimated_delta_phi; + // Check what is the displacement estimated by ICP + delta_pose = icp.align(laser_set_1,laser_set_2,delta_pose, gate1, nit, interpolate); + cout<<"\nDelta Pose:2 x:"<<delta_pose.p.x<<" y:"<<delta_pose.p.x<<" phi:"<<delta_pose.phi; + if(delta_pose.p.x ==-1 && delta_pose.p.y ==-1 && delta_pose.phi==-1) + { + if (this->warning_misalign) + cout <<"\nWARNING: possible misalignment ICP: 1 - skipping scan"; + return; + } + global_pose = TransformToGlobal(delta_pose,global_pose); - // Check what is the displacement estimated by ICP - delta_pose = icp.align(laser_set_1,laser_set_2,delta_pose, gate1, nit, interpolate); - if(delta_pose.p.x ==-1 && delta_pose.p.y ==-1 && delta_pose.phi==-1) - { - if (this->warning_misalign) - cout <<"\nWARNING: possible misalignment ICP: 1 - skipping scan"; - //laser_set_1 = laser_set_2; - return; - } - global_pose = TransformToGlobal(delta_pose,global_pose); - // Is the ICP estimation more than what we excpect ?? If yes then ignore this set - /*if(sqrt(pow(delta_pose.p.x,2)+pow(delta_pose.p.y,2)) > (estimated_delta_d +0.1 ) || abs(delta_pose.phi) > abs(estimated_delta_phi + DTOR(5))) - { - cout<<"\n Delta Pose:1 x:"<<delta_pose.p.x <<" Y="<<delta_pose.p.y<<" Phi"<<delta_pose.phi; - cout <<"\nWARNING: possible misalignment - skipping scan"; - this->reset_timer = false; - return; - }*/ - this->reset_timer = true; - if (!this->map_points.size()) - { - sample_initialized = false; - return; - } - this->speed = sqrt(pow(delta_pose.p.x,2) + pow(delta_pose.p.y,2))/this->delta_time; - this->turn_rate = delta_pose.phi/this->delta_time; + this->reset_timer = true; + if (!this->map_points.size()) + { + sample_initialized = false; + return; + } + this->speed = sqrt(pow(delta_pose.p.x,2) + pow(delta_pose.p.y,2))/this->delta_time; + this->turn_rate = delta_pose.phi/this->delta_time; - GenerateLocalMap(global_pose); - global_pose = icp.align(this->local_map,laser_set_2,global_pose, gate1, nit, interpolate); - if(global_pose.p.x ==-1 && global_pose.p.y ==-1 && global_pose.phi==-1) - { - if (this->warning_misalign) - cout <<"\nWARNING: possible misalignment ICP: 2 - skipping scan"; - global_pose.p.x = global_pose_prev.p.x; - global_pose.p.y = global_pose_prev.p.y; - global_pose.phi = global_pose_prev.phi; - //laser_set_1 = laser_set_2; - return; - } - if(this->debug) - cout<<"\n Delta Pose:2 x:"<<global_pose.p.x<<" y:"<<global_pose.p.x<<" phi:"<<global_pose.phi; - global_pose = icp.align(this->local_map,laser_set_2,global_pose, gate2, nit, interpolate); - if(global_pose.p.x ==-1 && global_pose.p.y ==-1 && global_pose.phi==-1) - { - if (this->warning_misalign) - cout <<"\nWARNING: possible misalignment ICP: 3 - skipping scan"; - global_pose.p.x = global_pose_prev.p.x; - global_pose.p.y = global_pose_prev.p.y; - global_pose.phi = global_pose_prev.phi; - //laser_set_1 = laser_set_2; - return; - } - if(this->debug) - cout<<"\n Delta Pose:3 x:"<<global_pose.p.x<<" y:"<<global_pose.p.x<<" phi:"<<global_pose.phi; + GenerateLocalMap(global_pose); + global_pose = icp.align(this->local_map,laser_set_2,global_pose, gate1, nit, interpolate); + if(global_pose.p.x ==-1 && global_pose.p.y ==-1 && global_pose.phi==-1) + { + if (this->warning_misalign) + cout <<"\nWARNING: possible misalignment ICP: 2 - skipping scan"; + global_pose.p.x = global_pose_prev.p.x; + global_pose.p.y = global_pose_prev.p.y; + global_pose.phi = global_pose_prev.phi; + return; + } + if(this->debug) + cout<<"\n Delta Pose:2 x:"<<global_pose.p.x<<" y:"<<global_pose.p.x<<" phi:"<<global_pose.phi; + global_pose = icp.align(this->local_map,laser_set_2,global_pose, gate2, nit, interpolate); + if(global_pose.p.x ==-1 && global_pose.p.y ==-1 && global_pose.phi==-1) + { + if (this->warning_misalign) + cout <<"\nWARNING: possible misalignment ICP: 3 - skipping scan"; + global_pose.p.x = global_pose_prev.p.x; + global_pose.p.y = global_pose_prev.p.y; + global_pose.phi = global_pose_prev.phi; + //laser_set_1 = laser_set_2; + return; + } + if(this->debug) + cout<<"\n Delta Pose:3 x:"<<global_pose.p.x<<" y:"<<global_pose.p.x<<" phi:"<<global_pose.phi; - // Serve Data to Position Interface - this->global_pose_prev.p.x = this->px = global_pose.p.x; - this->global_pose_prev.p.y = this->py = global_pose.p.y; - this->global_pose_prev.phi = this->pa = NORMALIZE(global_pose.phi); - // Use ALL the Laser data for the occupancy grid update - AddToMap(occ_laser_set,global_pose); + // Serve Data to Position Interface + this->global_pose_prev.p.x = this->px = global_pose.p.x; + this->global_pose_prev.p.y = this->py = global_pose.p.y; + this->global_pose_prev.phi = this->pa = NORMALIZE(global_pose.phi); + // Use ALL the Laser data for the occupancy grid update + AddToMap(occ_laser_set,global_pose); - // Perform the ICP on Next Laser Scan - laser_set_1 = laser_set_2; - if(this->position_device) - pose_1 = pose_2; + // Perform the ICP on Next Laser Scan + laser_set_1 = laser_set_2; + ld_free(refLaserScan); + refLaserScan = currentLaserScan; + if(this->position_device) + pose_1 = pose_2; }; -void MrIcp::ConnectPatches() +void MRSM::ConnectPatches() { int patch_number=0; gchar * patch; diff --git a/sm/drivers/playerstage/mricp/stage_test/stage_mricp.cfg b/sm/drivers/playerstage/mricp/stage_test/stage_mricp.cfg index 5d4cedf..e567714 100644 --- a/sm/drivers/playerstage/mricp/stage_test/stage_mricp.cfg +++ b/sm/drivers/playerstage/mricp/stage_test/stage_mricp.cfg @@ -17,8 +17,8 @@ driver driver ( - name "mricp" - plugin "libmricp" + name "MRSM" + plugin "libmricp.so" provides ["position2d:1" "map:0"] requires ["position2d:0" "laser:0"] number_of_lasers 1 -- GitLab