agenticros 0.5.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/README.md +2 -0
  2. package/dist/commands/up.d.ts +1 -0
  3. package/dist/commands/up.d.ts.map +1 -1
  4. package/dist/commands/up.js +3 -2
  5. package/dist/commands/up.js.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/runners/sim.d.ts +2 -0
  9. package/dist/runners/sim.d.ts.map +1 -1
  10. package/dist/runners/sim.js +7 -0
  11. package/dist/runners/sim.js.map +1 -1
  12. package/package.json +2 -2
  13. package/runtime/BUNDLE.json +1 -1
  14. package/runtime/README.md +20 -48
  15. package/runtime/docs/cli.md +4 -2
  16. package/runtime/packages/agenticros-claude-code/README.md +1 -1
  17. package/runtime/packages/core/README.md +4 -2
  18. package/runtime/packages/core/package.json +1 -1
  19. package/runtime/packages/core/src/__tests__/external-capability.test.ts +21 -0
  20. package/runtime/packages/core/src/external-capability.ts +35 -0
  21. package/runtime/pnpm-lock.yaml +5 -5
  22. package/runtime/ros2_ws/src/agenticros_sim/CMakeLists.txt +1 -0
  23. package/runtime/ros2_ws/src/agenticros_sim/README.md +13 -10
  24. package/runtime/ros2_ws/src/agenticros_sim/config/agenticros-sim.config.json +3 -2
  25. package/runtime/ros2_ws/src/agenticros_sim/config/amr_bridge.yaml +6 -4
  26. package/runtime/ros2_ws/src/agenticros_sim/config/nav2_params.yaml +320 -0
  27. package/runtime/ros2_ws/src/agenticros_sim/launch/sim_amr_nav2.launch.py +101 -0
  28. package/runtime/ros2_ws/src/agenticros_sim/maps/agenticros_indoor.pgm +0 -0
  29. package/runtime/ros2_ws/src/agenticros_sim/maps/agenticros_indoor.yaml +7 -0
  30. package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.sdf +18 -1
  31. package/runtime/ros2_ws/src/agenticros_sim/package.xml +15 -2
  32. package/runtime/ros2_ws/src/agenticros_sim/urdf/agenticros_amr.urdf.xacro +9 -0
  33. package/runtime/scripts/sim/run_sim.sh +26 -5
  34. package/runtime/scripts/test-navigate-sim.mjs +164 -0
