kalman.cpp
Go to the documentation of this file.
00001 #include "kalman.hpp"
00002 
00003 EKFnode::EKFnode(const ros::NodeHandle& nh, const double & spin_rate, const double & voxel_grid_size_) :
00004     nh_(nh),
00005     nh_priv("~"),
00006     listener(new tf::TransformListener(ros::Duration(10.0))),
00007     map_(new pcl::PointCloud<point_type>()),
00008     laser(new pcl::PointCloud<point_type>()),
00009     voxel_grid_size(voxel_grid_size_),
00010     odom_active_(false),
00011     laser_active_(false),
00012     odom_initialized_(false),
00013     laser_initialized_(false),
00014     first_map_received_(false)
00015 {
00016     nh_priv.param<std::string>("base_frame_id",base_link, "base_link");
00017     nh_priv.param<std::string>("odom_frame_id",odom_link, "odom");
00018     nh_priv.param<std::string>("map_frame_id",map_link, "map");
00019     nh_priv.param<std::string>("laser_frame_id",laser_link, "laser_frame");
00020 
00021     double x_init, y_init, theta_init, initial_cov_xx, initial_cov_yy, initial_cov_aa;
00022     nh_priv.param("initial_pose_x",x_init, 0.0);
00023     nh_priv.param("initial_pose_y",y_init, 0.0);
00024     nh_priv.param("initial_pose_a",theta_init, 0.0);
00025     nh_priv.param("initial_cov_xx",initial_cov_xx, 0.25);
00026     nh_priv.param("initial_cov_yy",initial_cov_yy, 0.25);
00027     nh_priv.param("initial_cov_aa",initial_cov_aa, pow(M_PI/12.0,2));
00028 
00029     nh_priv.param("update_min_d", d_thresh_, 0.2);
00030     nh_priv.param("update_min_a", a_thresh_, M_PI/6.0);
00031 
00032     nh_priv.param("alpha_1",alpha_1, 0.05);
00033     nh_priv.param("alpha_2",alpha_2, 0.001);
00034     nh_priv.param("alpha_3",alpha_3, 5.0);
00035     nh_priv.param("alpha_4",alpha_4, 0.05);
00036 
00037     nh_priv.param("max_correspondence_distance",max_correspondence_distance, 100.0);
00038     nh_priv.param("max_iterations",max_iterations, 1000);
00039     nh_priv.param("ransac_iterations",ransac_iterations, 1000);
00040     nh_priv.param("ransac_outlier_threshold",ransac_outlier_threshold, 0.1);
00041     nh_priv.param("icp_optimization_epsilon",icp_optimization_epsilon, 0.0000001);
00042     nh_priv.param("icp_score_scale",icp_score_scale, 100.0);
00043     nh_priv.param("laser_max_beams",laser_max_beams_, 30);
00044 
00045     nh_priv.param("use_map_topic", use_map_topic_, true);
00046     nh_priv.param("first_map_only", first_map_only_, false);
00047 
00048     nh_priv.param("covariance_marker_scale",covariance_marker_scale_, 3.0);
00049 
00050     ROS_INFO_STREAM("base_frame_id:"<<base_link);
00051     ROS_INFO_STREAM("odom_frame_id:"<<odom_link);
00052     ROS_INFO_STREAM("map_frame_id:"<<map_link);
00053     ROS_INFO_STREAM("laser_frame_id:"<<laser_link);
00054 
00055     ROS_INFO_STREAM("initial_pose_x:"<<x_init);
00056     ROS_INFO_STREAM("initial_pose_y:"<<y_init);
00057     ROS_INFO_STREAM("initial_pose_a:"<<theta_init);
00058 
00059     ROS_INFO_STREAM("initial_cov_xx:"<<initial_cov_xx);
00060     ROS_INFO_STREAM("initial_cov_yy:"<<initial_cov_yy);
00061     ROS_INFO_STREAM("initial_cov_aa:"<<initial_cov_aa);
00062 
00063     ROS_INFO_STREAM("update_min_d:"<<d_thresh_);
00064     ROS_INFO_STREAM("update_min_a:"<<a_thresh_);
00065 
00066     ROS_INFO_STREAM("alpha_1:"<<alpha_1);
00067     ROS_INFO_STREAM("alpha_2:"<<alpha_2);
00068     ROS_INFO_STREAM("alpha_3:"<<alpha_3);
00069     ROS_INFO_STREAM("alpha_4:"<<alpha_4);
00070 
00071     ROS_INFO_STREAM("max_correspondence_distance:"<<max_correspondence_distance);
00072     ROS_INFO_STREAM("max_iterations:"<<max_iterations);
00073     ROS_INFO_STREAM("ransac_iterations:"<<ransac_iterations);
00074     ROS_INFO_STREAM("ransac_outlier_threshold:"<<ransac_outlier_threshold);
00075     ROS_INFO_STREAM("icp_optimization_epsilon:"<<icp_optimization_epsilon);
00076     ROS_INFO_STREAM("icp_score_scale:"<<icp_score_scale);
00077     ROS_INFO_STREAM("laser_max_beams:"<<laser_max_beams_);
00078 
00079     ROS_INFO_STREAM("covariance_marker_scale:"<<covariance_marker_scale_);
00080 
00081 
00082     alpha_2=alpha_2*180/M_PI; // Convert to radian
00083     alpha_3=alpha_3*M_PI/180; // Convert to radians
00084 
00085 
00086     /****************************
00087      * NonLinear system model   *
00088      ***************************/
00089     // create gaussian
00090     BFL::ColumnVector sys_noise_mu(3);
00091     sys_noise_mu(1) = 0.0;
00092     sys_noise_mu(2) = 0.0;
00093     sys_noise_mu(3) = 0.0;
00094 
00095     BFL::SymmetricMatrix sys_noise_cov(3);
00096     sys_noise_cov = 0.0;
00097     sys_noise_cov(1,1) = 1.0;
00098     sys_noise_cov(2,2) = 1.0;
00099     sys_noise_cov(3,3) = 1.0;
00100 
00101     BFL::Gaussian system_uncertainty(sys_noise_mu, sys_noise_cov);
00102     sys_pdf = boost::shared_ptr<BFL::NonLinearAnalyticConditionalGaussianMobile> (new  BFL::NonLinearAnalyticConditionalGaussianMobile(system_uncertainty));
00103     sys_model = boost::shared_ptr<BFL::AnalyticSystemModelGaussianUncertainty> (new BFL::AnalyticSystemModelGaussianUncertainty (sys_pdf.get()));
00104 
00105     /*********************************
00106      * Initialise measurement model *
00107      ********************************/
00108 
00109     // create matrix H for linear measurement model
00110     BFL::Matrix H(3,3);
00111     H = 0.0;
00112     H(1,1) = 1.0;
00113     H(2,2) = 1.0;
00114     H(3,3) = 1.0;
00115 
00116     // Construct the measurement noise (a scalar in this case)
00117     BFL::ColumnVector measNoise_Mu(3);
00118     measNoise_Mu = 0.0;
00119 
00120     BFL::SymmetricMatrix measNoise_Cov(3);
00121     measNoise_Cov(1,1) = 1.0;
00122     measNoise_Cov(2,2) = 1.0;
00123     measNoise_Cov(3,3) = 1.0;
00124 
00125     BFL::Gaussian measurement_uncertainty(measNoise_Mu, measNoise_Cov);
00126 
00127     // create the model
00128     meas_pdf=boost::shared_ptr<BFL::LinearAnalyticConditionalGaussian> (new BFL::LinearAnalyticConditionalGaussian(H, measurement_uncertainty));
00129     meas_model=boost::shared_ptr<BFL::LinearAnalyticMeasurementModelGaussianUncertainty> (new BFL::LinearAnalyticMeasurementModelGaussianUncertainty(meas_pdf.get()));
00130 
00131 
00132     /****************************
00133      * Linear prior DENSITY     *
00134      ***************************/
00135     // Continuous Gaussian prior (for Kalman filters)
00136     BFL::ColumnVector prior_mu(3);
00137     prior_mu(1) = x_init;
00138     prior_mu(2) = y_init;
00139     prior_mu(2) = theta_init;
00140     BFL::SymmetricMatrix prior_cov(3);
00141     prior_cov=0.0;
00142     prior_cov(1,1) = initial_cov_xx;
00143     prior_cov(2,2) = initial_cov_yy;
00144     prior_cov(3,3) = initial_cov_aa;
00145     BFL::Gaussian prior(prior_mu,prior_cov);
00146 
00147 
00148     /******************************
00149      * Construction of the Filter *
00150      ******************************/
00151     filter=boost::shared_ptr<BFL::ExtendedKalmanFilter> (new BFL::ExtendedKalmanFilter(&prior));
00152 
00153 
00154     if(use_map_topic_)
00155     {
00156         map_sub_ = nh_.subscribe("map", 1, &EKFnode::mapReceived, this);
00157         ROS_INFO("Subscribed to map topic.");
00158     } else
00159     {
00160         requestMap();
00161     }
00162     timer_ = nh_.createTimer(ros::Duration(1.0/std::max(spin_rate,1.0)), &EKFnode::spin, this);
00163 
00164     laser_sub = nh_.subscribe("scan", 1, &EKFnode::laser_callback, this);
00165     location_undertainty = nh_.advertise<visualization_msgs::Marker>("/location_undertainty",1);
00166     map_pub_ = nh_.advertise<sensor_msgs::PointCloud2>("/map_",1);
00167     local_features_pub = nh_.advertise<sensor_msgs::PointCloud2>("/laser_aligned",1);
00168 }
00169 
00170 
00171 void EKFnode::laser_callback(const sensor_msgs::LaserScan::ConstPtr& msg)
00172 {
00173     if (!laser_active_)
00174     {
00175         if (!laser_initialized_)
00176         {
00177             laser_initialized_ = true;
00178             laser_last_stamp_ = msg->header.stamp;
00179             laser_init_stamp_ = msg->header.stamp;
00180             ROS_INFO("Initializing Laser sensor");
00181 
00182         }
00183         if ( filter_stamp_ >= laser_init_stamp_)
00184         {
00185             laser_active_ = true;
00186             laser_initialized_ = false;
00187             ROS_INFO("Laser sensor activated");
00188             return;
00189         }
00190         else
00191         {
00192             ROS_ERROR("Waiting to activate Laser, because Laser measurements are still %f sec in the future.",
00193                       (laser_init_stamp_ - filter_stamp_).toSec());
00194             return;
00195         }
00196     }
00197 
00198     tf::StampedTransform laserToBaseTf;
00199     tf::StampedTransform baseDeltaTf;
00200 
00201     try
00202     {
00203         listener->waitForTransform(map_link, laser_link, msg->header.stamp, ros::Duration(0.1) );
00204         listener->waitForTransform(map_link, laser_link, msg->header.stamp+ros::Duration().fromSec((msg->ranges.size()-1)*msg->time_increment), ros::Duration(0.1) );
00205         listener->lookupTransform(map_link, laser_link,  msg->header.stamp,  laserToBaseTf); // delta position
00206         listener->lookupTransform(map_link, laser_link,  msg->header.stamp+ros::Duration().fromSec((msg->ranges.size()-1)*msg->time_increment),  laserToBaseTf); // delta position
00207 
00208         listener->waitForTransform(base_link, laser_last_stamp_, base_link, msg->header.stamp , odom_link, ros::Duration(0.1) );
00209         listener->lookupTransform(base_link, laser_last_stamp_, base_link, msg->header.stamp, odom_link, baseDeltaTf); // delta position
00210     }
00211     catch(tf::TransformException& ex)
00212     {
00213         laser_last_stamp_=msg->header.stamp;
00214         ROS_WARN("%s",ex.what());
00215         return;
00216     }
00217 
00218     // If the robot has moved, update the filter
00219 
00220     double dx=baseDeltaTf.getOrigin().getX();
00221     double dy=baseDeltaTf.getOrigin().getY();
00222     double d_theta=baseDeltaTf.getRotation().getAxis()[2]*baseDeltaTf.getRotation().getAngle();
00223 
00224     // See if we should update the filter
00225     if(!(fabs(dx) > d_thresh_ || fabs(dy) > d_thresh_ || fabs(d_theta) > a_thresh_))
00226     {
00227         return;
00228     }
00229 
00230     // Transform to sensor_msgs::PointCloud
00231     sensor_msgs::PointCloud2 cloud_msg;
00232     projector_.transformLaserScanToPointCloud(map_link,*msg,
00233                                               cloud_msg,*listener);
00234 
00235     // Transform to pcl
00236     pcl::PCLPointCloud2 pcl_pc;
00237 
00238     pcl_conversions::toPCL(cloud_msg,pcl_pc);
00239     pcl::fromPCLPointCloud2(pcl_pc, *laser);
00240 
00241     // Remove NAN
00242     pcl::PointIndices::Ptr inliers (new pcl::PointIndices ());
00243     pcl::removeNaNFromPointCloud((*laser), *laser,inliers->indices);
00244     pcl::PointIndices::Ptr toProcessIndices (new pcl::PointIndices ());
00245 
00246     int step = (laser->size() - 1) / (laser_max_beams_ - 1);
00247     for (int i = 0; i < laser->size(); i += step)
00248     {
00249         toProcessIndices->indices.push_back(i);
00250     }
00251 
00252     pcl_conversions::toPCL(msg->header.stamp, map_->header.stamp);
00253 
00254     // Compute ICP
00255     pcl::IterativeClosestPoint<point_type, point_type> icp;
00256     icp.setInputSource(laser);
00257     icp.setIndices(toProcessIndices);
00258     icp.setInputTarget(map_);
00259     icp.setTransformationEpsilon (icp_optimization_epsilon);
00260     icp.setMaxCorrespondenceDistance(max_correspondence_distance); //10
00261 
00262     icp.setMaximumIterations(max_iterations); //200
00263     icp.setRANSACIterations (ransac_iterations);
00264     icp.setRANSACOutlierRejectionThreshold(ransac_outlier_threshold);
00265     pcl::PointCloud<point_type> Final;
00266     icp.align(Final);
00267 
00268     Final.header.frame_id=map_link;
00269     pcl_conversions::toPCL(filter_stamp_, Final.header.stamp);
00270 
00271     if(icp.hasConverged())
00272     {
00273 
00274         Eigen::Matrix4f correction_transform_=icp.getFinalTransformation();
00275 
00276         BFL::ColumnVector observation_mean(3);
00277         BFL::Pdf<BFL::ColumnVector> * posterior = filter->PostGet();
00278         double angle=correction_transform_.block<3,3>(0,0).eulerAngles (0,1,2)(2)+posterior->ExpectedValueGet()(3);
00279         angleOverflowCorrect(angle);
00280         observation_mean(1)=correction_transform_(0,3)+posterior->ExpectedValueGet()(1);
00281         observation_mean(2)=correction_transform_(1,3)+posterior->ExpectedValueGet()(2);
00282         observation_mean(3)=angle;
00283         BFL::SymmetricMatrix observation_noise(3);
00284         double icp_fitness_score=icp.getFitnessScore(max_correspondence_distance);
00285         observation_noise=0.0;
00286         observation_noise(1,1) = icp_score_scale*icp_fitness_score;
00287         observation_noise(2,2) = icp_score_scale*icp_fitness_score;
00288         observation_noise(3,3) = icp_score_scale*icp_fitness_score;
00289 
00290         meas_pdf->AdditiveNoiseSigmaSet(observation_noise);
00291         filter->Update(meas_model.get(),observation_mean);
00292 
00293         if(filter->PostGet()->ExpectedValueGet()(3)>M_PI || filter->PostGet()->ExpectedValueGet()(3)<-M_PI)
00294         {
00295             std::cout << filter->PostGet()->ExpectedValueGet()(3) << std::endl;
00296             exit(-1);
00297         }
00298         broadcast(msg->header.stamp);
00299 
00300         laser_last_stamp_=msg->header.stamp;
00301         local_features_pub.publish(Final);
00302     }
00303     else
00304     {
00305         ROS_ERROR("ICP DID NOT CONVERGE");
00306     }
00307 
00308     return;
00309 }
00310 
00311 
00312 bool EKFnode::predict()
00313 {
00314     ros::Time odom_time=ros::Time::now();
00315 
00316 
00317     if (!odom_active_)
00318     {
00319         if (!odom_initialized_)
00320         {
00321             odom_initialized_ = true;
00322             odom_last_stamp_ = odom_time;
00323             odom_init_stamp_ = odom_time;
00324             ROS_INFO("Initializing Odom sensor");
00325 
00326         }
00327         if ( filter_stamp_ >= odom_init_stamp_)
00328         {
00329             odom_active_ = true;
00330             odom_initialized_ = false;
00331             ROS_INFO("Odom sensor activated");
00332             return true;
00333         }
00334         else
00335         {
00336             ROS_ERROR("Waiting to activate Odom, because odom measurements are still %f sec in the future.",
00337                       (odom_init_stamp_ - filter_stamp_).toSec());
00338             return false;
00339         }
00340     }
00341 
00342     tf::StampedTransform baseDeltaTf;
00343 
00344     // Get odom delta motion in cartesian coordinates with TF
00345     try
00346     {
00347         listener->waitForTransform(base_link, odom_last_stamp_, base_link, odom_time , odom_link, ros::Duration(0.5) );
00348         listener->lookupTransform(base_link, odom_last_stamp_, base_link, odom_time, odom_link, baseDeltaTf); // delta position
00349 
00350     }
00351     catch (tf::TransformException &ex)
00352     {
00353         //odom_initialized_=false;
00354 
00355         ROS_WARN("%s",ex.what());
00356         return false;
00357     }
00358 
00359     // Get control input
00360     double dx=baseDeltaTf.getOrigin().getX();
00361     double dy=baseDeltaTf.getOrigin().getY();
00362     double d_theta=baseDeltaTf.getRotation().getAxis()[2]*baseDeltaTf.getRotation().getAngle();
00363 
00364     double delta_rot1=atan2(dy,dx);
00365     double delta_trans=sqrt(dx*dx+dy*dy);
00366     double delta_rot2=d_theta-delta_rot1;
00367 
00368     double var_rot1=alpha_1*delta_rot1*delta_rot1+alpha_2*delta_trans*delta_trans;
00369     double var_trans=alpha_3*delta_trans*delta_trans+alpha_4*(delta_rot1*delta_rot1+delta_rot2*delta_rot2);
00370     double var_rot2=alpha_1*delta_rot2*delta_rot2+alpha_2*delta_trans*delta_trans;
00371 
00372     BFL::ColumnVector control_mean(3);
00373     control_mean(1)=delta_rot1;
00374     control_mean(2)=delta_trans;
00375     control_mean(3)=delta_rot2;
00376 
00377     BFL::Matrix control_noise(3,3);
00378     control_noise=0.0;
00379     control_noise(1,1) = var_rot1;
00380     control_noise(2,2) = var_trans;
00381     control_noise(3,3) = var_rot2;
00382 
00383     // Linearize control noise
00384     BFL::Matrix J(3,3);
00385     J(1,1)=-sin(filter->PostGet()->ExpectedValueGet()(3)+delta_rot1)*delta_trans;
00386     J(1,2)=cos(filter->PostGet()->ExpectedValueGet()(3)+delta_rot1);
00387     J(2,2)=0;
00388 
00389     J(2,1)=cos(filter->PostGet()->ExpectedValueGet()(3)+delta_rot1)*delta_trans;
00390     J(2,2)=sin(filter->PostGet()->ExpectedValueGet()(3)+delta_rot1);
00391     J(2,3)=0;
00392 
00393     J(3,1)=1;
00394     J(3,2)=0;
00395     J(3,3)=1;
00396 
00397     BFL::SymmetricMatrix R(J*control_noise*J.transpose());
00398 
00399     sys_pdf->AdditiveNoiseSigmaSet(R);
00400     filter->Update(sys_model.get(),control_mean);
00401     if(filter->PostGet()->ExpectedValueGet()(3)>M_PI || filter->PostGet()->ExpectedValueGet()(3)<-M_PI)
00402     {
00403         std::cout << filter->PostGet()->ExpectedValueGet()(3) << std::endl;
00404         exit(-1);
00405     }
00406     broadcast(odom_time);
00407 
00408     // Update filter stamp
00409 
00410 
00411 
00412     odom_last_stamp_=odom_time;
00413     return true;
00414 }
00415 
00416 
00417 
00418 
00419 void EKFnode::broadcast(const ros::Time & broad_cast_time)
00420 {
00421     BFL::Pdf<BFL::ColumnVector> * posterior = filter->PostGet();
00422 
00423     BFL::ColumnVector estimated_mean=posterior->ExpectedValueGet();
00424 
00425     BFL::SymmetricMatrix estimated_cov=posterior->CovarianceGet();
00426 
00427     tf::Stamped<tf::Pose> odom_to_map;
00428     try
00429     {
00430         tf::Transform tmp_tf(tf::createQuaternionFromYaw(estimated_mean(3)),
00431                              tf::Vector3(estimated_mean(1),
00432                                          estimated_mean(2),
00433                                          0.0));
00434         tf::Stamped<tf::Pose> tmp_tf_stamped (tmp_tf.inverse(),
00435                                               broad_cast_time,
00436                                               base_link); // base to map
00437         listener->transformPose(odom_link,
00438                                 tmp_tf_stamped,
00439                                 odom_to_map);
00440     }
00441     catch(tf::TransformException)
00442     {
00443         ROS_DEBUG("Failed to subtract base to odom transform");
00444         return;
00445     }
00446 
00447     tf::Transform latest_tf_ = tf::Transform(tf::Quaternion(odom_to_map.getRotation()),
00448                                              tf::Point(odom_to_map.getOrigin()));
00449 
00450     // We want to send a transform that is good up until a
00451     // tolerance time so that odom can be used
00452     tf::StampedTransform tmp_tf_stamped(latest_tf_.inverse(),
00453                                         broad_cast_time+ros::Duration(0.1),
00454                                         map_link, odom_link);
00455     tf_broadcaster.sendTransform(tmp_tf_stamped);
00456 
00457     filter_stamp_=broad_cast_time;
00458 }
00459 
00460 void EKFnode::drawCovariance(const Eigen::Matrix2f& covMatrix)
00461 {
00462     visualization_msgs::Marker tempMarker;
00463     tempMarker.pose.position.x = 0;
00464     tempMarker.pose.position.y = 0;
00465 
00466     Eigen::SelfAdjointEigenSolver<Eigen::Matrix2f> eig(covMatrix);
00467 
00468     const Eigen::Vector2f& eigValues (eig.eigenvalues());
00469     const Eigen::Matrix2f& eigVectors (eig.eigenvectors());
00470 
00471     float angle = (atan2(eigVectors(1, 0), eigVectors(0, 0)));
00472 
00473 
00474     tempMarker.type = visualization_msgs::Marker::SPHERE;
00475 
00476     double lengthMajor = sqrt(eigValues[0]);
00477     double lengthMinor = sqrt(eigValues[1]);
00478 
00479     tempMarker.scale.x = covariance_marker_scale_*lengthMajor;
00480     tempMarker.scale.y = covariance_marker_scale_*lengthMinor;
00481     tempMarker.scale.z = 0.001;
00482 
00483     tempMarker.color.a = 1.0;
00484     tempMarker.color.r = 1.0;
00485 
00486     tempMarker.pose.orientation.w = cos(angle*0.5);
00487     tempMarker.pose.orientation.z = sin(angle*0.5);
00488 
00489     tempMarker.header.frame_id=base_link;
00490     tempMarker.id = 0;
00491 
00492     location_undertainty.publish(tempMarker);
00493 }
00494 
00495 
00496 void EKFnode::mapReceived(const nav_msgs::OccupancyGridConstPtr& msg)
00497 {
00498     if( first_map_only_ && first_map_received_ )
00499     {
00500         return;
00501     }
00502 
00503     handleMapMessage( *msg );
00504 
00505     first_map_received_ = true;
00506 }
00507 
00508 void EKFnode::handleMapMessage(const nav_msgs::OccupancyGrid& msg)
00509 {
00510     ROS_INFO("Received a %d X %d map @ %.3f m/pix\n",
00511              msg.info.width,
00512              msg.info.height,
00513              msg.info.resolution);
00514     convertMap(msg);
00515 }
00516 
00517 void EKFnode::requestMap()
00518 {
00519     //boost::recursive_mutex::scoped_lock ml(configuration_mutex_);
00520 
00521     // get map via RPC
00522     nav_msgs::GetMap::Request  req;
00523     nav_msgs::GetMap::Response resp;
00524     ROS_INFO("Requesting the map...");
00525     while(!ros::service::call("static_map", req, resp)&&nh_priv.ok())
00526     {
00527         ROS_WARN("Request for map failed; trying again...");
00528         ros::Duration d(0.5);
00529         d.sleep();
00530     }
00531     handleMapMessage( resp.map );
00532 }
00533 
00534 void EKFnode::convertMap( const nav_msgs::OccupancyGrid& map_msg)
00535 {
00536     map_=map_t_ptr (new map_t());
00537     ROS_ASSERT(map_);
00538     map_->is_dense=false;
00539     map_->header.frame_id=map_msg.header.frame_id;
00540     double map_size_x = map_msg.info.width;
00541     double map_size_y = map_msg.info.height;
00542     double map_scale = map_msg.info.resolution;
00543     //    double map_origin_x = map_msg.info.origin.position.x + (map_size_x / 2.0) * map_scale;
00544     //    double map_origin_y = map_msg.info.origin.position.y + (map_size_y / 2.0) * map_scale;
00545 
00546     // Convert to player format
00547     for(int i=0;i<map_size_x; ++i) //Cols
00548     {
00549         for(int j=0;j<map_size_y; ++j) //Rows
00550         {
00551             if(map_msg.data[i+j*map_size_x] > 0.0)
00552             {
00553                 point_type point;
00554                 point.x=map_scale*i+map_msg.info.origin.position.x;
00555                 point.y=map_scale*j+map_msg.info.origin.position.y;
00556                 point.z=0.0;
00557                 //point.intensity=1.0;
00558                 map_->push_back(point);
00559             }
00560         }
00561     }
00562 
00563     pcl::VoxelGrid<point_type> voxel_grid;
00564     voxel_grid.setLeafSize (voxel_grid_size, voxel_grid_size, voxel_grid_size);
00565     voxel_grid.setInputCloud (map_);
00566     voxel_grid.filter (*map_);
00567 
00568 }
00569 
00570 
00571 
00572 void EKFnode::spin(const ros::TimerEvent& e)
00573 {
00574 
00575     // initial value for filter stamp; keep this stamp when no sensors are active
00576     filter_stamp_ = ros::Time::now();
00577 
00578     predict();
00579 
00580     // Check callbacks
00581     ros::spinOnce();
00582 
00583     // only update filter when one of the sensors is active
00584     if (odom_active_ || laser_active_)
00585     {
00586         if (odom_active_)  filter_stamp_ = std::min(filter_stamp_, odom_last_stamp_);
00587         if (laser_active_)   filter_stamp_ = std::min(filter_stamp_, laser_last_stamp_);
00588 
00589         // Publish stuff
00590         Eigen::Matrix2f covMatrix;
00591         BFL::Pdf<BFL::ColumnVector> * posterior = filter->PostGet();
00592         BFL::SymmetricMatrix estimated_cov=posterior->CovarianceGet();
00593 
00594         covMatrix(0,0)=estimated_cov(1,1);
00595         covMatrix(0,1)=estimated_cov(1,2);
00596 
00597         covMatrix(1,0)=estimated_cov(2,1);
00598         covMatrix(1,1)=estimated_cov(2,2);
00599         drawCovariance(covMatrix);
00600 
00601         publishFeatures();
00602     }
00603 }


ekf_localization
Author(s):
autogenerated on Sat Jun 8 2019 20:11:55