21 #ifndef NAV2_AMCL__AMCL_NODE_HPP_
22 #define NAV2_AMCL__AMCL_NODE_HPP_
33 #include "message_filters/subscriber.hpp"
34 #include "rclcpp/version.h"
36 #include "geometry_msgs/msg/pose_stamped.hpp"
37 #include "nav2_ros_common/lifecycle_node.hpp"
38 #include "nav2_amcl/motion_model/motion_model.hpp"
39 #include "nav2_amcl/sensors/laser/laser.hpp"
40 #include "nav2_msgs/msg/particle.hpp"
41 #include "nav2_msgs/msg/particle_cloud.hpp"
42 #include "nav2_msgs/srv/set_initial_pose.hpp"
43 #include "nav_msgs/srv/set_map.hpp"
44 #include "pluginlib/class_loader.hpp"
45 #include "rclcpp/node_options.hpp"
46 #include "sensor_msgs/msg/laser_scan.hpp"
47 #include "nav2_ros_common/service_server.hpp"
48 #include "std_srvs/srv/empty.hpp"
49 #include "nav2_ros_common/tf2_factories.hpp"
51 #define NEW_UNIFORM_SAMPLING 1
66 explicit AmclNode(
const rclcpp::NodeOptions & options = rclcpp::NodeOptions());
76 nav2::CallbackReturn on_configure(
const rclcpp_lifecycle::State & state)
override;
80 nav2::CallbackReturn on_activate(
const rclcpp_lifecycle::State & state)
override;
84 nav2::CallbackReturn on_deactivate(
const rclcpp_lifecycle::State & state)
override;
88 nav2::CallbackReturn on_cleanup(
const rclcpp_lifecycle::State & state)
override;
92 nav2::CallbackReturn on_shutdown(
const rclcpp_lifecycle::State & state)
override;
103 const std::vector<rclcpp::Parameter> & parameters);
114 rclcpp::node_interfaces::PostSetParametersCallbackHandle::SharedPtr post_set_params_handler_;
115 rclcpp::node_interfaces::OnSetParametersCallbackHandle::SharedPtr on_set_params_handler_;
119 std::atomic<bool> active_{
false};
123 rclcpp::CallbackGroup::SharedPtr callback_group_;
124 rclcpp::executors::SingleThreadedExecutor::SharedPtr executor_;
125 std::unique_ptr<nav2::NodeThread> executor_thread_;
140 void mapReceived(
const nav_msgs::msg::OccupancyGrid::ConstSharedPtr & msg);
145 void handleMapMessage(
const nav_msgs::msg::OccupancyGrid & msg);
149 void createFreeSpaceVector();
153 void freeMapDependentMemory();
154 map_t * map_{
nullptr};
160 map_t * convertMap(
const nav_msgs::msg::OccupancyGrid & map_msg);
161 bool first_map_only_{
true};
162 std::atomic<bool> first_map_received_{
false};
163 amcl_hyp_t * initial_pose_hyp_;
164 std::recursive_mutex mutex_;
165 nav2::Subscription<nav_msgs::msg::OccupancyGrid>::ConstSharedPtr map_sub_;
166 #if NEW_UNIFORM_SAMPLING
168 static std::vector<Point2D> free_space_indices;
175 void initTransforms();
176 nav2::TransformBroadcaster::SharedPtr tf_broadcaster_;
177 nav2::TransformListener::SharedPtr tf_listener_;
178 nav2::TransformBuffer::SharedPtr tf_buffer_;
179 bool sent_first_transform_{
false};
180 bool latest_tf_valid_{
false};
181 tf2::Transform latest_tf_;
187 void initMessageFilters();
190 #if RCLCPP_VERSION_GTE(29, 6, 0)
191 std::unique_ptr<message_filters::Subscriber<sensor_msgs::msg::LaserScan>> laser_scan_sub_;
193 std::unique_ptr<message_filters::Subscriber<sensor_msgs::msg::LaserScan,
194 rclcpp_lifecycle::LifecycleNode>> laser_scan_sub_;
197 nav2::MessageFilter<sensor_msgs::msg::LaserScan>::SharedPtr laser_scan_filter_;
198 message_filters::Connection laser_scan_connection_;
205 nav2::Subscription<geometry_msgs::msg::PoseWithCovarianceStamped>::ConstSharedPtr
207 nav2::Publisher<geometry_msgs::msg::PoseWithCovarianceStamped>::SharedPtr
209 nav2::Publisher<nav2_msgs::msg::ParticleCloud>::SharedPtr
214 void initialPoseReceived(
215 const geometry_msgs::msg::PoseWithCovarianceStamped::ConstSharedPtr & msg);
219 void laserReceived(sensor_msgs::msg::LaserScan::ConstSharedPtr laser_scan);
226 nav2::ServiceServer<std_srvs::srv::Empty>::SharedPtr global_loc_srv_;
230 void globalLocalizationCallback(
231 const std::shared_ptr<rmw_request_id_t> request_header,
232 const std::shared_ptr<std_srvs::srv::Empty::Request> request,
233 std::shared_ptr<std_srvs::srv::Empty::Response> response);
236 nav2::ServiceServer<nav2_msgs::srv::SetInitialPose>::SharedPtr initial_guess_srv_;
240 void initialPoseReceivedSrv(
241 const std::shared_ptr<rmw_request_id_t> request_header,
242 const std::shared_ptr<nav2_msgs::srv::SetInitialPose::Request> request,
243 std::shared_ptr<nav2_msgs::srv::SetInitialPose::Response> response);
246 nav2::ServiceServer<std_srvs::srv::Empty>::SharedPtr nomotion_update_srv_;
250 void nomotionUpdateCallback(
251 const std::shared_ptr<rmw_request_id_t> request_header,
252 const std::shared_ptr<std_srvs::srv::Empty::Request> request,
253 std::shared_ptr<std_srvs::srv::Empty::Response> response);
256 std::atomic<bool> force_update_{
false};
263 std::shared_ptr<nav2_amcl::MotionModel> motion_model_;
264 geometry_msgs::msg::PoseStamped latest_odom_pose_;
265 geometry_msgs::msg::PoseWithCovarianceStamped last_published_pose_;
266 double init_pose_[3];
268 pluginlib::ClassLoader<nav2_amcl::MotionModel> plugin_loader_{
"nav2_amcl",
269 "nav2_amcl::MotionModel"};
275 geometry_msgs::msg::PoseStamped & pose,
276 double & x,
double & y,
double & yaw,
277 const rclcpp::Time & sensor_timestamp,
const std::string & frame_id);
278 std::atomic<bool> first_pose_sent_;
284 void initParticleFilter();
288 static pf_vector_t uniformPoseGenerator(
void * arg);
292 int resample_count_{0};
293 int random_seed_{-1};
299 void initLaserScan();
303 std::unique_ptr<nav2_amcl::Laser> createLaserObject();
304 int scan_error_count_{0};
305 std::vector<std::unique_ptr<nav2_amcl::Laser>> lasers_;
306 std::vector<bool> lasers_update_;
307 std::map<std::string, int> frame_to_laser_;
308 rclcpp::Time last_laser_received_ts_;
313 bool checkElapsedTime(std::chrono::seconds check_interval, rclcpp::Time last_time);
314 rclcpp::Time last_time_printed_msg_;
320 const sensor_msgs::msg::LaserScan::ConstSharedPtr & laser_scan,
321 const std::string & laser_scan_frame_id,
322 geometry_msgs::msg::PoseStamped & laser_pose);
331 const int & laser_index,
332 const sensor_msgs::msg::LaserScan::ConstSharedPtr & laser_scan,
341 bool getMaxWeightHyp(
342 std::vector<amcl_hyp_t> & hyps, amcl_hyp_t & max_weight_hyps,
343 int & max_weight_hyp);
347 void publishAmclPose(
348 const sensor_msgs::msg::LaserScan::ConstSharedPtr & laser_scan,
349 const std::vector<amcl_hyp_t> & hyps,
const int & max_weight_hyp);
353 void calculateMaptoOdomTransform(
354 const sensor_msgs::msg::LaserScan::ConstSharedPtr & laser_scan,
355 const std::vector<amcl_hyp_t> & hyps,
356 const int & max_weight_hyp);
360 void sendMapToOdomTransform(
const tf2::TimePoint & transform_expiration);
364 void handleInitialPose(geometry_msgs::msg::PoseWithCovarianceStamped & msg);
368 void savePoseToFile();
374 bool loadPoseFromFile(geometry_msgs::msg::PoseWithCovarianceStamped & pose);
378 void savePoseTimerCallback();
379 bool init_pose_received_on_inactive{
false};
380 double save_pose_rate_{0.5};
381 bool initial_pose_is_known_{
false};
382 bool set_initial_pose_{
false};
383 bool always_reset_initial_pose_;
384 double initial_pose_x_;
385 double initial_pose_y_;
386 double initial_pose_z_;
387 double initial_pose_yaw_;
392 void initParameters();
398 std::string base_frame_id_;
399 double beam_skip_distance_;
400 double beam_skip_error_threshold_;
401 double beam_skip_threshold_;
403 std::string global_frame_id_;
404 double lambda_short_;
405 double laser_likelihood_max_dist_;
406 double laser_max_range_;
407 double laser_min_range_;
408 std::string sensor_model_type_;
412 std::string odom_frame_id_;
417 int resample_interval_;
418 std::string robot_model_type_;
419 bool initialize_at_saved_pose_;
420 std::string saved_pose_filepath_;
421 rclcpp::TimerBase::SharedPtr save_pose_timer_;
424 tf2::Duration transform_tolerance_;
431 std::string scan_topic_{
"scan"};
432 std::string map_topic_{
"map"};
433 bool freespace_downsampling_ =
false;
434 bool allow_parameter_qos_overrides_ =
true;
A lifecycle node wrapper to enable common Nav2 needs such as manipulating parameters.
void updateParametersCallback(const std::vector< rclcpp::Parameter > ¶meters)
Apply parameter updates after validation This callback is executed when parameters have been successf...
rcl_interfaces::msg::SetParametersResult validateParameterUpdatesCallback(const std::vector< rclcpp::Parameter > ¶meters)
Validate incoming parameter updates before applying them. This callback is triggered when one or more...