00001 #include "localization3d_alg_node.h"
00002
00003 Localization3dAlgNode::Localization3dAlgNode(void)
00004 {
00005
00006
00007
00008 infoGain = 0;
00009
00010
00011 this->tf_publisher_ = this->public_node_handle_.advertise<tf::tfMessage>("odom_to_map", 100);
00012 this->particleSet_publisher_ = this->public_node_handle_.advertise<geometry_msgs::PoseArray>("particleSet", 100);
00013 this->position_publisher_ = this->public_node_handle_.advertise<geometry_msgs::PoseWithCovarianceStamped>("position", 100);
00014
00015
00016 this->platformData_subscriber_ = this->public_node_handle_.subscribe("platform_data", 100, &Localization3dAlgNode::platformData_callback, this);
00017 this->platformOdometry_subscriber_ = this->public_node_handle_.subscribe("platform_odom", 100, &Localization3dAlgNode::platformOdometry_callback, this);
00018 this->laser0_subscriber_ = this->public_node_handle_.subscribe("laser0/scan", 100, &Localization3dAlgNode::laser0_callback, this);
00019 this->laser1_subscriber_ = this->public_node_handle_.subscribe("laser1/scan", 100, &Localization3dAlgNode::laser1_callback, this);
00020 this->laser2_subscriber_ = this->public_node_handle_.subscribe("laser2/scan", 100, &Localization3dAlgNode::laser2_callback, this);
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 odometry.setTimeStamp();
00032
00033
00034
00035 double lp_rt;
00036 this->public_node_handle_.getParam("filter_rate", lp_rt);
00037 this->loop_rate_ = lp_rt;
00038 transform_tolerance_.fromSec(1.0/lp_rt+0.1);
00039 this->public_node_handle_.getParam("num_particles", numberOfParticles);
00040 this->public_node_handle_.getParam("resampling_style", resamplingStyle);
00041 this->public_node_handle_.getParam("mapFile", mapFileName);
00042 this->public_node_handle_.getParam("floorGridFile", gridFileName);
00043 this->public_node_handle_.getParam("initX", initX);
00044 this->public_node_handle_.getParam("initY", initY);
00045 this->public_node_handle_.getParam("initH", initH);
00046
00047 this->public_node_handle_.getParam("odo_error_XY",odometry.error_factor_XY);
00048 this->public_node_handle_.getParam("odo_error_H",odometry.error_factor_H);
00049 this->public_node_handle_.getParam("odo_error_P",odometry.error_factor_P);
00050 this->public_node_handle_.getParam("odo_error_R",odometry.error_factor_R);
00051
00052 this->public_node_handle_.getParam("sigma_heading",inclinometers.sigmaH);
00053 this->public_node_handle_.getParam("sigma_pitch_roll",inclinometers.sigmaP);
00054 this->public_node_handle_.getParam("sigma_pitch_roll",inclinometers.sigmaR);
00055
00056 this->public_node_handle_.getParam("l0_frameName",rDevConfig[0].frameName);
00057 this->public_node_handle_.getParam("l0_typeId",rDevConfig[0].deviceType);
00058 if (rDevConfig[0].deviceType == 0)
00059 {
00060 this->public_node_handle_.getParam("l0_nRays",rDevConfig[0].nRays);
00061 this->public_node_handle_.getParam("l0_aperture",rDevConfig[0].aperture);
00062 this->public_node_handle_.getParam("l0_rMin",rDevConfig[0].rangeMin);
00063 this->public_node_handle_.getParam("l0_rMax",rDevConfig[0].rangeMax);
00064 this->public_node_handle_.getParam("l0_sigma_range",rDevConfig[0].stdDev);
00065 }
00066 this->public_node_handle_.getParam("l1_frameName",rDevConfig[1].frameName);
00067 this->public_node_handle_.getParam("l1_typeId",rDevConfig[1].deviceType);
00068 if (rDevConfig[1].deviceType == 0)
00069 {
00070 this->public_node_handle_.getParam("l1_nRays",rDevConfig[1].nRays);
00071 this->public_node_handle_.getParam("l1_aperture",rDevConfig[1].aperture);
00072 this->public_node_handle_.getParam("l1_rMin",rDevConfig[1].rangeMin);
00073 this->public_node_handle_.getParam("l1_rMax",rDevConfig[1].rangeMax);
00074 this->public_node_handle_.getParam("l1_sigma_range",rDevConfig[1].stdDev);
00075 }
00076 this->public_node_handle_.getParam("l2_frameName",rDevConfig[2].frameName);
00077 this->public_node_handle_.getParam("l2_typeId",rDevConfig[2].deviceType);
00078 if (rDevConfig[2].deviceType == 0)
00079 {
00080 this->public_node_handle_.getParam("l2_nRays",rDevConfig[2].nRays);
00081 this->public_node_handle_.getParam("l2_aperture",rDevConfig[2].aperture);
00082 this->public_node_handle_.getParam("l2_rMin",rDevConfig[2].rangeMin);
00083 this->public_node_handle_.getParam("l2_rMax",rDevConfig[2].rangeMax);
00084 this->public_node_handle_.getParam("l2_sigma_range",rDevConfig[2].stdDev);
00085 }
00086
00087
00088 printUserConfiguration();
00089
00090
00091
00092 initDevicePositions();
00093
00094
00095 int debugMode;
00096 this->public_node_handle_.getParam("debug_mode",debugMode);
00097
00098 pFilter = new CbasicPF(gridFileName, mapFileName, (bool)debugMode);
00099 for (unsigned int ii=0; ii<MAX_RANGE_DEVICES; ii++)
00100 {
00101 if(rDevConfig[ii].frameName != "" )
00102 {
00103 if(rDevConfig[ii].deviceType == 0 )
00104 {
00105 pFilter->addRangeModel(2, rDevConfig[ii].nRays, rDevConfig[ii].aperture, rDevConfig[ii].aperture/(double)rDevConfig[ii].nRays,rDevConfig[ii].rangeMin,rDevConfig[ii].rangeMax,ii);
00106 }
00107 else
00108 {
00109 pFilter->addRangeModel(rDevConfig[ii].deviceType,ii);
00110 }
00111 }
00112 }
00113
00114
00115 pFilter->trackingInit(numberOfParticles, initX, initY, initH);
00116
00117 }
00118
00119 Localization3dAlgNode::~Localization3dAlgNode(void)
00120 {
00121
00122 delete pFilter;
00123 }
00124
00125 void Localization3dAlgNode::initDevicePositions()
00126 {
00127 tf::TransformListener tfListener;
00128 tf::StampedTransform laserWRTbase;
00129
00130
00131
00132
00133
00134 for (unsigned int ii=0; ii<MAX_RANGE_DEVICES; ii++)
00135 {
00136 if(rDevConfig[ii].frameName != "" )
00137 {
00138 tfListener.waitForTransform("base_link", rDevConfig[ii].frameName, ros::Time(0), ros::Duration(10.0),ros::Duration(1.0));
00139
00140
00141 tfListener.lookupTransform("base_link", rDevConfig[ii].frameName, ros::Time(0), laserWRTbase);
00142 laserObs[ii].mountingPosition.setXYZ(laserWRTbase.getOrigin().x(),laserWRTbase.getOrigin().y(),laserWRTbase.getOrigin().z());
00143 laserObs[ii].mountingPosition.setQuaternion(laserWRTbase.getRotation().getW(),laserWRTbase.getRotation().getX(),laserWRTbase.getRotation().getY(),laserWRTbase.getRotation().getZ());
00144 laserObs[ii].mountingPosition.printPosition();
00145 }
00146 }
00147 }
00148
00149 void Localization3dAlgNode::printUserConfiguration()
00150 {
00151 std::cout << "********************** PARTICLE FILTER CONFIGURATION **************************" << std::endl;
00152 std::cout << "Number Of Particles = \t " << numberOfParticles << std::endl;
00153
00154 std::cout << "Init (X,Y,H) = \t" << "(" << initX << "," << initY << "," << initH << ")" << std::endl;
00155 std::cout << "Map File = \t" << mapFileName << std::endl;
00156 std::cout << "Grid File = \t" << gridFileName << std::endl;
00157
00158 for (unsigned int ii=0; ii<MAX_RANGE_DEVICES; ii++)
00159 {
00160 if(rDevConfig[ii].frameName != "" )
00161 {
00162 std::cout << "RANGE DEVICE " << ii << std::endl;
00163 std::cout << "\t Frame Name = \t" << rDevConfig[ii].frameName << std::endl;
00164 std::cout << "\t Type = \t" << rDevConfig[ii].deviceType << std::endl;
00165 std::cout << "\t Num Rays = \t" << rDevConfig[ii].nRays << std::endl;
00166 std::cout << "\t Aperture = \t" << rDevConfig[ii].aperture << std::endl;
00167 std::cout << "\t Min Range = \t" << rDevConfig[ii].rangeMin << std::endl;
00168 std::cout << "\t Max Range = \t" << rDevConfig[ii].rangeMax << std::endl;
00169 }
00170 }
00171 std::cout << "*******************************************************************************" << std::endl;
00172 }
00173
00174 void Localization3dAlgNode::mainNodeThread(void)
00175 {
00176 double qReal, qi, qj, qk;
00177 unsigned int ii;
00178 Cparticle3d *particlePtr;
00179 tf::Quaternion quat;
00180
00181
00182
00183 config_mutex.enter();
00184
00185
00186 pFilter->incrementIterationId();
00187
00188
00189
00190 this->platformOdometry_mutex_.enter();
00191
00192
00193 pFilter->propagatePset(odometry);
00194
00195
00196 priorTime = odoTime;
00197 this->platformOdometry_mutex_.exit();
00198
00199
00200
00201 locEstimate.setTimeStamp();
00202
00203
00204
00205
00206
00207 this->platformData_mutex_.enter();
00208 pFilter->correctPset(inclinometers);
00209 this->platformData_mutex_.exit();
00210
00211
00212
00213
00214 for (ii=0; ii<MAX_RANGE_DEVICES; ii++)
00215 {
00216 if(rDevConfig[ii].frameName != "" )
00217 {
00218 this->laser_mutex[ii].enter();
00219 pFilter->correctPset(laserObs[ii], ii);
00220 this->laser_mutex[ii].exit();
00221 }
00222 }
00223
00224
00225 pFilter->normalizePset();
00226
00227
00228
00229 infoGain += pFilter->computeKLDivergence();
00230
00231
00232
00233 pFilter->setEstimate(locEstimate);
00234
00235
00236
00237
00238 pFilter->resamplingPset((unsigned int)resamplingStyle);
00239
00240
00241
00242 config_mutex.exit();
00243
00244
00245
00246
00247
00248 this->PoseArray_msg_.header.seq = pFilter->getIterationId();
00249
00250
00251 this->PoseArray_msg_.header.stamp = priorTime;
00252 this->PoseArray_msg_.header.frame_id = mapFrame;
00253 for(ii=0; ii<pFilter->getNumParticles(); ii++)
00254 {
00255 particlePtr = pFilter->getParticle(ii);
00256 PoseArray_msg_.poses.resize(ii+1);
00257 PoseArray_msg_.poses.at(ii).position.x = particlePtr->getX();
00258 PoseArray_msg_.poses.at(ii).position.y = particlePtr->getY();
00259 PoseArray_msg_.poses.at(ii).position.z = particlePtr->getZ()+0.1;
00260
00261
00262
00263
00264
00265 quat = tf::createQuaternionFromRPY( locEstimate.position.getR(),locEstimate.position.getP(),locEstimate.position.getH() );
00266 PoseArray_msg_.poses.at(ii).orientation.x = quat.getX();
00267 PoseArray_msg_.poses.at(ii).orientation.y = quat.getY();
00268 PoseArray_msg_.poses.at(ii).orientation.z = quat.getZ();
00269 PoseArray_msg_.poses.at(ii).orientation.w = quat.getW();
00270 }
00271
00272
00273
00274 this->PoseWithCovarianceStamped_msg_.header.seq = pFilter->getIterationId();
00275
00276
00277 this->PoseWithCovarianceStamped_msg_.header.stamp = priorTime;
00278 this->PoseWithCovarianceStamped_msg_.header.frame_id = mapFrame;
00279 this->PoseWithCovarianceStamped_msg_.pose.pose.position.x = locEstimate.position.getX();
00280 this->PoseWithCovarianceStamped_msg_.pose.pose.position.y = locEstimate.position.getY();
00281 this->PoseWithCovarianceStamped_msg_.pose.pose.position.z = locEstimate.position.getZ();
00282
00283 locEstimate.position.getQuaternion(qReal, qi, qj, qk);
00284 this->PoseWithCovarianceStamped_msg_.pose.pose.orientation.x = qi;
00285 this->PoseWithCovarianceStamped_msg_.pose.pose.orientation.y = qj;
00286 this->PoseWithCovarianceStamped_msg_.pose.pose.orientation.z = qk;
00287 this->PoseWithCovarianceStamped_msg_.pose.pose.orientation.w = qReal;
00288
00289
00290
00291
00292
00293
00294
00295 this->PoseWithCovarianceStamped_msg_.pose.covariance[0] = locEstimate.cxx;
00296 this->PoseWithCovarianceStamped_msg_.pose.covariance[1] = locEstimate.cxy;
00297 this->PoseWithCovarianceStamped_msg_.pose.covariance[6] = locEstimate.cxy;
00298 this->PoseWithCovarianceStamped_msg_.pose.covariance[7] = locEstimate.cyy;
00299 this->PoseWithCovarianceStamped_msg_.pose.covariance[14] = locEstimate.czz;
00300 this->PoseWithCovarianceStamped_msg_.pose.covariance[21] = locEstimate.chh;
00301 this->PoseWithCovarianceStamped_msg_.pose.covariance[28] = locEstimate.cpp;
00302 this->PoseWithCovarianceStamped_msg_.pose.covariance[35] = locEstimate.crr;
00303 this->PoseWithCovarianceStamped_msg_.pose.covariance[33] = locEstimate.position.getP();
00304 this->PoseWithCovarianceStamped_msg_.pose.covariance[34] = locEstimate.position.getR();
00305
00306
00307
00308
00309
00310
00311
00312 this->particleSet_publisher_.publish(this->PoseArray_msg_);
00313 this->position_publisher_.publish(this->PoseWithCovarianceStamped_msg_);
00314
00315
00316
00317 tf::Pose mapToBase;
00318 tf::poseMsgToTF(this->PoseWithCovarianceStamped_msg_.pose.pose, mapToBase);
00319 tf::Stamped<tf::Pose> baseToMap(mapToBase.inverse(),ros::Time(0),baseFrame);
00320 tf::Stamped<tf::Pose> odomToMap;
00321 this->tfListener.transformPose(odomFrame, baseToMap, odomToMap);
00322 this->tfBroadcaster.sendTransform(tf::StampedTransform(odomToMap.inverse(),priorTime+transform_tolerance_,mapFrame,odomFrame));
00323
00324
00325
00326 }
00327
00328
00329 void Localization3dAlgNode::platformData_callback(const iri_segway_rmp_msgs::SegwayRMP200Status::ConstPtr& msg)
00330 {
00331
00332
00333
00334
00335 this->platformData_mutex_.enter();
00336
00337
00338
00339 inclinometers.markAsNew();
00340 inclinometers.setTimeStamp();
00341
00342 inclinometers.pitch = msg->pitch_angle;
00343 inclinometers.roll = msg->roll_angle;
00344 inclinometers.setMagneticDistortion();
00345 inclinometers.markAsCorrect();
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 this->platformData_mutex_.exit();
00356
00357
00358 }
00359 void Localization3dAlgNode::platformOdometry_callback(const nav_msgs::Odometry::ConstPtr& msg)
00360 {
00361 double vx,vy,vz,vTrans;
00362 double tLast;
00363
00364
00365
00366
00367
00368 this->platformOdometry_mutex_.enter();
00369
00370
00371 odometry.markAsNew();
00372 tLast = odometry.getTimeStamp();
00373 odometry.setTimeStamp(msg->header.stamp.sec,msg->header.stamp.nsec);
00374
00375
00376 dT = odometry.getTimeStamp() - tLast;
00377
00378 if (fabs(dT)>1)
00379 {
00380 std::cout << "WARNING! Odometry Integration time >1s !" << std::endl;
00381 dT = 0;
00382 }
00383 vx = msg->twist.twist.linear.x;
00384 vy = msg->twist.twist.linear.y;
00385 vz = msg->twist.twist.linear.z;
00386 vTrans = sqrt(vx*vx+vy*vy+vz*vz);
00387 odometry.accumDeltaTrans(dT*vTrans);
00388 odometry.accumDeltaH(dT*msg->twist.twist.angular.z);
00389 odometry.accumDeltaP(dT*msg->twist.twist.angular.y);
00390 odometry.accumDeltaR(dT*msg->twist.twist.angular.x);
00391 odometry.markAsCorrect();
00392
00393 odoTime = msg->header.stamp;
00394
00395
00396
00397
00398 this->platformOdometry_mutex_.exit();
00399
00400
00401 }
00402 void Localization3dAlgNode::laser0_callback(const sensor_msgs::LaserScan::ConstPtr& msg)
00403 {
00404 unsigned int ii;
00405
00406
00407
00408
00409
00410 this->laser_mutex[0].enter();
00411
00412
00413 laserObs[0].markAsNew();
00414 laserObs[0].setTimeStamp(msg->header.stamp.sec,msg->header.stamp.nsec);
00415 laserObs[0].numPoints = msg->ranges.size();
00416 laserObs[0].aperture = fabs(msg->angle_max - msg->angle_min);
00417 laserObs[0].rmin = msg->range_min;
00418 laserObs[0].rmax = msg->range_max;
00419 laserObs[0].sigmaRange = rDevConfig[0].stdDev;
00420 laserObs[0].ranges.clear();
00421 laserObs[0].ranges.resize(laserObs[0].numPoints);
00422 if (msg->angle_min > msg->angle_max)
00423 {
00424
00425 for(ii=0; ii<laserObs[0].numPoints; ii++) laserObs[0].ranges.at(ii) = msg->ranges.at(ii);
00426 }
00427 else
00428 {
00429
00430 for(ii=0; ii<laserObs[0].numPoints; ii++) laserObs[0].ranges.at(ii) = msg->ranges.at(laserObs[0].numPoints-1-ii);
00431 }
00432 laserObs[0].markAsCorrect();
00433
00434
00435
00436
00437 this->laser_mutex[0].exit();
00438
00439
00440 }
00441 void Localization3dAlgNode::laser1_callback(const sensor_msgs::LaserScan::ConstPtr& msg)
00442 {
00443 unsigned int ii;
00444
00445
00446
00447
00448
00449 this->laser_mutex[1].enter();
00450
00451
00452 laserObs[1].markAsNew();
00453 laserObs[1].setTimeStamp(msg->header.stamp.sec,msg->header.stamp.nsec);
00454 laserObs[1].numPoints = msg->ranges.size();
00455 laserObs[1].aperture = fabs(msg->angle_max - msg->angle_min);
00456 laserObs[1].rmin = msg->range_min;
00457 laserObs[1].rmax = msg->range_max;
00458 laserObs[1].sigmaRange = rDevConfig[1].stdDev;
00459 laserObs[1].ranges.clear();
00460 laserObs[1].ranges.resize(laserObs[1].numPoints);
00461 if (msg->angle_min > msg->angle_max)
00462 {
00463
00464 for(ii=0; ii<laserObs[1].numPoints; ii++) laserObs[1].ranges.at(ii) = msg->ranges.at(ii);
00465 }
00466 else
00467 {
00468
00469 for(ii=0; ii<laserObs[1].numPoints; ii++) laserObs[1].ranges.at(ii) = msg->ranges.at(laserObs[1].numPoints-1-ii);
00470 }
00471 laserObs[1].markAsCorrect();
00472
00473
00474
00475
00476 this->laser_mutex[1].exit();
00477
00478
00479 }
00480 void Localization3dAlgNode::laser2_callback(const sensor_msgs::LaserScan::ConstPtr& msg)
00481 {
00482 unsigned int ii;
00483
00484
00485
00486
00487
00488 this->laser_mutex[2].enter();
00489
00490
00491 laserObs[2].markAsNew();
00492 laserObs[2].setTimeStamp(msg->header.stamp.sec,msg->header.stamp.nsec);
00493 laserObs[2].numPoints = msg->ranges.size();
00494 laserObs[2].aperture = fabs(msg->angle_max - msg->angle_min);
00495 laserObs[2].rmin = msg->range_min;
00496 laserObs[2].rmax = msg->range_max;
00497 laserObs[2].sigmaRange = rDevConfig[2].stdDev;
00498 laserObs[2].ranges.clear();
00499 laserObs[2].ranges.resize(laserObs[2].numPoints);
00500 if (msg->angle_min > msg->angle_max)
00501 {
00502
00503 for(ii=0; ii<laserObs[2].numPoints; ii++) laserObs[2].ranges.at(ii) = msg->ranges.at(ii);
00504 }
00505 else
00506 {
00507
00508 for(ii=0; ii<laserObs[2].numPoints; ii++) laserObs[2].ranges.at(ii) = msg->ranges.at(laserObs[2].numPoints-1-ii);
00509 }
00510 laserObs[2].markAsCorrect();
00511
00512
00513
00514
00515 this->laser_mutex[2].exit();
00516
00517
00518 }
00519
00520
00521
00522
00523
00524
00525
00526
00527 void Localization3dAlgNode::node_config_update(Config &config, uint32_t level)
00528 {
00529 config_mutex.enter();
00530 this->public_node_handle_.getParam("num_particles", numberOfParticles);
00531 pFilter->setNumParticles( (unsigned int)numberOfParticles );
00532 config_mutex.exit();
00533 }
00534
00535 void Localization3dAlgNode::addNodeDiagnostics(void)
00536 {
00537 }
00538
00539
00540
00541
00542
00543
00544
00545 int main(int argc,char *argv[])
00546 {
00547
00548
00549
00550 glutInit(&argc, argv);
00551
00552
00553 return algorithm_base::main<Localization3dAlgNode>(argc, argv, "localization3d_alg_node");
00554 }