@@ -0,0 +1,320 @@
1
+ # Nav2 parameters for agenticros_amr in Gazebo (agenticros_indoor world).
2
+ # Tuned for a ~0.40 x 0.30 m diff-drive footprint, /scan lidar, /cmd_vel,
3
+ # and use_sim_time. Used by launch/sim_amr_nav2.launch.py.
4
+
5
+ amcl:
6
+ ros__parameters:
7
+ use_sim_time: true
8
+ alpha1: 0.2
9
+ alpha2: 0.2
10
+ alpha3: 0.2
11
+ alpha4: 0.2
12
+ alpha5: 0.2
13
+ base_frame_id: base_footprint
14
+ beam_skip_distance: 0.5
15
+ beam_skip_error_threshold: 0.9
16
+ beam_skip_threshold: 0.3
17
+ do_beamskip: false
18
+ global_frame_id: map
19
+ lambda_short: 0.1
20
+ laser_likelihood_max_dist: 2.0
21
+ laser_max_range: 12.0
22
+ laser_min_range: 0.12
23
+ laser_model_type: likelihood_field
24
+ max_beams: 60
25
+ max_particles: 2000
26
+ min_particles: 500
27
+ odom_frame_id: odom
28
+ pf_err: 0.05
29
+ pf_z: 0.99
30
+ recovery_alpha_fast: 0.0
31
+ recovery_alpha_slow: 0.0
32
+ resample_interval: 1
33
+ robot_model_type: nav2_amcl::DifferentialMotionModel
34
+ save_pose_rate: 0.5
35
+ sigma_hit: 0.2
36
+ tf_broadcast: true
37
+ transform_tolerance: 1.0
38
+ update_min_a: 0.2
39
+ update_min_d: 0.25
40
+ z_hit: 0.5
41
+ z_max: 0.05
42
+ z_rand: 0.5
43
+ z_short: 0.05
44
+ scan_topic: scan
45
+ set_initial_pose: true
46
+ initial_pose:
47
+ x: 0.0
48
+ y: 0.0
49
+ z: 0.0
50
+ yaw: 0.0
51
+
52
+ bt_navigator:
53
+ ros__parameters:
54
+ use_sim_time: true
55
+ global_frame: map
56
+ robot_base_frame: base_footprint
57
+ odom_topic: /odom
58
+ bt_loop_duration: 10
59
+ default_server_timeout: 20
60
+ wait_for_service_timeout: 1000
61
+ plugin_lib_names:
62
+ - nav2_compute_path_to_pose_action_bt_node
63
+ - nav2_compute_path_through_poses_action_bt_node
64
+ - nav2_smooth_path_action_bt_node
65
+ - nav2_follow_path_action_bt_node
66
+ - nav2_spin_action_bt_node
67
+ - nav2_wait_action_bt_node
68
+ - nav2_assisted_teleop_action_bt_node
69
+ - nav2_back_up_action_bt_node
70
+ - nav2_drive_on_heading_bt_node
71
+ - nav2_clear_costmap_service_bt_node
72
+ - nav2_is_stuck_condition_bt_node
73
+ - nav2_goal_reached_condition_bt_node
74
+ - nav2_goal_updated_condition_bt_node
75
+ - nav2_globally_updated_goal_condition_bt_node
76
+ - nav2_is_path_valid_condition_bt_node
77
+ - nav2_initial_pose_received_condition_bt_node
78
+ - nav2_reinitialize_global_localization_service_bt_node
79
+ - nav2_rate_controller_bt_node
80
+ - nav2_distance_controller_bt_node
81
+ - nav2_speed_controller_bt_node
82
+ - nav2_truncate_path_action_bt_node
83
+ - nav2_truncate_path_local_action_bt_node
84
+ - nav2_goal_updater_node_bt_node
85
+ - nav2_recovery_node_bt_node
86
+ - nav2_pipeline_sequence_bt_node
87
+ - nav2_round_robin_node_bt_node
88
+ - nav2_transform_available_condition_bt_node
89
+ - nav2_time_expired_condition_bt_node
90
+ - nav2_path_expiring_timer_condition
91
+ - nav2_distance_traveled_condition_bt_node
92
+ - nav2_single_trigger_bt_node
93
+ - nav2_goal_updated_controller_bt_node
94
+ - nav2_is_battery_low_condition_bt_node
95
+ - nav2_navigate_through_poses_action_bt_node
96
+ - nav2_navigate_to_pose_action_bt_node
97
+ - nav2_remove_passed_goals_action_bt_node
98
+ - nav2_planner_selector_bt_node
99
+ - nav2_controller_selector_bt_node
100
+ - nav2_goal_checker_selector_bt_node
101
+ - nav2_controller_cancel_bt_node
102
+ - nav2_path_longer_on_approach_bt_node
103
+ - nav2_wait_cancel_bt_node
104
+ - nav2_spin_cancel_bt_node
105
+ - nav2_back_up_cancel_bt_node
106
+ - nav2_assisted_teleop_cancel_bt_node
107
+ - nav2_drive_on_heading_cancel_bt_node
108
+ - nav2_is_battery_charging_condition_bt_node
109
+
110
+ bt_navigator_navigate_through_poses_rclcpp_node:
111
+ ros__parameters:
112
+ use_sim_time: true
113
+
114
+ bt_navigator_navigate_to_pose_rclcpp_node:
115
+ ros__parameters:
116
+ use_sim_time: true
117
+
118
+ controller_server:
119
+ ros__parameters:
120
+ use_sim_time: true
121
+ controller_frequency: 20.0
122
+ min_x_velocity_threshold: 0.001
123
+ min_y_velocity_threshold: 0.5
124
+ min_theta_velocity_threshold: 0.001
125
+ failure_tolerance: 0.3
126
+ progress_checker_plugin: progress_checker
127
+ goal_checker_plugins: [general_goal_checker]
128
+ controller_plugins: [FollowPath]
129
+ progress_checker:
130
+ plugin: nav2_controller::SimpleProgressChecker
131
+ required_movement_radius: 0.5
132
+ movement_time_allowance: 10.0
133
+ general_goal_checker:
134
+ stateful: true
135
+ plugin: nav2_controller::SimpleGoalChecker
136
+ xy_goal_tolerance: 0.25
137
+ yaw_goal_tolerance: 0.25
138
+ FollowPath:
139
+ plugin: nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController
140
+ desired_linear_vel: 0.35
141
+ lookahead_dist: 0.6
142
+ min_lookahead_dist: 0.3
143
+ max_lookahead_dist: 0.9
144
+ lookahead_time: 1.5
145
+ rotate_to_heading_angular_vel: 1.0
146
+ transform_tolerance: 0.1
147
+ use_velocity_scaled_lookahead_dist: false
148
+ min_approach_linear_velocity: 0.05
149
+ approach_velocity_scaling_dist: 0.6
150
+ use_collision_detection: true
151
+ max_allowed_time_to_collision_up_to_carrot: 1.0
152
+ use_regulated_linear_velocity_scaling: true
153
+ use_cost_regulated_linear_velocity_scaling: false
154
+ regulated_linear_scaling_min_radius: 0.9
155
+ regulated_linear_scaling_min_speed: 0.1
156
+ allow_reversing: false
157
+ use_rotate_to_heading: true
158
+ rotate_to_heading_min_angular_vel: 0.3
159
+ max_angular_accel: 2.0
160
+ max_robot_pose_search_dist: 10.0
161
+
162
+ local_costmap:
163
+ local_costmap:
164
+ ros__parameters:
165
+ use_sim_time: true
166
+ update_frequency: 5.0
167
+ publish_frequency: 2.0
168
+ global_frame: odom
169
+ robot_base_frame: base_footprint
170
+ rolling_window: true
171
+ width: 3
172
+ height: 3
173
+ resolution: 0.05
174
+ robot_radius: 0.28
175
+ plugins: [voxel_layer, inflation_layer]
176
+ inflation_layer:
177
+ plugin: nav2_costmap_2d::InflationLayer
178
+ cost_scaling_factor: 3.0
179
+ inflation_radius: 0.55
180
+ voxel_layer:
181
+ plugin: nav2_costmap_2d::VoxelLayer
182
+ enabled: true
183
+ publish_voxel_map: false
184
+ origin_z: 0.0
185
+ z_resolution: 0.05
186
+ z_voxels: 16
187
+ max_obstacle_height: 2.0
188
+ mark_threshold: 0
189
+ observation_sources: scan
190
+ scan:
191
+ topic: /scan
192
+ max_obstacle_height: 2.0
193
+ clearing: true
194
+ marking: true
195
+ data_type: LaserScan
196
+ raytrace_max_range: 3.0
197
+ raytrace_min_range: 0.0
198
+ obstacle_max_range: 2.5
199
+ obstacle_min_range: 0.0
200
+ always_send_full_costmap: true
201
+
202
+ global_costmap:
203
+ global_costmap:
204
+ ros__parameters:
205
+ use_sim_time: true
206
+ update_frequency: 1.0
207
+ publish_frequency: 1.0
208
+ global_frame: map
209
+ robot_base_frame: base_footprint
210
+ robot_radius: 0.28
211
+ resolution: 0.05
212
+ track_unknown_space: true
213
+ plugins: [static_layer, obstacle_layer, inflation_layer]
214
+ obstacle_layer:
215
+ plugin: nav2_costmap_2d::ObstacleLayer
216
+ enabled: true
217
+ observation_sources: scan
218
+ scan:
219
+ topic: /scan
220
+ max_obstacle_height: 2.0
221
+ clearing: true
222
+ marking: true
223
+ data_type: LaserScan
224
+ raytrace_max_range: 3.0
225
+ raytrace_min_range: 0.0
226
+ obstacle_max_range: 2.5
227
+ obstacle_min_range: 0.0
228
+ static_layer:
229
+ plugin: nav2_costmap_2d::StaticLayer
230
+ map_subscribe_transient_local: true
231
+ inflation_layer:
232
+ plugin: nav2_costmap_2d::InflationLayer
233
+ cost_scaling_factor: 3.0
234
+ inflation_radius: 0.55
235
+ always_send_full_costmap: true
236
+
237
+ map_server:
238
+ ros__parameters:
239
+ use_sim_time: true
240
+ yaml_filename: ""
241
+
242
+ map_saver:
243
+ ros__parameters:
244
+ use_sim_time: true
245
+ save_map_timeout: 5.0
246
+ free_thresh_default: 0.25
247
+ occupied_thresh_default: 0.65
248
+ map_subscribe_transient_local: true
249
+
250
+ planner_server:
251
+ ros__parameters:
252
+ use_sim_time: true
253
+ expected_planner_frequency: 20.0
254
+ planner_plugins: [GridBased]
255
+ GridBased:
256
+ plugin: nav2_navfn_planner/NavfnPlanner
257
+ tolerance: 0.5
258
+ use_astar: false
259
+ allow_unknown: true
260
+
261
+ smoother_server:
262
+ ros__parameters:
263
+ use_sim_time: true
264
+ smoother_plugins: [simple_smoother]
265
+ simple_smoother:
266
+ plugin: nav2_smoother::SimpleSmoother
267
+ tolerance: 1.0e-10
268
+ max_its: 1000
269
+ do_refinement: true
270
+
271
+ behavior_server:
272
+ ros__parameters:
273
+ use_sim_time: true
274
+ costmap_topic: local_costmap/costmap_raw
275
+ footprint_topic: local_costmap/published_footprint
276
+ cycle_frequency: 10.0
277
+ behavior_plugins: [spin, backup, drive_on_heading, assisted_teleop, wait]
278
+ spin:
279
+ plugin: nav2_behaviors/Spin
280
+ backup:
281
+ plugin: nav2_behaviors/BackUp
282
+ drive_on_heading:
283
+ plugin: nav2_behaviors/DriveOnHeading
284
+ wait:
285
+ plugin: nav2_behaviors/Wait
286
+ assisted_teleop:
287
+ plugin: nav2_behaviors/AssistedTeleop
288
+ global_frame: odom
289
+ robot_base_frame: base_footprint
290
+ transform_tolerance: 0.1
291
+ simulate_ahead_time: 2.0
292
+ max_rotational_vel: 1.0
293
+ min_rotational_vel: 0.4
294
+ rotational_acc_lim: 3.2
295
+
296
+ waypoint_follower:
297
+ ros__parameters:
298
+ use_sim_time: true
299
+ loop_rate: 20
300
+ stop_on_failure: false
301
+ waypoint_task_executor_plugin: wait_at_waypoint
302
+ wait_at_waypoint:
303
+ plugin: nav2_waypoint_follower::WaitAtWaypoint
304
+ enabled: true
305
+ waypoint_pause_duration: 200
306
+
307
+ velocity_smoother:
308
+ ros__parameters:
309
+ use_sim_time: true
310
+ smoothing_frequency: 20.0
311
+ scale_velocities: false
312
+ feedback: OPEN_LOOP
313
+ max_velocity: [0.5, 0.0, 1.5]
314
+ min_velocity: [-0.5, 0.0, -1.5]
315
+ max_accel: [1.0, 0.0, 2.0]
316
+ max_decel: [-1.0, 0.0, -2.0]
317
+ odom_topic: odom
318
+ odom_duration: 0.1
319
+ deadband_velocity: [0.0, 0.0, 0.0]
320
+ velocity_timeout: 1.0
@@ -0,0 +1,101 @@
1
+ """sim_amr_nav2.launch.py
2
+
3
+ Bring up Gazebo AMR sim + Nav2 (static map + AMCL + navigation stack).
4
+
5
+ Includes:
6
+ * agenticros_sim/sim_amr.launch.py (gz + bridge + robot_state_publisher)
7
+ * nav2_bringup/bringup_launch.py (map_server + amcl + controller/planner/bt)
8
+
9
+ Launch args (forwarded to sim_amr where applicable):
10
+ gui, use_rviz, use_sim_time, x, y, z, yaw
11
+ map — occupancy grid YAML (default: maps/agenticros_indoor.yaml)
12
+ params_file — Nav2 params (default: config/nav2_params.yaml)
13
+ autostart — lifecycle autostart (default true)
14
+
15
+ Examples:
16
+ ros2 launch agenticros_sim sim_amr_nav2.launch.py gui:=false
17
+ ros2 launch agenticros_sim sim_amr_nav2.launch.py use_rviz:=true
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import os
23
+
24
+ from ament_index_python.packages import get_package_share_directory
25
+ from launch import LaunchDescription
26
+ from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
27
+ from launch.launch_description_sources import PythonLaunchDescriptionSource
28
+ from launch.substitutions import LaunchConfiguration
29
+
30
+
31
+ PKG_NAME = "agenticros_sim"
32
+
33
+
34
+ def generate_launch_description() -> LaunchDescription:
35
+ pkg_share = get_package_share_directory(PKG_NAME)
36
+ default_map = os.path.join(pkg_share, "maps", "agenticros_indoor.yaml")
37
+ default_params = os.path.join(pkg_share, "config", "nav2_params.yaml")
38
+ sim_amr_launch = os.path.join(pkg_share, "launch", "sim_amr.launch.py")
39
+ nav2_bringup = get_package_share_directory("nav2_bringup")
40
+ bringup_launch = os.path.join(nav2_bringup, "launch", "bringup_launch.py")
41
+
42
+ gui_arg = DeclareLaunchArgument("gui", default_value="true")
43
+ use_rviz_arg = DeclareLaunchArgument("use_rviz", default_value="false")
44
+ use_sim_time_arg = DeclareLaunchArgument("use_sim_time", default_value="true")
45
+ x_arg = DeclareLaunchArgument("x", default_value="0.0")
46
+ y_arg = DeclareLaunchArgument("y", default_value="0.0")
47
+ z_arg = DeclareLaunchArgument("z", default_value="0.1")
48
+ yaw_arg = DeclareLaunchArgument("yaw", default_value="0.0")
49
+ map_arg = DeclareLaunchArgument("map", default_value=default_map)
50
+ params_arg = DeclareLaunchArgument("params_file", default_value=default_params)
51
+ autostart_arg = DeclareLaunchArgument("autostart", default_value="true")
52
+
53
+ sim = IncludeLaunchDescription(
54
+ PythonLaunchDescriptionSource(sim_amr_launch),
55
+ launch_arguments={
56
+ "gui": LaunchConfiguration("gui"),
57
+ "use_rviz": LaunchConfiguration("use_rviz"),
58
+ "use_sim_time": LaunchConfiguration("use_sim_time"),
59
+ "x": LaunchConfiguration("x"),
60
+ "y": LaunchConfiguration("y"),
61
+ "z": LaunchConfiguration("z"),
62
+ "yaw": LaunchConfiguration("yaw"),
63
+ }.items(),
64
+ )
65
+
66
+ # slam:=False → localization_launch (map_server + amcl) + navigation_launch
67
+ nav2 = IncludeLaunchDescription(
68
+ PythonLaunchDescriptionSource(bringup_launch),
69
+ launch_arguments={
70
+ "slam": "False",
71
+ "map": LaunchConfiguration("map"),
72
+ "use_sim_time": LaunchConfiguration("use_sim_time"),
73
+ "params_file": LaunchConfiguration("params_file"),
74
+ "autostart": LaunchConfiguration("autostart"),
75
+ "use_composition": "False",
76
+ "use_respawn": "False",
77
+ }.items(),
78
+ )
79
+
80
+ # Remap Nav2's default cmd_vel if velocity_smoother is in the graph —
81
+ # our bridge listens on /cmd_vel. bringup already uses /cmd_vel by default
82
+ # for the controller; keep a no-op note via a tiny static transform wait
83
+ # is unnecessary. Publish map→odom is AMCL's job once initial pose is set
84
+ # (set_initial_pose: true in nav2_params.yaml).
85
+
86
+ return LaunchDescription(
87
+ [
88
+ gui_arg,
89
+ use_rviz_arg,
90
+ use_sim_time_arg,
91
+ x_arg,
92
+ y_arg,
93
+ z_arg,
94
+ yaw_arg,
95
+ map_arg,
96
+ params_arg,
97
+ autostart_arg,
98
+ sim,
99
+ nav2,
100
+ ]
101
+ )
@@ -0,0 +1,7 @@
1
+ image: agenticros_indoor.pgm
2
+ mode: trinary
3
+ resolution: 0.05
4
+ origin: [-6.0, -6.0, 0.0]
5
+ negate: 0
6
+ occupied_thresh: 0.65
7
+ free_thresh: 0.25
@@ -221,11 +221,28 @@
221
221
  <odom_topic>odometry</odom_topic>
222
222
  <tf_topic>tf</tf_topic>
223
223
  <frame_id>odom</frame_id>
224
- <child_frame_id>base_link</child_frame_id>
224
+ <child_frame_id>base_footprint</child_frame_id>
225
225
  <max_linear_acceleration>1.0</max_linear_acceleration>
226
226
  <max_angular_acceleration>2.0</max_angular_acceleration>
227
227
  </plugin>
228
228
 
229
+ <!--
230
+ Odometry with covariance for ros_gz_bridge on Humble/Jazzy.
231
+ DiffDrive publishes bare gz.msgs.Odometry on /odometry; some Humble
232
+ bridge builds only convert OdometryWithCovariance reliably to
233
+ nav_msgs/Odometry. TF stays on DiffDrive (tf_topic below is unused).
234
+ -->
235
+ <plugin
236
+ filename="gz-sim-odometry-publisher-system"
237
+ name="gz::sim::systems::OdometryPublisher">
238
+ <odom_frame>odom</odom_frame>
239
+ <robot_base_frame>base_footprint</robot_base_frame>
240
+ <odom_topic>odometry</odom_topic>
241
+ <odom_covariance_topic>odometry_with_covariance</odom_covariance_topic>
242
+ <tf_topic>odometry_publisher_tf_unused</tf_topic>
243
+ <dimensions>2</dimensions>
244
+ </plugin>
245
+
229
246
  <plugin filename="gz-sim-joint-state-publisher-system" name="gz::sim::systems::JointStatePublisher">
230
247
  <topic>joint_states</topic>
231
248
  </plugin>
@@ -6,8 +6,9 @@
6
6
  <description>
7
7
  AgenticROS Gazebo Harmonic simulation assets: indoor world, 2-wheel AMR
8
8
  model (depth camera + GPU lidar + IMU), ros_gz_bridge config that exposes
9
- topics on AgenticROS' real-robot topic names, and a launch file that wires
10
- it all together. Use with the agenticros CLI: agenticros up sim-amr.
9
+ topics on AgenticROS real-robot topic names, Nav2 bringup for the indoor
10
+ map (sim_amr_nav2.launch.py), and launch files that wire it all together.
11
+ Use with the agenticros CLI: agenticros up sim-amr [--nav2].
11
12
  </description>
12
13
  <maintainer email="hello@plaipin.com">PlaiPin</maintainer>
13
14
  <license>Apache-2.0</license>
@@ -20,6 +21,18 @@
20
21
  <exec_depend>robot_state_publisher</exec_depend>
21
22
  <exec_depend>xacro</exec_depend>
22
23
  <exec_depend>rviz2</exec_depend>
24
+ <!-- Optional Nav2 stack for `sim_amr_nav2.launch.py` / `agenticros up sim-amr --nav2` -->
25
+ <exec_depend>nav2_bringup</exec_depend>
26
+ <exec_depend>nav2_bt_navigator</exec_depend>
27
+ <exec_depend>nav2_amcl</exec_depend>
28
+ <exec_depend>nav2_map_server</exec_depend>
29
+ <exec_depend>nav2_controller</exec_depend>
30
+ <exec_depend>nav2_planner</exec_depend>
31
+ <exec_depend>nav2_behaviors</exec_depend>
32
+ <exec_depend>nav2_smoother</exec_depend>
33
+ <exec_depend>nav2_waypoint_follower</exec_depend>
34
+ <exec_depend>nav2_velocity_smoother</exec_depend>
35
+ <exec_depend>nav2_lifecycle_manager</exec_depend>
23
36
 
24
37
  <export>
25
38
  <build_type>ament_cmake</build_type>
@@ -19,6 +19,15 @@
19
19
  -->
20
20
  <robot name="agenticros_amr" xmlns:xacro="http://www.ros.org/wiki/xacro">
21
21
 
22
+ <!-- ===================== base_footprint (Nav2 / costmap convention) ===================== -->
23
+ <link name="base_footprint"/>
24
+ <joint name="base_footprint_joint" type="fixed">
25
+ <parent link="base_footprint"/>
26
+ <child link="base_link"/>
27
+ <!-- base_link visual origin is chassis center ~0.10 m above ground -->
28
+ <origin xyz="0 0 0.10" rpy="0 0 0"/>
29
+ </joint>
30
+
22
31
  <!-- ===================== base_link ===================== -->
23
32
  <link name="base_link">
24
33
  <visual>
@@ -7,13 +7,14 @@
7
7
  # tees output to /tmp/agenticros-sim.log so `agenticros logs sim` works.
8
8
  #
9
9
  # Usage:
10
- # run_sim.sh --robot amr [--namespace sim_robot] [--rviz] [--no-gui]
10
+ # run_sim.sh --robot amr [--namespace sim_robot] [--rviz] [--no-gui] [--nav2]
11
11
  #
12
12
  # Flags:
13
13
  # --robot amr|arm Which sim launch to start (default: amr).
14
14
  # --namespace <ns> Robot namespace; exported as AGENTICROS_ROBOT_NAMESPACE.
15
15
  # --rviz Bring up RViz alongside Gazebo.
16
16
  # --no-gui Run gz-sim headless (CI / docker).
17
+ # --nav2 AMR only: also launch Nav2 (map + AMCL + navigation).
17
18
  # --ros-distro <distro> Override ROS 2 distro (auto-detect by default).
18
19
  # --colcon-ws <path> Override the colcon workspace (default: <repo>/ros2_ws).
19
20
  # --help Print this help and exit.
@@ -34,6 +35,7 @@ ROBOT="amr"
34
35
  NAMESPACE=""
35
36
  USE_RVIZ="false"
36
37
  GUI="true"
38
+ USE_NAV2="false"
37
39
  ROS_DISTRO_OVERRIDE=""
38
40
  COLCON_WS=""
39
41
 
@@ -43,10 +45,11 @@ while [[ $# -gt 0 ]]; do
43
45
  --namespace) NAMESPACE="$2"; shift 2 ;;
44
46
  --rviz) USE_RVIZ="true"; shift ;;
45
47
  --no-gui) GUI="false"; shift ;;
48
+ --nav2) USE_NAV2="true"; shift ;;
46
49
  --ros-distro) ROS_DISTRO_OVERRIDE="$2"; shift 2 ;;
47
50
  --colcon-ws) COLCON_WS="$2"; shift 2 ;;
48
51
  -h|--help)
49
- sed -n '2,24p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
52
+ sed -n '2,26p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
50
53
  exit 0 ;;
51
54
  *) echo "Unknown arg: $1" >&2; exit 2 ;;
52
55
  esac
@@ -57,6 +60,11 @@ if [[ "$ROBOT" != "amr" && "$ROBOT" != "arm" ]]; then
57
60
  exit 2
58
61
  fi
59
62
 
63
+ if [[ "$USE_NAV2" == "true" && "$ROBOT" != "amr" ]]; then
64
+ echo "--nav2 is only supported with --robot amr" >&2
65
+ exit 2
66
+ fi
67
+
60
68
  # ---------- paths ----------
61
69
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
62
70
  REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
@@ -85,7 +93,7 @@ fi
85
93
 
86
94
  log "ROS_DISTRO=$ROS_DISTRO"
87
95
  log "COLCON_WS=$COLCON_WS"
88
- log "robot=$ROBOT namespace=${NAMESPACE:-<none>} rviz=$USE_RVIZ gui=$GUI"
96
+ log "robot=$ROBOT namespace=${NAMESPACE:-<none>} rviz=$USE_RVIZ gui=$GUI nav2=$USE_NAV2"
89
97
 
90
98
  # shellcheck disable=SC1090
91
99
  source "/opt/ros/$ROS_DISTRO/setup.bash"
@@ -145,10 +153,23 @@ LAUNCH_ARGS=(
145
153
 
146
154
  # ---------- Pick launch file ----------
147
155
  case "$ROBOT" in
148
- amr) LAUNCH_FILE="sim_amr.launch.py" ;;
149
- arm) LAUNCH_FILE="sim_arm.launch.py" ;; # Phase 3
156
+ amr)
157
+ if [[ "$USE_NAV2" == "true" ]]; then
158
+ LAUNCH_FILE="sim_amr_nav2.launch.py"
159
+ else
160
+ LAUNCH_FILE="sim_amr.launch.py"
161
+ fi
162
+ ;;
163
+ arm) LAUNCH_FILE="sim_arm.launch.py" ;;
150
164
  esac
151
165
 
166
+ if [[ "$USE_NAV2" == "true" ]]; then
167
+ if ! ros2 pkg prefix nav2_bringup >/dev/null 2>&1; then
168
+ err "nav2_bringup not found. Install: sudo apt install ros-\$ROS_DISTRO-nav2-bringup"
169
+ exit 1
170
+ fi
171
+ fi
172
+
152
173
  if ! ros2 launch --help >/dev/null 2>&1; then
153
174
  err "ros2 launch not available — is ROS sourced properly?"
154
175
  exit 1