33 #include <geometry_msgs/Polygon.h>
34 #include <geometry_msgs/PoseStamped.h>
35 #include <mrpt/config/CConfigFile.h>
36 #include <mrpt/config/CConfigFileMemory.h>
37 #include <mrpt/kinematics/CVehicleVelCmd_DiffDriven.h>
38 #include <mrpt/maps/CSimplePointsMap.h>
39 #include <mrpt/nav/reactive/CReactiveNavigationSystem.h>
40 #include <mrpt/nav/reactive/TWaypoint.h>
41 #include <mrpt/obs/CObservationOdometry.h>
42 #include <mrpt/ros1bridge/point_cloud2.h>
43 #include <mrpt/ros1bridge/pose.h>
44 #include <mrpt/ros1bridge/time.h>
45 #include <mrpt/system/CTimeLogger.h>
46 #include <mrpt/system/filesystem.h>
47 #include <mrpt/system/os.h>
48 #include <mrpt_msgs/Waypoint.h>
49 #include <mrpt_msgs/WaypointSequence.h>
50 #include <nav_msgs/Odometry.h>
52 #include <sensor_msgs/LaserScan.h>
53 #include <sensor_msgs/PointCloud2.h>
63 using namespace mrpt::nav;
64 using mrpt::maps::CSimplePointsMap;
65 using namespace mrpt::system;
66 using namespace mrpt::config;
76 ros::init(argc, argv,
"mrpt_reactivenav2d");
98 bool m_1st_time_init =
false;
99 double m_target_allowed_distance = 0.40f;
100 double m_nav_period = 0.1;
102 std::string m_sub_topic_reactive_nav_goal =
"reactive_nav_goal";
103 std::string m_sub_topic_local_obstacles =
"local_map_pointcloud";
104 std::string m_sub_topic_robot_shape{};
106 std::string m_pub_topic_cmd_vel =
"cmd_vel";
107 std::string m_sub_topic_wp_seq =
"reactive_nav_waypoints";
108 std::string m_sub_topic_odometry =
"odom";
110 std::string m_frameid_reference =
"map";
111 std::string m_frameid_robot =
"base_link";
115 bool m_save_nav_log =
false;
137 mrpt::math::TPose2D& curPose, mrpt::math::TTwist2D& curVel,
138 mrpt::system::TTimeStamp& timestamp,
139 mrpt::math::TPose2D& curOdometry, std::string& frame_id)
override
143 CTimeLoggerEntry tle(
144 m_parent.
m_profiler,
"getCurrentPoseAndSpeeds");
148 geometry_msgs::TransformStamped tfGeom;
151 CTimeLoggerEntry tle2(
153 "getCurrentPoseAndSpeeds.lookupTransform_sensor");
168 const mrpt::poses::CPose3D curRobotPose =
169 mrpt::ros1bridge::fromROS(txRobotPose);
171 timestamp = mrpt::ros1bridge::fromROS(tfGeom.header.stamp);
174 curPose = mrpt::poses::CPose2D(curRobotPose).asTPose();
175 curOdometry = curPose;
178 MRPT_TODO(
"Retrieve current speeds from /odom topic?");
180 "[getCurrentPoseAndSpeeds] Latest pose: %s",
181 curPose.asString().c_str());
184 curVel = mrpt::math::TTwist2D(curV, .0, curW).rotated(curPose.phi);
195 const mrpt::kinematics::CVehicleVelCmd& vel_cmd)
override
197 using namespace mrpt::kinematics;
198 const CVehicleVelCmd_DiffDriven* vel_cmd_diff_driven =
199 dynamic_cast<const CVehicleVelCmd_DiffDriven*
>(&vel_cmd);
200 ASSERT_(vel_cmd_diff_driven);
202 const double v = vel_cmd_diff_driven->lin_vel;
203 const double w = vel_cmd_diff_driven->ang_vel;
205 "changeSpeeds: v=%7.4f m/s w=%8.3f deg/s", v,
207 geometry_msgs::Twist
cmd;
214 bool stop(
bool isEmergency)
override
216 mrpt::kinematics::CVehicleVelCmd_DiffDriven vel_cmd;
219 return changeSpeeds(vel_cmd);
232 CSimplePointsMap& obstacles,
233 mrpt::system::TTimeStamp& timestamp)
override
235 timestamp = mrpt::Clock::now();
239 MRPT_TODO(
"TODO: Check age of obstacles!");
249 mrpt::kinematics::CVehicleVelCmd::Ptr ret =
250 mrpt::kinematics::CVehicleVelCmd::Ptr(
251 new mrpt::kinematics::CVehicleVelCmd_DiffDriven);
270 : m_auxinit(argc, argv),
273 m_reactive_if(*this),
274 m_reactive_nav_engine(m_reactive_if)
277 std::string cfg_file_reactive;
279 "cfg_file_reactive", cfg_file_reactive, cfg_file_reactive);
281 "target_allowed_distance", m_target_allowed_distance,
282 m_target_allowed_distance);
283 m_localn.param(
"nav_period", m_nav_period, m_nav_period);
285 "frameid_reference", m_frameid_reference, m_frameid_reference);
286 m_localn.param(
"frameid_robot", m_frameid_robot, m_frameid_robot);
288 "topic_robot_shape", m_sub_topic_robot_shape,
289 m_sub_topic_robot_shape);
291 m_localn.param(
"topic_wp_seq", m_sub_topic_wp_seq, m_sub_topic_wp_seq);
293 "topic_odometry", m_sub_topic_odometry, m_sub_topic_odometry);
295 "topic_cmd_vel", m_pub_topic_cmd_vel, m_pub_topic_cmd_vel);
297 "topic_obstacles", m_sub_topic_local_obstacles,
298 m_sub_topic_local_obstacles);
300 m_localn.param(
"save_nav_log", m_save_nav_log, m_save_nav_log);
302 m_localn.param(
"ptg_plugin_files", m_plugin_file, m_plugin_file);
304 if (!m_plugin_file.empty())
307 std::string errorMsgs;
308 if (!mrpt::system::loadPluginModules(m_plugin_file, errorMsgs))
317 !cfg_file_reactive.empty(),
318 "Mandatory param 'cfg_file_reactive' is missing!");
320 mrpt::system::fileExists(cfg_file_reactive),
321 "Config file not found: '%s'", cfg_file_reactive.c_str());
323 m_reactive_nav_engine.enableLogFile(m_save_nav_log);
329 CConfigFile cfgFil(cfg_file_reactive);
330 m_reactive_nav_engine.loadConfigFile(cfgFil);
332 catch (std::exception& e)
335 "Exception initializing reactive navigation engine:\n%s",
346 if (!m_sub_topic_robot_shape.empty())
349 "Subscribing to robot shape via topic '%s'...",
350 m_sub_topic_robot_shape.c_str());
351 m_sub_robot_shape = m_nh.subscribe<geometry_msgs::Polygon>(
352 m_sub_topic_robot_shape, 1,
359 CConfigFile c(cfg_file_reactive);
360 std::string
s =
"CReactiveNavigationSystem";
362 std::vector<float> xs, ys;
364 s,
"RobotModel_shape2D_xs", std::vector<float>(), xs,
false);
366 s,
"RobotModel_shape2D_ys", std::vector<float>(), ys,
false);
368 xs.size() == ys.size(),
369 "Config parameters `RobotModel_shape2D_xs` and "
370 "`RobotModel_shape2D_ys` "
371 "must have the same length!");
374 mrpt::math::CPolygon poly;
375 poly.resize(xs.size());
376 for (
size_t i = 0; i < xs.size(); i++)
382 std::lock_guard<std::mutex> csl(m_reactive_nav_engine_cs);
383 m_reactive_nav_engine.changeRobotShape(poly);
388 if (
const double robot_radius = c.read_double(
389 s,
"RobotModel_circular_shape_radius", -1.0,
false);
392 std::lock_guard<std::mutex> csl(m_reactive_nav_engine_cs);
393 m_reactive_nav_engine.changeRobotCircularShapeRadius(
401 m_nh.advertise<geometry_msgs::Twist>(m_pub_topic_cmd_vel, 1);
406 m_sub_odometry = m_nh.subscribe(
410 m_sub_wp_seq = m_nh.subscribe(
415 m_sub_nav_goal = m_nh.subscribe<geometry_msgs::PoseStamped>(
416 m_sub_topic_reactive_nav_goal, 1,
418 m_sub_local_obs = m_nh.subscribe<sensor_msgs::PointCloud2>(
419 m_sub_topic_local_obstacles, 1,
424 m_timer_run_nav = m_nh.createTimer(
437 "[navigateTo] Starting navigation to %s",
438 target.asString().c_str());
440 CAbstractPTGBasedReactive::TNavigationParamsPTG navParams;
442 CAbstractNavigator::TargetInfo target_info;
443 target_info.target_coords.x = target.x;
444 target_info.target_coords.y = target.y;
445 target_info.targetAllowedDistance = m_target_allowed_distance;
446 target_info.targetIsRelative =
false;
453 navParams.target = target_info;
459 std::lock_guard<std::mutex> csl(m_reactive_nav_engine_cs);
460 m_reactive_nav_engine.navigate(&navParams);
469 if (!m_1st_time_init)
471 m_1st_time_init =
true;
473 "[ReactiveNav2DNode] Initializing reactive navigation "
476 std::lock_guard<std::mutex> csl(m_reactive_nav_engine_cs);
477 m_reactive_nav_engine.initialize();
480 "[ReactiveNav2DNode] Reactive navigation engine init done!");
483 CTimeLoggerEntry tle(m_profiler,
"onDoNavigation");
485 m_reactive_nav_engine.navigationStep();
490 std::lock_guard<std::mutex> csl(m_odometry_cs);
492 msg.pose.pose.orientation.x, msg.pose.pose.orientation.y,
493 msg.pose.pose.orientation.z, msg.pose.pose.orientation.w);
495 double roll, pitch, yaw;
496 mat.
getRPY(roll, pitch, yaw);
497 m_odometry.odometry = mrpt::poses::CPose2D(
498 msg.pose.pose.position.x, msg.pose.pose.position.y, yaw);
500 m_odometry.velocityLocal.vx = msg.twist.twist.linear.x;
501 m_odometry.velocityLocal.vy = msg.twist.twist.linear.y;
502 m_odometry.velocityLocal.omega = msg.twist.twist.angular.z;
503 m_odometry.hasVelocities =
true;
510 mrpt::nav::TWaypointSequence wps;
512 for (
const auto& wp : msg.waypoints)
515 wp.target.orientation.x, wp.target.orientation.y,
516 wp.target.orientation.z, wp.target.orientation.w);
518 double roll, pitch, yaw;
519 mat.
getRPY(roll, pitch, yaw);
520 auto waypoint = mrpt::nav::TWaypoint(
521 wp.target.position.x, wp.target.position.y, wp.allowed_distance,
524 if (yaw == yaw && !wp.ignore_heading)
525 waypoint.target_heading = yaw;
527 wps.waypoints.push_back(waypoint);
532 std::lock_guard<std::mutex> csl(m_reactive_nav_engine_cs);
533 m_reactive_nav_engine.navigateWaypoints(wps);
538 updateWaypointSequence(wps);
543 geometry_msgs::PoseStamped trg = *trg_ptr;
546 "Nav target received via topic sub: (%.03f,%.03f, %.03fdeg) "
548 trg.pose.position.x, trg.pose.position.y,
549 trg.pose.orientation.z * 180.0 / M_PI, trg.header.frame_id.c_str());
552 if (trg.header.frame_id != m_frameid_reference)
557 geometry_msgs::TransformStamped ref_to_trgFrame =
559 trg.header.frame_id, m_frameid_reference,
ros::Time(0),
571 this->navigateTo(mrpt::math::TPose2D(
572 trg.pose.position.x, trg.pose.position.y, trg.pose.orientation.z));
577 std::lock_guard<std::mutex> csl(m_last_obstacles_cs);
578 mrpt::ros1bridge::fromROS(*obs, m_last_obstacles);
586 "[onRosSetRobotShape] Robot shape received via topic: "
589 mrpt::math::CPolygon poly;
590 poly.resize(newShape->points.size());
591 for (
size_t i = 0; i < newShape->points.size(); i++)
593 poly[i].x = newShape->points[i].x;
594 poly[i].y = newShape->points[i].y;
598 std::lock_guard<std::mutex> csl(m_reactive_nav_engine_cs);
599 m_reactive_nav_engine.changeRobotShape(poly);
605 int main(
int argc,
char** argv)