mrpt_rbpf_slam_wrapper.cpp
Go to the documentation of this file.
2 #include <mrpt/maps/CBeaconMap.h>
3 #include <mrpt/maps/COccupancyGridMap2D.h>
7 
8 namespace {
9 bool isFileExists(const std::string &name) {
10  std::ifstream f(name.c_str());
11  return f.good();
12 }
13 } // namespace
14 
15 namespace mrpt_rbpf_slam {
18 }
19 
21  ROS_INFO("READ PARAM FROM LAUNCH FILE");
22  nh_p.param<double>("rawlog_play_delay", rawlog_play_delay_, 0.1);
23  ROS_INFO("rawlog_play_delay: %f", rawlog_play_delay_);
24 
25  nh_p.getParam("rawlog_filename", rawlog_filename_);
26  ROS_INFO("rawlog_filename: %s", rawlog_filename_.c_str());
27 
28  nh_p.getParam("ini_filename", ini_filename_);
29  ROS_INFO("ini_filename: %s", ini_filename_.c_str());
30 
31  nh_p.param<std::string>("global_frame_id", global_frame_id_, "map");
32  ROS_INFO("global_frame_id: %s", global_frame_id_.c_str());
33 
34  nh_p.param<std::string>("odom_frame_id", odom_frame_id_, "odom");
35  ROS_INFO("odom_frame_id: %s", odom_frame_id_.c_str());
36 
37  nh_p.param<std::string>("base_frame_id", base_frame_id_, "base_link");
38  ROS_INFO("base_frame_id: %s", base_frame_id_.c_str());
39 
40  nh_p.param<std::string>("sensor_source", sensor_source_, "scan");
41  ROS_INFO("sensor_source: %s", sensor_source_.c_str());
42 
43  nh_p.param<std::string>("sensor_source", sensor_source_, "scan");
44  ROS_INFO("sensor_source: %s", sensor_source_.c_str());
45 
46  nh_p.param<bool>("update_sensor_pose", update_sensor_pose_, true);
47  ROS_INFO("update_sensor_pose: %s", (update_sensor_pose_?"TRUE":"FALSE"));
48 
49 
51  if (!loadOptions(nh_p, options)) {
52  ROS_ERROR("Not able to read all parameters!");
53  return false;
54  }
55  initSlam(std::move(options));
56  return true;
57 }
58 
60  // get parameters from ini file
61  if (!isFileExists(ini_filename_)) {
62  ROS_ERROR_STREAM("CAN'T READ INI FILE" << ini_filename_);
63  return false;
64  }
65 
67 
68  // read rawlog file if it exists
69  if (isFileExists(rawlog_filename_)) {
70  ROS_WARN_STREAM("PLAY FROM RAWLOG FILE: " << rawlog_filename_);
72  rawlog_play_ = true;
73  }
74 
76  // publish grid map
77  pub_map_ = nh.advertise<nav_msgs::OccupancyGrid>("map", 1, true);
78  pub_metadata_ = nh.advertise<nav_msgs::MapMetaData>("map_metadata", 1, true);
79  // robot pose
81  nh.advertise<geometry_msgs::PoseArray>("particlecloud", 1, true);
82  // ro particles poses
84  nh.advertise<geometry_msgs::PoseArray>("particlecloud_beacons", 1, true);
86  nh.advertise<visualization_msgs::MarkerArray>("/beacons_viz", 1);
87 
88  // read sensor topics
89  std::vector<std::string> lstSources;
90  mrpt::system::tokenize(sensor_source_, " ,\t\n", lstSources);
91  ROS_ASSERT_MSG(!lstSources.empty(),
92  "*Fatal*: At least one sensor source must be provided in "
93  "~sensor_sources (e.g. "
94  "\"scan\" or \"beacon\")");
95 
97  sensorSub_.resize(lstSources.size());
98  for (size_t i = 0; i < lstSources.size(); i++) {
99  if (lstSources[i].find("scan") != std::string::npos) {
100  sensorSub_[i] =
101  nh.subscribe(lstSources[i], 1, &PFslamWrapper::laserCallback, this);
102  } else {
103  sensorSub_[i] =
104  nh.subscribe(lstSources[i], 1, &PFslamWrapper::callbackBeacon, this);
105  }
106  }
107 
109  init3Dwindow();
110  return true;
111 }
112 
114  mrpt::obs::CObservationOdometry::Ptr &odometry,
115  const std_msgs::Header &_msg_header) {
116  mrpt::poses::CPose3D poseOdom;
117  if (this->waitForTransform(poseOdom, odom_frame_id_, base_frame_id_,
118  _msg_header.stamp, ros::Duration(1))) {
119  odometry = mrpt::obs::CObservationOdometry::Create();
120  odometry->sensorLabel = odom_frame_id_;
121  odometry->hasEncodersInfo = false;
122  odometry->hasVelocities = false;
123  odometry->odometry.x() = poseOdom.x();
124  odometry->odometry.y() = poseOdom.y();
125  odometry->odometry.phi() = poseOdom.yaw();
126  }
127 }
128 
130  mrpt::poses::CPose3D &des, const std::string &target_frame,
131  const std::string &source_frame, const ros::Time &time,
132  const ros::Duration &timeout, const ros::Duration &polling_sleep_duration) {
134  try {
135  listenerTF_.waitForTransform(target_frame, source_frame, time, timeout,
136  polling_sleep_duration);
137  listenerTF_.lookupTransform(target_frame, source_frame, time, transform);
138  } catch (tf::TransformException ex) {
139  ROS_ERROR("Failed to get transform target_frame (%s) to source_frame (%s). "
140  "TransformException: %s",
141  target_frame.c_str(), source_frame.c_str(), ex.what());
142  return false;
143  }
144  mrpt_bridge::convert(transform, des);
145  return true;
146 }
147 
149  using namespace mrpt::maps;
150  using namespace mrpt::obs;
151  CObservation2DRangeScan::Ptr laser = CObservation2DRangeScan::Create();
152 
153 
154  if (laser_poses_.find(msg.header.frame_id) == laser_poses_.end()) {
155  // check if the tf to establish the sensor pose
156  updateSensorPose(msg.header.frame_id);
157  } else {
158  // update sensor pose
159  if(update_sensor_pose_) updateSensorPose(msg.header.frame_id);
160  mrpt::poses::CPose3D pose = laser_poses_[msg.header.frame_id];
161  mrpt_bridge::convert(msg, laser_poses_[msg.header.frame_id], *laser);
162 
163  sensory_frame_ = CSensoryFrame::Create();
164  CObservationOdometry::Ptr odometry;
165  odometryForCallback(odometry, msg.header);
166 
167  CObservation::Ptr obs = CObservation::Ptr(laser);
168  sensory_frame_->insert(obs);
169  observation(sensory_frame_, odometry);
170  timeLastUpdate_ = sensory_frame_->getObservationByIndex(0)->timestamp;
171 
172  tictac_.Tic();
174  t_exec_ = tictac_.Tac();
175  ROS_INFO("Map building executed in %.03fms", 1000.0f * t_exec_);
176  publishMapPose();
177  run3Dwindow();
178  publishTF();
179  }
180 }
181 
184  using namespace mrpt::maps;
185  using namespace mrpt::obs;
186 
187  CObservationBeaconRanges::Ptr beacon = CObservationBeaconRanges::Create();
188 
189  if (beacon_poses_.find(msg.header.frame_id) == beacon_poses_.end()) {
190  // check if the tf to establish the sensor pose
191  updateSensorPose(msg.header.frame_id);
192  } else {
193  // update sensor pose
194  if(update_sensor_pose_) updateSensorPose(msg.header.frame_id);
195 
196  mrpt_bridge::convert(msg, beacon_poses_[msg.header.frame_id], *beacon);
197 
198  sensory_frame_ = CSensoryFrame::Create();
199  CObservationOdometry::Ptr odometry;
200  odometryForCallback(odometry, msg.header);
201 
202  CObservation::Ptr obs = CObservation::Ptr(beacon);
203  sensory_frame_->insert(obs);
204  observation(sensory_frame_, odometry);
205  timeLastUpdate_ = sensory_frame_->getObservationByIndex(0)->timestamp;
206 
207  tictac_.Tic();
209  t_exec_ = tictac_.Tac();
210  ROS_INFO("Map building executed in %.03fms", 1000.0f * t_exec_);
211 
212  publishMapPose();
213  run3Dwindow();
214  }
215 }
216 
218  // if I received new grid maps from 2D laser scan sensors
221  // publish map
222 
223  COccupancyGridMap2D *grid = nullptr;
224  CBeaconMap *bm = nullptr;
225 #if MRPT_VERSION >= 0x199
226  if (metric_map_->countMapsByClass<COccupancyGridMap2D>())
227  grid = metric_map_->mapByClass<COccupancyGridMap2D>().get();
228  bm = metric_map_->mapByClass<CBeaconMap>().get();
229 #else
230  if (metric_map_->m_gridMaps.size())
231  grid = metric_map_->m_gridMaps[0].get();
232  bm = metric_map_->getMapByClass<CBeaconMap>().get();
233 #endif
234 
235  if (grid) {
236  // publish map
238  mrpt_bridge::convert(*grid, msg);
239  pub_map_.publish(msg);
240  pub_metadata_.publish(msg.info);
241  }
242 
243  // if I received new beacon (range only) map
244  if (bm) {
245  mrpt::opengl::CSetOfObjects::Ptr objs;
246 
247  objs = mrpt::opengl::CSetOfObjects::Create();
248  // Get th map as the set of 3D objects
249  bm->getAs3DObject(objs);
250 
251  geometry_msgs::PoseArray poseArrayBeacons;
252  poseArrayBeacons.header.frame_id = global_frame_id_;
253  poseArrayBeacons.header.stamp = ros::Time::now();
254 
255  // Count the number of beacons
256  unsigned int objs_counter = 0;
257  while (objs->getByClass<mrpt::opengl::CEllipsoid>(objs_counter)) {
258  objs_counter++;
259  }
260  poseArrayBeacons.poses.resize(objs_counter);
261  mrpt::opengl::CEllipsoid::Ptr beacon_particle;
262 
263  for (size_t i = 0; i < objs_counter; i++) {
264  beacon_particle = objs->getByClass<mrpt::opengl::CEllipsoid>(i);
265  mrpt_bridge::convert(mrpt::poses::CPose3D(beacon_particle->getPose()),
266  poseArrayBeacons.poses[i]);
267  viz_beacons_.push_back(beacon_particle);
268  }
269  pub_particles_beacons_.publish(poseArrayBeacons);
270  vizBeacons();
271  viz_beacons_.clear();
272  }
273 
274  // publish pose
275  geometry_msgs::PoseArray poseArray;
276  poseArray.header.frame_id = global_frame_id_;
277  poseArray.header.stamp = ros::Time::now();
278  poseArray.poses.resize(curPDF.particlesCount());
279  for (size_t i = 0; i < curPDF.particlesCount(); i++) {
280  const auto p = mrpt::poses::CPose3D(curPDF.getParticlePose(i));
281  mrpt_bridge::convert(p, poseArray.poses[i]);
282  }
283 
284  pub_particles_.publish(poseArray);
285 }
286 
288  if (viz_beacons_.size() == 0) {
289  return;
290  }
291  visualization_msgs::MarkerArray ma;
292  visualization_msgs::Marker marker;
293 
294  marker.header.frame_id = "/map";
295 
296  marker.id = 0;
297  marker.type = visualization_msgs::Marker::SPHERE;
298  marker.action = visualization_msgs::Marker::ADD;
299  marker.lifetime = ros::Duration(1);
300  marker.pose.position.x = 0;
301  marker.pose.position.y = 0;
302  marker.pose.position.z = 0;
303  marker.pose.orientation.x = 0.0;
304  marker.pose.orientation.y = 0.0;
305  marker.pose.orientation.z = 0.0;
306  marker.pose.orientation.w = 1.0;
307  marker.scale.x = 0.12;
308  marker.scale.y = 0.12;
309  marker.scale.z = 0.12;
310  marker.color.a = 1.0;
311  marker.color.r = 1.0;
312  marker.color.g = 0.0;
313 
314  for (unsigned int i = 0; i < viz_beacons_.size(); i++) {
315  mrpt::poses::CPose3D meanPose(viz_beacons_[i]->getPose());
316  marker.type = visualization_msgs::Marker::SPHERE;
317 
318  marker.pose.position.x = meanPose.x();
319  marker.pose.position.y = meanPose.y();
320  marker.pose.position.z = meanPose.z();
321  marker.color.r = 1.0;
322  marker.color.g = 0.0;
323  marker.color.b = 0.0;
324 
325  ma.markers.push_back(marker);
326  marker.id++;
327 
328  marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
329  marker.text = std::to_string(i);
330 
331  marker.pose.position.x = meanPose.x();
332  marker.pose.position.y = meanPose.y();
333  marker.pose.position.z = meanPose.z() + 0.12;
334  marker.color.r = 1.0;
335  marker.color.g = 1.0;
336  marker.color.b = 1.0;
337  // marker.scale.z = 1;
338  ma.markers.push_back(marker);
339  marker.id++;
340  }
341 
343 }
344 
345 void PFslamWrapper::updateSensorPose(const std::string &frame_id) {
348  try {
350  transform);
351 
352  tf::Vector3 translation = transform.getOrigin();
353  tf::Quaternion quat = transform.getRotation();
354  pose.x() = translation.x();
355  pose.y() = translation.y();
356  pose.z() = translation.z();
357  tf::Matrix3x3 Rsrc(quat);
359  for (int c = 0; c < 3; c++)
360  for (int r = 0; r < 3; r++)
361  Rdes(r, c) = Rsrc.getRow(r)[c];
362  pose.setRotationMatrix(Rdes);
363  laser_poses_[frame_id] = pose;
364  beacon_poses_[frame_id] = pose;
365  } catch (tf::TransformException ex) {
366  ROS_ERROR("%s", ex.what());
367  ros::Duration(1.0).sleep();
368  }
369 }
370 
372  if (rawlog_play_ == false) {
373  return false;
374  } else {
375  for (unsigned int i = 0; i < data_.size(); i++) {
376  if (ros::ok()) {
377  tictac_.Tic();
379  t_exec_ = tictac_.Tac();
380  ROS_INFO("Map building executed in %.03fms", 1000.0f * t_exec_);
381 
383 
386 
387  COccupancyGridMap2D *grid = nullptr;
388  CBeaconMap *bm = nullptr;
389 #if MRPT_VERSION >= 0x199
390  if (metric_map_->countMapsByClass<COccupancyGridMap2D>())
391  grid = metric_map_->mapByClass<COccupancyGridMap2D>().get();
392  bm = metric_map_->mapByClass<CBeaconMap>().get();
393 #else
394  if (metric_map_->m_gridMaps.size())
395  grid = metric_map_->m_gridMaps[0].get();
396  bm = metric_map_->getMapByClass<CBeaconMap>().get();
397 #endif
398 
399  // if I received new grid maps from 2D laser scan sensors
400  if (grid) {
402  // if we have new map for current sensor update it
403  mrpt_bridge::convert(*grid, msg);
404  pub_map_.publish(msg);
405  pub_metadata_.publish(msg.info);
406  }
407 
408  // if I received new beacon (range only) map
409  if (bm) {
410  mrpt::opengl::CSetOfObjects::Ptr objs;
411  objs = mrpt::opengl::CSetOfObjects::Create();
412  bm->getAs3DObject(objs);
413 
414  geometry_msgs::PoseArray poseArrayBeacons;
415  poseArrayBeacons.header.frame_id = global_frame_id_;
416  poseArrayBeacons.header.stamp = ros::Time::now();
417 
418  unsigned int objs_counter = 0;
419  while (objs->getByClass<mrpt::opengl::CEllipsoid>(objs_counter)) {
420  objs_counter++;
421  }
422  poseArrayBeacons.poses.resize(objs_counter);
423  mrpt::opengl::CEllipsoid::Ptr beacon_particle;
424 
425  for (size_t i = 0; i < objs_counter; i++) {
426  beacon_particle = objs->getByClass<mrpt::opengl::CEllipsoid>(i);
428  mrpt::poses::CPose3D(beacon_particle->getPose()),
429  poseArrayBeacons.poses[i]);
430  viz_beacons_.push_back(beacon_particle);
431  }
432  pub_particles_beacons_.publish(poseArrayBeacons);
433  vizBeacons();
434  viz_beacons_.clear();
435  }
436 
437  // publish pose
438  geometry_msgs::PoseArray poseArray;
439  poseArray.header.frame_id = global_frame_id_;
440  poseArray.header.stamp = ros::Time::now();
441  poseArray.poses.resize(curPDF.particlesCount());
442  for (size_t i = 0; i < curPDF.particlesCount(); i++) {
443  const auto p = mrpt::poses::CPose3D(curPDF.getParticlePose(i));
444  mrpt_bridge::convert(p, poseArray.poses[i]);
445  }
446 
447  pub_particles_.publish(poseArray);
448  }
449  ros::spinOnce();
450  run3Dwindow();
451  }
452  }
453  // if there is mrpt_gui it will wait until push any key in order to close the
454  // window
455  if (win3D_)
456  win3D_->waitForKey();
457  return true;
458 }
459 
461  // Most of this code was copy and pase from ros::amcl
462  mrpt::poses::CPose3D robotPose;
464 
465  curPDF.getMean(robotPose);
466 
467  tf::Stamped<tf::Pose> odom_to_map;
468  tf::Transform tmp_tf;
469  ros::Time stamp;
471  mrpt_bridge::convert(robotPose, tmp_tf);
472 
473  try {
474  tf::Stamped<tf::Pose> tmp_tf_stamped(tmp_tf.inverse(), stamp,
476  listenerTF_.transformPose(odom_frame_id_, tmp_tf_stamped, odom_to_map);
477  } catch (tf::TransformException ex) {
478  ROS_ERROR("Failed to subtract global_frame (%s) from odom_frame (%s). "
479  "TransformException: %s",
480  global_frame_id_.c_str(), odom_frame_id_.c_str(), ex.what());
481  return;
482  }
483 
484  tf::Transform latest_tf_ =
486  tf::Point(odom_to_map.getOrigin()));
487 
488  // We want to send a transform that is good up until a
489  // tolerance time so that odom can be used
490 
491  ros::Duration transform_tolerance_(0.5);
492  ros::Time transform_expiration = (stamp + transform_tolerance_);
493  tf::StampedTransform tmp_tf_stamped(latest_tf_.inverse(),
494  transform_expiration, global_frame_id_,
496  tf_broadcaster_.sendTransform(tmp_tf_stamped);
497 }
498 
499 } // namespace mrpt_rbpf_slam
void getEstimatedPosePDF(mrpt::poses::CPose3DPDFParticles &out_estimation) const
std::string global_frame_id_
/map frame
bool update_sensor_pose_
on true the sensor pose is updated on every sensor reading
tf::TransformListener listenerTF_
transform listener
void odometryForCallback(mrpt::obs::CObservationOdometry::Ptr &odometry, const std_msgs::Header &msg_header)
Get the odometry for received observation.
std::vector< ros::Subscriber > sensorSub_
list of sensors topics
void getMean(CPose3D &mean_pose) const MRPT_OVERRIDE
mrpt::slam::CMetricMapBuilderRBPF::TConstructionOptions rbpfMappingOptions_
options for SLAM from ini file
void observation(const mrpt::obs::CSensoryFrame::ConstPtr sensory_frame, const mrpt::obs::CObservationOdometry::ConstPtr odometry)
Calculate the actions from odometry model for current observation.
void publish(const boost::shared_ptr< M > &message) const
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
std::string rawlog_filename_
name of rawlog file
const GLfloat * c
std::vector< std::pair< mrpt::obs::CActionCollection, mrpt::obs::CSensoryFrame > > data_
void laserCallback(const sensor_msgs::LaserScan &msg)
Callback function for the laser scans.
ros::Publisher beacon_viz_pub_
publishers for map and pose particles
mrpt::poses::CPose3DPDFParticles curPDF
current robot pose
std::string odom_frame_id_
/odom frame
bool sleep() const
void vizBeacons()
Correct visualization for ro slam.
bool getParams(const ros::NodeHandle &nh_p)
Read the parameters from launch file.
float t_exec_
the time which take one SLAM update execution
void publishMapPose()
Publish beacon or grid map and robot pose.
std::map< std::string, mrpt::poses::CPose3D > beacon_poses_
beacon poses with respect to the map
bool waitForTransform(mrpt::poses::CPose3D &des, const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01))
Wait for transform between odometry frame and the robot frame.
bool init(ros::NodeHandle &nh)
Initialize publishers subscribers and RBPF slam.
void getAs3DObject(mrpt::opengl::CSetOfObjectsPtr &outObj) const MRPT_OVERRIDE
int marker
GLuint GLenum GLenum transform
mrpt::gui::CDisplayWindow3D::Ptr win3D_
MRPT window.
TFSIMD_FORCE_INLINE const Vector3 & getRow(int i) const
struct mrpt_rbpf_slam::PFslam::Options options_
mrpt::obs::CSensoryFrame::Ptr sensory_frame_
observations
bool waitForTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration &timeout, const ros::Duration &polling_sleep_duration=ros::Duration(0.01), std::string *error_msg=NULL) const
void readIniFile(const std::string &ini_filename)
Read ini file.
mrpt::slam::CMetricMapBuilderRBPF mapBuilder_
map builder
void updateSensorPose(const std::string &frame_id)
Update the pose of the sensor with respect to the robot.
TFSIMD_FORCE_INLINE const tfScalar & x() const
const CMultiMetricMap * getCurrentMostLikelyMetricMap() const
obs
void initSlam(Options options)
initialize the SLAM
TFSIMD_FORCE_INLINE const tfScalar & z() const
double yaw() const
void callbackBeacon(const mrpt_msgs::ObservationRangeBeacon &msg)
Callback function for the beacons.
#define ROS_INFO(...)
options
mrpt::obs::CActionCollection::Ptr action_
actions
GLuint const GLchar * name
std::string sensor_source_
2D laser scans
bool param(const std::string &param_name, T &param_val, const T &default_val) const
#define ROS_ASSERT_MSG(cond,...)
GLfloat GLfloat p
ROSCPP_DECL bool ok()
TFSIMD_FORCE_INLINE const tfScalar & y() const
void sendTransform(const StampedTransform &transform)
GLint * first
Transform inverse() const
void readRawlog(const std::string &rawlog_filename, std::vector< std::pair< mrpt::obs::CActionCollection, mrpt::obs::CSensoryFrame >> &data)
Read pairs of actions and observations from rawlog file.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
double rawlog_play_delay_
delay of replay from rawlog file
#define ROS_WARN_STREAM(args)
bool loadOptions(const ros::NodeHandle &nh, PFslam::Options &options)
Definition: options.cpp:91
TFSIMD_FORCE_INLINE Vector3 & getOrigin()
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
mrpt::system::TTimeStamp timeLastUpdate_
last update of the pose and map
const mrpt::maps::CMultiMetricMap * metric_map_
receive map after iteration of SLAM to metric map
void convert(const ros::Time &src, mrpt::system::TTimeStamp &des)
bool rawlog_play_
true if rawlog file exists
std::map< std::string, mrpt::poses::CPose3D > laser_poses_
laser scan poses with respect to the map
const_iterator find(const KEY &key) const
std::string ini_filename_
name of ini file
void transformPose(const std::string &target_frame, const geometry_msgs::PoseStamped &stamped_in, geometry_msgs::PoseStamped &stamped_out) const
Quaternion getRotation() const
GLdouble GLdouble GLdouble r
bool getParam(const std::string &key, std::string &s) const
tf::TransformBroadcaster tf_broadcaster_
transform broadcaster
static Time now()
std::vector< mrpt::opengl::CEllipsoid::Ptr > viz_beacons_
std::string base_frame_id_
robot frame
ProxyFilterContainerByClass< mrpt::maps::COccupancyGridMap2DPtr, TListMaps > m_gridMaps
#define ROS_ERROR_STREAM(args)
ROSCPP_DECL void spinOnce()
void BASE_IMPEXP tokenize(const std::string &inString, const std::string &inDelimiters, std::deque< std::string > &outTokens, bool skipBlankTokens=true) MRPT_NO_THROWS
#define ROS_ERROR(...)
mrpt::maps::CMultiMetricMapPDF mapPDF
CPose3D getParticlePose(int i) const
T::Ptr getMapByClass(const size_t &ith=0) const
void setRotationMatrix(const mrpt::math::CMatrixDouble33 &ROT)
GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble f
void processActionObservation(mrpt::obs::CActionCollection &action, mrpt::obs::CSensoryFrame &observations)


mrpt_rbpf_slam
Author(s): Vladislav Tananaev
autogenerated on Sat May 2 2020 03:44:39