29 : solver_loader_(
"slam_toolbox",
"karto::ScanSolver"),
31 first_measurement_(true),
33 process_near_pose_(nullptr)
36 smapper_ = std::make_unique<mapper_utils::SMapper>();
37 dataset_ = std::make_unique<karto::Dataset>();
45 pose_helper_ = std::make_unique<pose_utils::GetPoseHelper>(
50 std::make_unique<loop_closure_assistant::LoopClosureAssistant>(
55 double transform_publish_period;
56 nh_.param(
"transform_publish_period", transform_publish_period, 0.05);
57 threads_.push_back(std::make_unique<boost::thread>(
59 this, transform_publish_period)));
60 threads_.push_back(std::make_unique<boost::thread>(
68 for (
int i=0; i !=
threads_.size(); i++)
87 std::string solver_plugin;
88 if(!private_nh_.
getParam(
"solver_plugin", solver_plugin))
90 ROS_WARN(
"unable to find requested solver plugin, defaulting to SPA");
91 solver_plugin =
"solver_plugins::CeresSolver";
96 ROS_INFO(
"Using plugin %s", solver_plugin.c_str());
100 ROS_FATAL(
"Failed to create %s, is it registered and built? Exception: %s.",
101 solver_plugin.c_str(), ex.what());
122 private_nh.
param(
"transform_timeout", tmp_val, 0.2);
124 private_nh.
param(
"tf_buffer_duration", tmp_val, 30.);
126 private_nh.
param(
"minimum_time_interval", tmp_val, 0.5);
130 if (private_nh.
getParam(
"debug_logging", debug) && debug)
140 private_nh.
setParam(
"paused_new_measurements",
false);
148 tfL_ = std::make_unique<tf2_ros::TransformListener>(*tf_);
149 tfB_ = std::make_unique<tf2_ros::TransformBroadcaster>();
151 sstm_ = node.
advertise<nav_msgs::MapMetaData>(map_name_ +
"_metadata", 1,
true);
165 if(transform_publish_period == 0)
175 geometry_msgs::TransformStamped msg;
180 tfB_->sendTransform(msg);
190 nav_msgs::OccupancyGrid& og =
map_.map;
192 og.info.origin.position.x = 0.0;
193 og.info.origin.position.y = 0.0;
194 og.info.origin.position.z = 0.0;
195 og.info.origin.orientation.x = 0.0;
196 og.info.origin.orientation.y = 0.0;
197 og.info.origin.orientation.z = 0.0;
198 og.info.origin.orientation.w = 1.0;
201 double map_update_interval;
202 if(!
nh_.
getParam(
"map_update_interval", map_update_interval))
203 map_update_interval = 10.0;
222 geometry_msgs::Pose2D pose;
226 slam_toolbox_msgs::DeserializePoseGraph::Request req;
227 slam_toolbox_msgs::DeserializePoseGraph::Response resp;
228 req.initial_pose = pose;
229 req.filename = filename;
233 slam_toolbox_msgs::DeserializePoseGraph::Request::START_AT_FIRST_NODE;
238 slam_toolbox_msgs::DeserializePoseGraph::Request::START_AT_GIVEN_POSE;
246 geometry_msgs::Pose2D& pose,
bool& start_at_dock)
252 std::vector<double> read_pose;
255 start_at_dock =
false;
256 if (read_pose.size() != 3)
258 ROS_ERROR(
"LocalizationSlamToolbox: Incorrect number of " 259 "arguments for map starting pose. Must be in format: " 260 "[x, y, theta]. Starting at the origin");
267 pose.x = read_pose[0];
268 pose.y = read_pose[1];
269 pose.theta = read_pose[2];
285 sensor_msgs::LaserScan::ConstPtr& scan)
288 const std::string& frame = scan->header.frame_id;
298 ROS_ERROR(
"Failed to compute laser pose, aborting initialization (%s)",
304 return lasers_[frame].getLaser();
339 const bool& update_reprocessing_transform)
351 geometry_msgs::TransformStamped base_to_map_msg, odom_to_map_msg;
358 ROS_ERROR(
"Transform from base_link to odom failed: %s", e.what());
366 if (update_reprocessing_transform)
374 odom_to_base_serialized * odom_to_base_current.
inverse();
380 tf2::Vector3( odom_to_map.getOrigin() ) ).
inverse();
388 const sensor_msgs::LaserScan::ConstPtr& scan,
394 *scan,
lasers_[scan->header.frame_id].isInverted());
411 const sensor_msgs::LaserScan::ConstPtr& scan,
417 static const double dist_thresh_sq =
smapper_->getMapper()->getParamMinimumTravelDistance()*
418 smapper_->getMapper()->getParamMinimumTravelDistance();
423 last_scan_time = scan->header.stamp;
448 const double sq_dist_to_last_accepted_pose = last_pose.
SquaredDistance(pose);
450 if(sq_dist_to_last_accepted_pose < 0.8 * dist_thresh_sq || scan->
header.seq < 5)
456 last_scan_time = scan->header.stamp;
464 PosedScan& scan_w_pose)
467 return addScan(laser, scan_w_pose.scan, scan_w_pose.pose);
473 const sensor_msgs::LaserScan::ConstPtr& scan,
479 laser, scan, karto_pose);
483 bool processed =
false, update_reprocessing_transform =
false;
487 processed =
smapper_->getMapper()->Process(range_scan);
491 processed =
smapper_->getMapper()->ProcessAtDock(range_scan);
493 update_reprocessing_transform =
true;
500 ROS_ERROR(
"Process near region called without a " 501 "valid region request. Ignoring scan.");
507 processed =
smapper_->getMapper()->ProcessAgainstNodesNearBy(range_scan);
508 update_reprocessing_transform =
true;
513 ROS_FATAL(
"SlamToolbox: No valid processor type set! Exiting.");
527 scan->header.stamp, update_reprocessing_transform);
533 range_scan =
nullptr;
541 nav_msgs::GetMap::Request &req,
542 nav_msgs::GetMap::Response &res)
545 if(
map_.map.info.width &&
map_.map.info.height)
559 slam_toolbox_msgs::Pause::Request& req,
560 slam_toolbox_msgs::Pause::Response& resp)
566 nh_.
setParam(
"paused_new_measurements", !curr_state);
567 ROS_INFO(
"SlamToolbox: Toggled to %s",
568 !curr_state ?
"pause taking new measurements." :
569 "actively taking new measurements.");
583 slam_toolbox_msgs::SerializePoseGraph::Request &req,
584 slam_toolbox_msgs::SerializePoseGraph::Response &resp)
587 std::string
filename = req.filename;
602 std::unique_ptr<karto::Mapper>& mapper,
603 std::unique_ptr<karto::Dataset>& dataset)
611 VerticeMap mapper_vertices = mapper->GetGraph()->GetVertices();
612 VerticeMap::iterator vertex_map_it = mapper_vertices.begin();
613 for(vertex_map_it; vertex_map_it != mapper_vertices.end(); ++vertex_map_it)
615 ScanMap::iterator vertex_it = vertex_map_it->second.begin();
616 for(vertex_it; vertex_it != vertex_map_it->second.end(); ++vertex_it)
618 if (vertex_it->second !=
nullptr)
620 solver_->AddNode(vertex_it->second);
625 EdgeVector mapper_edges = mapper->GetGraph()->GetEdges();
626 EdgeVector::iterator edges_it = mapper_edges.begin();
627 for( edges_it; edges_it != mapper_edges.end(); ++edges_it)
629 if (*edges_it !=
nullptr)
631 solver_->AddConstraint(*edges_it);
635 mapper->SetScanSolver(
solver_.get());
638 smapper_->setMapper(mapper.release());
644 ROS_FATAL(
"loadSerializedPoseGraph: Could not properly load " 645 "a valid mapping object. Did you modify something by hand?");
649 if (
dataset_->GetLasers().size() < 1)
651 ROS_FATAL(
"loadSerializedPoseGraph: Cannot deserialize " 652 "dataset with no laser objects.");
667 ROS_INFO(
"Waiting for incoming scan to get metadata...");
669 ros::topic::waitForMessage<sensor_msgs::LaserScan>(
676 lasers_[scan->header.frame_id] =
682 ROS_ERROR(
"Failed to compute laser pose, aborting continue mapping (%s)",
691 ROS_ERROR(
"Invalid sensor pointer in dataset. Unable to register sensor.");
701 slam_toolbox_msgs::DeserializePoseGraph::Request &req,
702 slam_toolbox_msgs::DeserializePoseGraph::Response &resp)
705 if (req.match_type == slam_toolbox_msgs::DeserializePoseGraph::Request::UNSET)
707 ROS_ERROR(
"Deserialization called without valid processor type set. " 708 "Undefined behavior!");
712 std::string
filename = req.filename;
714 if (filename.empty())
726 std::unique_ptr<karto::Dataset> dataset = std::make_unique<karto::Dataset>();
727 std::unique_ptr<karto::Mapper> mapper = std::make_unique<karto::Mapper>();
731 ROS_ERROR(
"DeserializePoseGraph: Failed to read " 732 "file: %s.", filename.c_str());
735 ROS_DEBUG(
"DeserializePoseGraph: Successfully read file.");
742 switch (req.match_type)
744 case procType::START_AT_FIRST_NODE:
747 case procType::START_AT_GIVEN_POSE:
750 req.initial_pose.y, req.initial_pose.theta);
752 case procType::LOCALIZE_AT_POSE:
755 req.initial_pose.y, req.initial_pose.theta);
758 ROS_FATAL(
"Deserialization called without valid processor type set.");
std::string getSnapPath()
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
kt_double SquaredDistance(const Pose2 &rOther) const
ROSCONSOLE_DECL void notifyLoggerLevelsChanged()
const Pose2 & GetOdometricPose() const
const Pose2 & GetCorrectedPose() const
boost::shared_ptr< T > createInstance(const std::string &lookup_name)
void toNavMap(const karto::OccupancyGrid *occ_grid, nav_msgs::OccupancyGrid &map)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
bool read(const std::string &filename, karto::Mapper &mapper, karto::Dataset &dataset)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void publish(const boost::shared_ptr< M > &message) const
bool getParam(const std::string &key, std::string &s) const
TFSIMD_FORCE_INLINE Quaternion inverse(const Quaternion &q)
std::vector< double > scanToReadings(const sensor_msgs::LaserScan &scan, const bool &inverted)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
static SensorManager * GetInstance()
double getYaw(const A &a)
void SetOdometricPose(const Pose2 &rPose)
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
const Name & GetName() const
void SetCorrectedPose(const Pose2 &rPose)
void convert(const A &a, B &b)
void RegisterSensor(Sensor *pSensor, kt_bool override=false)
ROSCONSOLE_DECL bool set_logger_level(const std::string &name, levels::Level level)
uint32_t getNumSubscribers() const
#define ROSCONSOLE_DEFAULT_NAME
void write(const std::string &filename, karto::Mapper &mapper, karto::Dataset &dataset)
kt_double GetHeading() const