小鱼 ROS 2 新书上线!点击链接查看, 新书配套视频点击链接查看。
提问前必看的发帖注意事项—— 提问前必看!不符合要求的问题拒绝回答!!
社区使用指南—如何添加标签修改密码
nav2中amcl没有正常发布map->odom的TF变换
-
您好,以下是我的问题描述,恳请各位看一下,是我配置文件,哪里出了问题? 有些疏忽没有注意到
环境描述
实体小车、 ubuntu24.04、 ros2-jazzy
问题描述:
在使用nav2时amcl没有正常发布map->odom的变换,导致日志中显示:
[component_container_isolated-1] [INFO] [1722479581.777346684] [global_costmap.global_costmap]: Timed out waiting for transform from base_link to map to become available, tf error: Invalid frame ID "map" passed to canTransform argument target_frame - frame does not exist
具体细节和上下文:
1、小车激光雷达,里程计驱动正常
2、构建的栅格地图信息可正常加载(如图1)
3、amcl可正常进行生命周期管理(如图2 )
4、amcl显示可正常订阅map话题(如图3)
5、amcl生命周期显示正在激活状态(如图4)
6、静态图层订阅/map话题(如图5)7、具体报错信息(INFO级别)(如图6)
8、TF树(未发布map->odom的变换信息)、部分话题通讯见图7、8
9、launch和具体params信息如下:
def generate_launch_description(): # 1. 定位到包的地址 robot_navigation2_dir = get_package_share_directory('robot_nav') nav2_bringup_dir = get_package_share_directory('nav2_bringup') # 2. 声明参数,获取配置文件路径 use_sim_time = LaunchConfiguration('use_sim_time', default='false') map_yaml_path = LaunchConfiguration('map', default=os.path.join(robot_navigation2_dir, 'maps', 'map.yaml')) nav2_param_path = LaunchConfiguration('params_file', default=os.path.join(robot_navigation2_dir, 'param', 'robot_params.yaml')) # 3. 声明启动launch文件,传入:地图路径、是否使用仿真时间以及nav2参数文件 nav2_bringup_launch = IncludeLaunchDescription( PythonLaunchDescriptionSource([nav2_bringup_dir, '/launch', '/bringup_launch.py']), launch_arguments={ 'map': map_yaml_path, 'use_sim_time': use_sim_time, 'params_file': nav2_param_path }.items(), )
amcl: ros__parameters: alpha1: 0.2 alpha2: 0.2 alpha3: 0.2 alpha4: 0.2 alpha5: 0.2 base_frame_id: "base_link" # base_frame_id: "odom" beam_skip_distance: 0.5 beam_skip_error_threshold: 0.9 beam_skip_threshold: 0.3 do_beamskip: false global_frame_id: "map" lambda_short: 0.1 laser_likelihood_max_dist: 2.0 laser_max_range: 100.0 laser_min_range: -1.0 laser_model_type: "likelihood_field" max_beams: 60 max_particles: 2000 min_particles: 500 odom_frame_id: "odom" pf_err: 0.05 pf_z: 0.99 recovery_alpha_fast: 0.0 recovery_alpha_slow: 0.0 resample_interval: 1 robot_model_type: "nav2_amcl::DifferentialMotionModel" save_pose_rate: 0.5 sigma_hit: 0.2 tf_broadcast: true transform_tolerance: 1.0 update_min_a: 0.2 update_min_d: 0.25 z_hit: 0.5 z_max: 0.05 z_rand: 0.5 z_short: 0.05 scan_topic: scan bt_navigator: ros__parameters: global_frame: map robot_base_frame: base_link odom_topic: /odom bt_loop_duration: 10 default_server_timeout: 20 wait_for_service_timeout: 1000 action_server_result_timeout: 900.0 navigators: ["navigate_to_pose", "navigate_through_poses"] navigate_to_pose: plugin: "nav2_bt_navigator::NavigateToPoseNavigator" navigate_through_poses: plugin: "nav2_bt_navigator::NavigateThroughPosesNavigator" # 'default_nav_through_poses_bt_xml' and 'default_nav_to_pose_bt_xml' are use defaults: # nav2_bt_navigator/navigate_to_pose_w_replanning_and_recovery.xml # nav2_bt_navigator/navigate_through_poses_w_replanning_and_recovery.xml # They can be set here or via a RewrittenYaml remap from a parent launch file to Nav2. # plugin_lib_names is used to add custom BT plugins to the executor (vector of strings). # Built-in plugins are added automatically # plugin_lib_names: [] error_code_names: - compute_path_error_code - follow_path_error_code controller_server: ros__parameters: controller_frequency: 20.0 min_x_velocity_threshold: 0.001 min_y_velocity_threshold: 0.5 min_theta_velocity_threshold: 0.001 failure_tolerance: 0.3 progress_checker_plugins: ["progress_checker"] goal_checker_plugins: ["general_goal_checker"] # "precise_goal_checker" controller_plugins: ["FollowPath"] use_realtime_priority: false # Progress checker parameters progress_checker: plugin: "nav2_controller::SimpleProgressChecker" required_movement_radius: 0.5 movement_time_allowance: 10.0 # Goal checker parameters #precise_goal_checker: # plugin: "nav2_controller::SimpleGoalChecker" # xy_goal_tolerance: 0.25 # yaw_goal_tolerance: 0.25 # stateful: True general_goal_checker: stateful: True plugin: "nav2_controller::SimpleGoalChecker" xy_goal_tolerance: 0.25 yaw_goal_tolerance: 0.25 FollowPath: plugin: "nav2_mppi_controller::MPPIController" time_steps: 56 model_dt: 0.05 batch_size: 2000 ax_max: 3.0 ax_min: -3.0 ay_max: 3.0 az_max: 3.5 vx_std: 0.2 vy_std: 0.2 wz_std: 0.4 vx_max: 0.5 vx_min: -0.35 vy_max: 0.5 wz_max: 1.9 iteration_count: 1 prune_distance: 1.7 transform_tolerance: 0.1 temperature: 0.3 gamma: 0.015 motion_model: "DiffDrive" visualize: true regenerate_noises: true TrajectoryVisualizer: trajectory_step: 5 time_step: 3 AckermannConstraints: min_turning_r: 0.2 critics: [ "ConstraintCritic", "CostCritic", "GoalCritic", "GoalAngleCritic", "PathAlignCritic", "PathFollowCritic", "PathAngleCritic", "PreferForwardCritic"] ConstraintCritic: enabled: true cost_power: 1 cost_weight: 4.0 GoalCritic: enabled: true cost_power: 1 cost_weight: 5.0 threshold_to_consider: 1.4 GoalAngleCritic: enabled: true cost_power: 1 cost_weight: 3.0 threshold_to_consider: 0.5 PreferForwardCritic: enabled: true cost_power: 1 cost_weight: 5.0 threshold_to_consider: 0.5 CostCritic: enabled: true cost_power: 1 cost_weight: 3.81 critical_cost: 300.0 consider_footprint: true collision_cost: 1000000.0 near_goal_distance: 1.0 trajectory_point_step: 2 PathAlignCritic: enabled: true cost_power: 1 cost_weight: 14.0 max_path_occupancy_ratio: 0.05 trajectory_point_step: 4 threshold_to_consider: 0.5 offset_from_furthest: 20 use_path_orientations: false PathFollowCritic: enabled: true cost_power: 1 cost_weight: 5.0 offset_from_furthest: 5 threshold_to_consider: 1.4 PathAngleCritic: enabled: true cost_power: 1 cost_weight: 2.0 offset_from_furthest: 4 threshold_to_consider: 0.5 max_angle_to_furthest: 1.0 mode: 0 # TwirlingCritic: # enabled: true # twirling_cost_power: 1 # twirling_cost_weight: 10.0 local_costmap: local_costmap: ros__parameters: update_frequency: 5.0 publish_frequency: 2.0 global_frame: odom robot_base_frame: base_link rolling_window: true width: 3 height: 3 resolution: 0.05 robot_radius: 0.22 plugins: ["voxel_layer", "inflation_layer"] inflation_layer: plugin: "nav2_costmap_2d::InflationLayer" cost_scaling_factor: 3.0 inflation_radius: 0.70 voxel_layer: plugin: "nav2_costmap_2d::VoxelLayer" enabled: True publish_voxel_map: True origin_z: 0.0 z_resolution: 0.05 z_voxels: 16 max_obstacle_height: 2.0 mark_threshold: 0 observation_sources: scan scan: topic: /scan max_obstacle_height: 2.0 clearing: True marking: True data_type: "LaserScan" raytrace_max_range: 3.0 raytrace_min_range: 0.0 obstacle_max_range: 2.5 obstacle_min_range: 0.0 static_layer: plugin: "nav2_costmap_2d::StaticLayer" map_subscribe_transient_local: True always_send_full_costmap: True global_costmap: global_costmap: ros__parameters: update_frequency: 1.0 publish_frequency: 1.0 global_frame: map robot_base_frame: base_link robot_radius: 0.22 resolution: 0.05 track_unknown_space: true plugins: ["static_layer", "obstacle_layer", "inflation_layer"] obstacle_layer: plugin: "nav2_costmap_2d::ObstacleLayer" enabled: True observation_sources: scan scan: topic: /scan max_obstacle_height: 2.0 clearing: True marking: True data_type: "LaserScan" raytrace_max_range: 3.0 raytrace_min_range: 0.0 obstacle_max_range: 2.5 obstacle_min_range: 0.0 static_layer: plugin: "nav2_costmap_2d::StaticLayer" map_subscribe_transient_local: True inflation_layer: plugin: "nav2_costmap_2d::InflationLayer" cost_scaling_factor: 3.0 inflation_radius: 0.25 always_send_full_costmap: True # The yaml_filename does not need to be specified since it going to be set by defaults in launch. # If you'd rather set it in the yaml, remove the default "map" value in the tb3_simulation_launch.py # file & provide full path to map below. If CLI map configuration or launch default is provided, that will be used. # map_server: # ros__parameters: # yaml_filename: "" map_saver: ros__parameters: save_map_timeout: 5.0 free_thresh_default: 0.25 occupied_thresh_default: 0.65 map_subscribe_transient_local: True planner_server: ros__parameters: expected_planner_frequency: 20.0 planner_plugins: ["GridBased"] GridBased: plugin: "nav2_navfn_planner::NavfnPlanner" tolerance: 0.5 use_astar: false allow_unknown: true smoother_server: ros__parameters: smoother_plugins: ["simple_smoother"] simple_smoother: plugin: "nav2_smoother::SimpleSmoother" tolerance: 1.0e-10 max_its: 1000 do_refinement: True behavior_server: ros__parameters: local_costmap_topic: local_costmap/costmap_raw global_costmap_topic: global_costmap/costmap_raw local_footprint_topic: local_costmap/published_footprint global_footprint_topic: global_costmap/published_footprint cycle_frequency: 10.0 behavior_plugins: ["spin", "backup", "drive_on_heading", "assisted_teleop", "wait"] spin: plugin: "nav2_behaviors::Spin" backup: plugin: "nav2_behaviors::BackUp" drive_on_heading: plugin: "nav2_behaviors::DriveOnHeading" wait: plugin: "nav2_behaviors::Wait" assisted_teleop: plugin: "nav2_behaviors::AssistedTeleop" local_frame: odom global_frame: map robot_base_frame: base_link transform_tolerance: 0.1 simulate_ahead_time: 2.0 max_rotational_vel: 1.0 min_rotational_vel: 0.4 rotational_acc_lim: 3.2 waypoint_follower: ros__parameters: loop_rate: 20 stop_on_failure: false action_server_result_timeout: 900.0 waypoint_task_executor_plugin: "wait_at_waypoint" wait_at_waypoint: plugin: "nav2_waypoint_follower::WaitAtWaypoint" enabled: True waypoint_pause_duration: 200 velocity_smoother: ros__parameters: smoothing_frequency: 20.0 scale_velocities: False feedback: "OPEN_LOOP" max_velocity: [0.5, 0.0, 2.0] min_velocity: [-0.5, 0.0, -2.0] max_accel: [2.5, 0.0, 3.2] max_decel: [-2.5, 0.0, -3.2] odom_topic: "odom" odom_duration: 0.1 deadband_velocity: [0.0, 0.0, 0.0] velocity_timeout: 1.0 collision_monitor: ros__parameters: base_frame_id: "base_link" odom_frame_id: "odom" cmd_vel_in_topic: "cmd_vel_smoothed" cmd_vel_out_topic: "cmd_vel" state_topic: "collision_monitor_state" transform_tolerance: 0.2 source_timeout: 1.0 base_shift_correction: True stop_pub_timeout: 2.0 # Polygons represent zone around the robot for "stop", "slowdown" and "limit" action types, # and robot footprint for "approach" action type. polygons: ["FootprintApproach"] FootprintApproach: type: "polygon" action_type: "approach" footprint_topic: "/local_costmap/published_footprint" time_before_collision: 1.2 simulation_time_step: 0.1 min_points: 6 visualize: False enabled: True observation_sources: ["scan"] scan: type: "scan" topic: "scan" min_height: 0.15 max_height: 2.0 enabled: True docking_server: ros__parameters: controller_frequency: 50.0 initial_perception_timeout: 5.0 wait_charge_timeout: 5.0 dock_approach_timeout: 30.0 undock_linear_tolerance: 0.05 undock_angular_tolerance: 0.1 max_retries: 3 base_frame: "base_link" fixed_frame: "odom" dock_backwards: false dock_prestaging_tolerance: 0.5 # Types of docks dock_plugins: ['simple_charging_dock'] simple_charging_dock: plugin: 'opennav_docking::SimpleChargingDock' docking_threshold: 0.05 staging_x_offset: -0.7 use_external_detection_pose: true use_battery_status: false # true use_stall_detection: false # true external_detection_timeout: 1.0 external_detection_translation_x: -0.18 external_detection_translation_y: 0.0 external_detection_rotation_roll: -1.57 external_detection_rotation_pitch: -1.57 external_detection_rotation_yaw: 0.0 filter_coef: 0.1 # Dock instances # The following example illustrates configuring dock instances. # docks: ['home_dock'] # Input your docks here # home_dock: # type: 'simple_charging_dock' # frame: map # pose: [0.0, 0.0, 0.0] controller: k_phi: 3.0 k_delta: 2.0 v_linear_min: 0.15 v_linear_max: 0.15
尝试过的解决方法:
1、采用gmapping替换amcl输出map->odom转换,可正常进行导航,无错误,但是无法展示输入的先验地图。
2、先启动map_server独立控制先验地图的生命周期管理,仍报无法找到map->odom的错误 -
从你描述的问题和配置文件中,我们可以看到几个可能的原因和解决方案。首先,确保你的系统能够正确地生成和发布
map
到odom
的变换,这是导航过程中非常重要的一个环节。这里有几个步骤可以帮助你检查和解决问题:1. 确认里程计 (Odometry) 的来源
确保你的小车正在发布有效的里程计数据到
/odom
话题。这通常包括位置(position)和姿态(orientation)信息。你可以使用rostopic echo /odom
来检查这些数据。2. 检查 AMCL 配置
从你的 AMCL 配置来看,
odom_frame_id
已经被设置为"odom"
,这是正确的。但重要的是要确保 AMCL 能够接收到这个里程计数据。你可以通过查看 AMCL 的日志或使用调试工具来确认 AMCL 是否正在订阅/odom
话题。3. 确保 TF 树完整
TF(Transform Trees)是 ROS 中用于处理不同坐标系之间转换的系统。你需要确保 TF 树包含了从
map
到odom
的转换。你可以使用ros2 run tf2_ros tf2_echo map odom
来检查这一点。如果没有输出,说明 TF 树中没有这个转换。4. 检查其他节点的 TF 发布
如果有其他节点(如里程计估计器或 SLAM 系统)负责发布
map
到odom
的变换,请确保这些节点正在运行并正确配置。5. 使用
static_transform_publisher
如果其他方法都不奏效,你可以尝试使用
static_transform_publisher
来临时添加一个从map
到odom
的静态变换。这可以通过在你的 launch 文件中添加以下内容来实现:from launch_ros.actions import Node # ... 其他 launch 配置 ... def generate_launch_description(): # ... 其他 launch 逻辑 ... # 添加静态变换 static_transform_publisher = Node( package='tf2_ros', executable='static_transform_publisher', name='static_transform_publisher', output='screen', arguments=[ '0.0', '0.0', '0.0', # translation '0.0', '0.0', '0.0', '1.0', # quaternion (w, x, y, z) 'map', 'odom', # source_frame, target_frame '10', # period (in seconds) ] ) # ... 其他 launch 逻辑,包括返回所有节点 ...
请注意,这个静态变换只是一个临时的解决方案,它假设
map
和odom
之间的变换是固定的,这在许多情况下可能不是真的。6. 检查和更新 ROS 2 和 Nav2 的版本
确保你使用的是 ROS 2 和 Nav2 的最新版本。有时候,一些已知的问题和错误会在新版本中得到修复。
7. 查阅文档和社区
查看 Nav2 的官方文档和社区论坛,看看是否有其他人遇到并解决了类似的问题。
通过这些步骤,你应该能够诊断并解决 AMCL 没有发布
map
到odom
变换的问题。如果问题仍然存在,可能需要更深入地检查你的系统配置或寻求更专业的帮助。
以上为生成回答,仅供参考~
-
@liang0706 看起来像amcl没有正常工作,正常导航过程中是由amcl提供从map到odom的变换的,重点检查这个模块