agenticros 0.1.0 → 0.1.1

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 (41) hide show
  1. package/dist/commands/config.d.ts.map +1 -1
  2. package/dist/commands/config.js +37 -1
  3. package/dist/commands/config.js.map +1 -1
  4. package/dist/commands/down.d.ts +6 -4
  5. package/dist/commands/down.d.ts.map +1 -1
  6. package/dist/commands/down.js +16 -6
  7. package/dist/commands/down.js.map +1 -1
  8. package/dist/commands/logs.js +2 -2
  9. package/dist/commands/logs.js.map +1 -1
  10. package/dist/commands/status.d.ts.map +1 -1
  11. package/dist/commands/status.js +10 -6
  12. package/dist/commands/status.js.map +1 -1
  13. package/dist/commands/up.d.ts +1 -0
  14. package/dist/commands/up.d.ts.map +1 -1
  15. package/dist/commands/up.js +12 -0
  16. package/dist/commands/up.js.map +1 -1
  17. package/dist/index.js +4 -3
  18. package/dist/index.js.map +1 -1
  19. package/dist/runners/sim.d.ts +2 -0
  20. package/dist/runners/sim.d.ts.map +1 -1
  21. package/dist/runners/sim.js +2 -0
  22. package/dist/runners/sim.js.map +1 -1
  23. package/package.json +1 -1
  24. package/runtime/BUNDLE.json +1 -1
  25. package/runtime/packages/core/src/transport/local/transport.ts +25 -5
  26. package/runtime/ros2_ws/src/agenticros_sim/CMakeLists.txt +24 -0
  27. package/runtime/ros2_ws/src/agenticros_sim/README.md +120 -0
  28. package/runtime/ros2_ws/src/agenticros_sim/config/agenticros-sim.config.json +28 -0
  29. package/runtime/ros2_ws/src/agenticros_sim/config/amr_bridge.yaml +111 -0
  30. package/runtime/ros2_ws/src/agenticros_sim/config/amr_view.rviz +172 -0
  31. package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.dsv.in +3 -0
  32. package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.sh.in +7 -0
  33. package/runtime/ros2_ws/src/agenticros_sim/launch/sim_amr.launch.py +159 -0
  34. package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.config +17 -0
  35. package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.sdf +244 -0
  36. package/runtime/ros2_ws/src/agenticros_sim/package.xml +27 -0
  37. package/runtime/ros2_ws/src/agenticros_sim/worlds/agenticros_indoor.sdf +183 -0
  38. package/runtime/scripts/configure_for_sim.sh +64 -0
  39. package/runtime/scripts/sim/run_sim.sh +146 -0
  40. package/runtime/scripts/test-follow-me-sim.mjs +135 -0
  41. package/runtime/scripts/test-mcp-e2e.mjs +184 -0
@@ -0,0 +1,244 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ agenticros_amr/model.sdf
4
+ Two-wheel differential-drive AMR with:
5
+ * Chassis link (rectangular)
6
+ * Two driven wheels + one passive caster
7
+ * Forward-facing RGB-D camera (RealSense D435-ish: 640x480 colour + 16-bit depth)
8
+ * 2D GPU lidar (RPLidar-like, 360°, 12 Hz)
9
+ * IMU
10
+ * gz-sim diff-drive + odometry + joint-state systems
11
+
12
+ Topic layout (Gazebo side; ros_gz_bridge translates to ROS):
13
+ cmd_vel → /model/agenticros_amr/cmd_vel
14
+ odom → /model/agenticros_amr/odometry
15
+ tf → /model/agenticros_amr/tf
16
+ rgb image → /camera/camera/color/image_raw (matches real RealSense)
17
+ rgb camera_info → /camera/camera/color/camera_info
18
+ depth image (16UC1) → /camera/camera/depth/image_rect_raw
19
+ depth camera_info → /camera/camera/depth/camera_info
20
+ lidar scan → /scan
21
+ imu → /imu/data
22
+ -->
23
+ <sdf version="1.10">
24
+ <model name="agenticros_amr">
25
+
26
+ <!-- ===================== Chassis ===================== -->
27
+ <link name="base_link">
28
+ <pose>0 0 0.10 0 0 0</pose>
29
+ <inertial>
30
+ <mass>5.0</mass>
31
+ <inertia>
32
+ <ixx>0.10</ixx><iyy>0.15</iyy><izz>0.20</izz>
33
+ <ixy>0</ixy><ixz>0</ixz><iyz>0</iyz>
34
+ </inertia>
35
+ </inertial>
36
+ <collision name="chassis_col">
37
+ <geometry><box><size>0.40 0.30 0.15</size></box></geometry>
38
+ </collision>
39
+ <visual name="chassis_vis">
40
+ <geometry><box><size>0.40 0.30 0.15</size></box></geometry>
41
+ <material><ambient>0.2 0.2 0.25 1</ambient><diffuse>0.3 0.3 0.35 1</diffuse></material>
42
+ </visual>
43
+
44
+ <!-- ============ RealSense-D435-like depth camera ============ -->
45
+ <!--
46
+ Mounted at front of the chassis, 0.10 m above the chassis top, looking
47
+ forward (+X). HFOV 87° matches the real D435 depth sensor; FOLLOW_ME
48
+ depth-loop code already assumes this HFOV constant.
49
+ -->
50
+ <sensor name="depth_camera" type="rgbd_camera">
51
+ <pose>0.20 0 0.18 0 0 0</pose>
52
+ <topic>camera</topic>
53
+ <update_rate>30</update_rate>
54
+ <camera>
55
+ <horizontal_fov>1.5184</horizontal_fov>
56
+ <image>
57
+ <width>640</width>
58
+ <height>480</height>
59
+ <format>R8G8B8</format>
60
+ </image>
61
+ <clip>
62
+ <near>0.10</near>
63
+ <far>10.0</far>
64
+ </clip>
65
+ <distortion>
66
+ <k1>0.0</k1><k2>0.0</k2><k3>0.0</k3><p1>0.0</p1><p2>0.0</p2>
67
+ </distortion>
68
+ <optical_frame_id>camera_optical_link</optical_frame_id>
69
+ <depth_camera>
70
+ <output>depths</output>
71
+ </depth_camera>
72
+ </camera>
73
+ <always_on>true</always_on>
74
+ <visualize>false</visualize>
75
+ </sensor>
76
+
77
+ <!-- ============ 2D GPU lidar (RPLidar-ish) ============ -->
78
+ <sensor name="gpu_lidar" type="gpu_lidar">
79
+ <pose>0 0 0.20 0 0 0</pose>
80
+ <topic>scan</topic>
81
+ <update_rate>12</update_rate>
82
+ <lidar>
83
+ <scan>
84
+ <horizontal>
85
+ <samples>360</samples>
86
+ <resolution>1</resolution>
87
+ <min_angle>-3.14159</min_angle>
88
+ <max_angle>3.14159</max_angle>
89
+ </horizontal>
90
+ </scan>
91
+ <range>
92
+ <min>0.10</min>
93
+ <max>12.0</max>
94
+ <resolution>0.01</resolution>
95
+ </range>
96
+ <noise>
97
+ <type>gaussian</type><mean>0.0</mean><stddev>0.01</stddev>
98
+ </noise>
99
+ <frame_id>lidar_link</frame_id>
100
+ </lidar>
101
+ <always_on>true</always_on>
102
+ <visualize>false</visualize>
103
+ </sensor>
104
+
105
+ <!-- ============ IMU ============ -->
106
+ <sensor name="imu_sensor" type="imu">
107
+ <pose>0 0 0 0 0 0</pose>
108
+ <topic>imu</topic>
109
+ <update_rate>100</update_rate>
110
+ <imu>
111
+ <angular_velocity>
112
+ <x><noise type="gaussian"><mean>0.0</mean><stddev>0.0005</stddev></noise></x>
113
+ <y><noise type="gaussian"><mean>0.0</mean><stddev>0.0005</stddev></noise></y>
114
+ <z><noise type="gaussian"><mean>0.0</mean><stddev>0.0005</stddev></noise></z>
115
+ </angular_velocity>
116
+ <linear_acceleration>
117
+ <x><noise type="gaussian"><mean>0.0</mean><stddev>0.005</stddev></noise></x>
118
+ <y><noise type="gaussian"><mean>0.0</mean><stddev>0.005</stddev></noise></y>
119
+ <z><noise type="gaussian"><mean>0.0</mean><stddev>0.005</stddev></noise></z>
120
+ </linear_acceleration>
121
+ </imu>
122
+ <always_on>true</always_on>
123
+ </sensor>
124
+ </link>
125
+
126
+ <!-- ===================== Left wheel ===================== -->
127
+ <link name="left_wheel_link">
128
+ <pose>0 0.18 0.08 -1.5707 0 0</pose>
129
+ <inertial>
130
+ <mass>0.5</mass>
131
+ <inertia><ixx>0.0008</ixx><iyy>0.0008</iyy><izz>0.0015</izz><ixy>0</ixy><ixz>0</ixz><iyz>0</iyz></inertia>
132
+ </inertial>
133
+ <collision name="col">
134
+ <geometry><cylinder><radius>0.08</radius><length>0.04</length></cylinder></geometry>
135
+ <surface><friction><ode><mu>1.0</mu><mu2>1.0</mu2></ode></friction></surface>
136
+ </collision>
137
+ <visual name="vis">
138
+ <geometry><cylinder><radius>0.08</radius><length>0.04</length></cylinder></geometry>
139
+ <material><ambient>0.1 0.1 0.1 1</ambient><diffuse>0.15 0.15 0.15 1</diffuse></material>
140
+ </visual>
141
+ </link>
142
+
143
+ <!-- ===================== Right wheel ===================== -->
144
+ <link name="right_wheel_link">
145
+ <pose>0 -0.18 0.08 -1.5707 0 0</pose>
146
+ <inertial>
147
+ <mass>0.5</mass>
148
+ <inertia><ixx>0.0008</ixx><iyy>0.0008</iyy><izz>0.0015</izz><ixy>0</ixy><ixz>0</ixz><iyz>0</iyz></inertia>
149
+ </inertial>
150
+ <collision name="col">
151
+ <geometry><cylinder><radius>0.08</radius><length>0.04</length></cylinder></geometry>
152
+ <surface><friction><ode><mu>1.0</mu><mu2>1.0</mu2></ode></friction></surface>
153
+ </collision>
154
+ <visual name="vis">
155
+ <geometry><cylinder><radius>0.08</radius><length>0.04</length></cylinder></geometry>
156
+ <material><ambient>0.1 0.1 0.1 1</ambient><diffuse>0.15 0.15 0.15 1</diffuse></material>
157
+ </visual>
158
+ </link>
159
+
160
+ <!-- ===================== Caster (passive front wheel) ===================== -->
161
+ <link name="caster_link">
162
+ <pose>0.16 0 0.04 0 0 0</pose>
163
+ <inertial>
164
+ <mass>0.1</mass>
165
+ <inertia><ixx>0.00004</ixx><iyy>0.00004</iyy><izz>0.00004</izz><ixy>0</ixy><ixz>0</ixz><iyz>0</iyz></inertia>
166
+ </inertial>
167
+ <collision name="col">
168
+ <geometry><sphere><radius>0.04</radius></sphere></geometry>
169
+ <surface><friction><ode><mu>0.05</mu><mu2>0.05</mu2></ode></friction></surface>
170
+ </collision>
171
+ <visual name="vis">
172
+ <geometry><sphere><radius>0.04</radius></sphere></geometry>
173
+ <material><ambient>0.1 0.1 0.1 1</ambient><diffuse>0.15 0.15 0.15 1</diffuse></material>
174
+ </visual>
175
+ </link>
176
+
177
+ <!-- ===================== Joints ===================== -->
178
+ <joint name="left_wheel_joint" type="revolute">
179
+ <parent>base_link</parent>
180
+ <child>left_wheel_link</child>
181
+ <axis>
182
+ <xyz>0 0 1</xyz>
183
+ <limit><lower>-1e16</lower><upper>1e16</upper></limit>
184
+ </axis>
185
+ </joint>
186
+
187
+ <joint name="right_wheel_joint" type="revolute">
188
+ <parent>base_link</parent>
189
+ <child>right_wheel_link</child>
190
+ <axis>
191
+ <xyz>0 0 1</xyz>
192
+ <limit><lower>-1e16</lower><upper>1e16</upper></limit>
193
+ </axis>
194
+ </joint>
195
+
196
+ <joint name="caster_joint" type="ball">
197
+ <parent>base_link</parent>
198
+ <child>caster_link</child>
199
+ </joint>
200
+
201
+ <!-- ===================== Plugins ===================== -->
202
+ <!--
203
+ Differential drive: subscribes to /model/agenticros_amr/cmd_vel and drives
204
+ the wheels. Publishes /model/agenticros_amr/odometry and tf as gz topics
205
+ that the bridge re-emits as ROS topics.
206
+ -->
207
+ <plugin filename="gz-sim-diff-drive-system" name="gz::sim::systems::DiffDrive">
208
+ <left_joint>left_wheel_joint</left_joint>
209
+ <right_joint>right_wheel_joint</right_joint>
210
+ <wheel_separation>0.36</wheel_separation>
211
+ <wheel_radius>0.08</wheel_radius>
212
+ <odom_publish_frequency>50</odom_publish_frequency>
213
+ <topic>cmd_vel</topic>
214
+ <odom_topic>odometry</odom_topic>
215
+ <tf_topic>tf</tf_topic>
216
+ <frame_id>odom</frame_id>
217
+ <child_frame_id>base_link</child_frame_id>
218
+ <max_linear_acceleration>1.0</max_linear_acceleration>
219
+ <max_angular_acceleration>2.0</max_angular_acceleration>
220
+ </plugin>
221
+
222
+ <plugin filename="gz-sim-joint-state-publisher-system" name="gz::sim::systems::JointStatePublisher">
223
+ <topic>joint_states</topic>
224
+ </plugin>
225
+
226
+ <!--
227
+ Pose publisher: every link's pose relative to the world. Useful for RViz
228
+ visualization without running robot_state_publisher with a URDF — but
229
+ note ROS tools generally expect /tf, which the diff-drive plugin
230
+ provides for the base + odom relationship.
231
+ -->
232
+ <plugin filename="gz-sim-pose-publisher-system" name="gz::sim::systems::PosePublisher">
233
+ <publish_link_pose>true</publish_link_pose>
234
+ <publish_sensor_pose>true</publish_sensor_pose>
235
+ <publish_collision_pose>false</publish_collision_pose>
236
+ <publish_visual_pose>false</publish_visual_pose>
237
+ <publish_nested_model_pose>false</publish_nested_model_pose>
238
+ <use_pose_vector_msg>true</use_pose_vector_msg>
239
+ <static_publisher>true</static_publisher>
240
+ <static_update_frequency>1</static_update_frequency>
241
+ </plugin>
242
+
243
+ </model>
244
+ </sdf>
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0"?>
2
+ <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
3
+ <package format="3">
4
+ <name>agenticros_sim</name>
5
+ <version>0.1.0</version>
6
+ <description>
7
+ AgenticROS Gazebo Harmonic simulation assets: indoor world, 2-wheel AMR
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.
11
+ </description>
12
+ <maintainer email="hello@plaipin.com">PlaiPin</maintainer>
13
+ <license>Apache-2.0</license>
14
+
15
+ <buildtool_depend>ament_cmake</buildtool_depend>
16
+
17
+ <exec_depend>ros_gz_sim</exec_depend>
18
+ <exec_depend>ros_gz_bridge</exec_depend>
19
+ <exec_depend>ros_gz_image</exec_depend>
20
+ <exec_depend>robot_state_publisher</exec_depend>
21
+ <exec_depend>xacro</exec_depend>
22
+ <exec_depend>rviz2</exec_depend>
23
+
24
+ <export>
25
+ <build_type>ament_cmake</build_type>
26
+ </export>
27
+ </package>
@@ -0,0 +1,183 @@
1
+ <?xml version="1.0"?>
2
+ <!--
3
+ agenticros_indoor.sdf
4
+ Gazebo Harmonic 8.x indoor environment for testing AgenticROS' sim AMR.
5
+
6
+ Layout:
7
+ * 12 m x 12 m floor with subtle walls (so SLAM-style demos have something
8
+ to localize against)
9
+ * Three free-standing cylinder + box obstacles inside the room so the
10
+ depth camera and LIDAR see non-trivial data
11
+ * One human-sized cylinder labeled "person" near the center — used by the
12
+ ros2_follow_me smoke test
13
+ * Standard physics + sensors + ros_gz system plugins so the AMR's depth
14
+ camera / IMU / lidar publish on Gazebo topics that the bridge picks up
15
+ -->
16
+ <sdf version="1.10">
17
+ <world name="agenticros_indoor">
18
+
19
+ <!-- ====== System plugins ====== -->
20
+ <plugin filename="gz-sim-physics-system" name="gz::sim::systems::Physics"/>
21
+ <plugin filename="gz-sim-sensors-system" name="gz::sim::systems::Sensors">
22
+ <render_engine>ogre2</render_engine>
23
+ </plugin>
24
+ <plugin filename="gz-sim-user-commands-system" name="gz::sim::systems::UserCommands"/>
25
+ <plugin filename="gz-sim-scene-broadcaster-system" name="gz::sim::systems::SceneBroadcaster"/>
26
+ <plugin filename="gz-sim-imu-system" name="gz::sim::systems::Imu"/>
27
+
28
+ <gravity>0 0 -9.81</gravity>
29
+
30
+ <gui fullscreen="false">
31
+ <plugin filename="MinimalScene" name="3D View">
32
+ <gz-gui>
33
+ <title>3D View</title>
34
+ <property type="bool" key="showTitleBar">false</property>
35
+ <property type="string" key="state">docked</property>
36
+ </gz-gui>
37
+ <engine>ogre2</engine>
38
+ <scene>scene</scene>
39
+ <ambient_light>0.4 0.4 0.4</ambient_light>
40
+ <background_color>0.8 0.8 0.8</background_color>
41
+ <camera_pose>-7 -7 6 0 0.6 0.78</camera_pose>
42
+ </plugin>
43
+ </gui>
44
+
45
+ <!-- ====== Lighting ====== -->
46
+ <light type="directional" name="sun">
47
+ <cast_shadows>true</cast_shadows>
48
+ <pose>0 0 10 0 0 0</pose>
49
+ <diffuse>0.9 0.9 0.9 1</diffuse>
50
+ <specular>0.2 0.2 0.2 1</specular>
51
+ <direction>-0.3 0.2 -0.9</direction>
52
+ </light>
53
+
54
+ <!-- ====== Ground ====== -->
55
+ <model name="ground_plane">
56
+ <static>true</static>
57
+ <link name="link">
58
+ <collision name="collision">
59
+ <geometry><plane><normal>0 0 1</normal><size>20 20</size></plane></geometry>
60
+ </collision>
61
+ <visual name="visual">
62
+ <geometry><plane><normal>0 0 1</normal><size>20 20</size></plane></geometry>
63
+ <material>
64
+ <ambient>0.6 0.6 0.6 1</ambient>
65
+ <diffuse>0.75 0.75 0.75 1</diffuse>
66
+ <specular>0.05 0.05 0.05 1</specular>
67
+ </material>
68
+ </visual>
69
+ </link>
70
+ </model>
71
+
72
+ <!-- ====== Walls (12m x 12m room, 2.5m tall, 0.15m thick) ====== -->
73
+ <model name="walls">
74
+ <static>true</static>
75
+ <link name="link">
76
+ <!-- North wall (+Y) -->
77
+ <collision name="north_col">
78
+ <pose>0 6 1.25 0 0 0</pose>
79
+ <geometry><box><size>12 0.15 2.5</size></box></geometry>
80
+ </collision>
81
+ <visual name="north_vis">
82
+ <pose>0 6 1.25 0 0 0</pose>
83
+ <geometry><box><size>12 0.15 2.5</size></box></geometry>
84
+ <material><ambient>0.85 0.85 0.9 1</ambient><diffuse>0.9 0.9 0.95 1</diffuse></material>
85
+ </visual>
86
+ <!-- South wall (-Y) -->
87
+ <collision name="south_col">
88
+ <pose>0 -6 1.25 0 0 0</pose>
89
+ <geometry><box><size>12 0.15 2.5</size></box></geometry>
90
+ </collision>
91
+ <visual name="south_vis">
92
+ <pose>0 -6 1.25 0 0 0</pose>
93
+ <geometry><box><size>12 0.15 2.5</size></box></geometry>
94
+ <material><ambient>0.85 0.85 0.9 1</ambient><diffuse>0.9 0.9 0.95 1</diffuse></material>
95
+ </visual>
96
+ <!-- East wall (+X) -->
97
+ <collision name="east_col">
98
+ <pose>6 0 1.25 0 0 0</pose>
99
+ <geometry><box><size>0.15 12 2.5</size></box></geometry>
100
+ </collision>
101
+ <visual name="east_vis">
102
+ <pose>6 0 1.25 0 0 0</pose>
103
+ <geometry><box><size>0.15 12 2.5</size></box></geometry>
104
+ <material><ambient>0.85 0.85 0.9 1</ambient><diffuse>0.9 0.9 0.95 1</diffuse></material>
105
+ </visual>
106
+ <!-- West wall (-X) -->
107
+ <collision name="west_col">
108
+ <pose>-6 0 1.25 0 0 0</pose>
109
+ <geometry><box><size>0.15 12 2.5</size></box></geometry>
110
+ </collision>
111
+ <visual name="west_vis">
112
+ <pose>-6 0 1.25 0 0 0</pose>
113
+ <geometry><box><size>0.15 12 2.5</size></box></geometry>
114
+ <material><ambient>0.85 0.85 0.9 1</ambient><diffuse>0.9 0.9 0.95 1</diffuse></material>
115
+ </visual>
116
+ </link>
117
+ </model>
118
+
119
+ <!-- ====== Person-sized cylinder (for ros2_follow_me depth-mode smoke test) ====== -->
120
+ <!--
121
+ Roughly human-shaped: 0.35 m radius, 1.7 m tall, centered ~2.5 m in front
122
+ of the AMR's spawn pose (the AMR spawns at origin facing +X by default).
123
+ -->
124
+ <model name="person_target">
125
+ <!-- Static so it doesn't drift or topple when nudged by the AMR. The
126
+ follow-me smoke test just needs a person-sized object in front of
127
+ the spawn pose; dynamics would make the smoke test flaky. -->
128
+ <static>true</static>
129
+ <pose>2.5 0 0.85 0 0 0</pose>
130
+ <link name="link">
131
+ <inertial>
132
+ <mass>60</mass>
133
+ <inertia><ixx>14.7</ixx><iyy>14.7</iyy><izz>3.7</izz><ixy>0</ixy><ixz>0</ixz><iyz>0</iyz></inertia>
134
+ </inertial>
135
+ <collision name="collision">
136
+ <geometry><cylinder><radius>0.35</radius><length>1.7</length></cylinder></geometry>
137
+ </collision>
138
+ <visual name="visual">
139
+ <geometry><cylinder><radius>0.35</radius><length>1.7</length></cylinder></geometry>
140
+ <material><ambient>0.7 0.4 0.3 1</ambient><diffuse>0.8 0.5 0.4 1</diffuse></material>
141
+ </visual>
142
+ </link>
143
+ </model>
144
+
145
+ <!-- ====== A few static obstacles to give the LIDAR / depth camera structure ====== -->
146
+ <model name="obstacle_box_1">
147
+ <static>true</static>
148
+ <pose>3 -2.5 0.4 0 0 0</pose>
149
+ <link name="link">
150
+ <collision name="c"><geometry><box><size>0.8 0.8 0.8</size></box></geometry></collision>
151
+ <visual name="v">
152
+ <geometry><box><size>0.8 0.8 0.8</size></box></geometry>
153
+ <material><ambient>0.3 0.5 0.7 1</ambient><diffuse>0.3 0.5 0.7 1</diffuse></material>
154
+ </visual>
155
+ </link>
156
+ </model>
157
+
158
+ <model name="obstacle_cyl_1">
159
+ <static>true</static>
160
+ <pose>-2 2.5 0.6 0 0 0</pose>
161
+ <link name="link">
162
+ <collision name="c"><geometry><cylinder><radius>0.35</radius><length>1.2</length></cylinder></geometry></collision>
163
+ <visual name="v">
164
+ <geometry><cylinder><radius>0.35</radius><length>1.2</length></cylinder></geometry>
165
+ <material><ambient>0.7 0.6 0.2 1</ambient><diffuse>0.8 0.7 0.2 1</diffuse></material>
166
+ </visual>
167
+ </link>
168
+ </model>
169
+
170
+ <model name="obstacle_box_2">
171
+ <static>true</static>
172
+ <pose>-3.5 -3 0.3 0 0 0</pose>
173
+ <link name="link">
174
+ <collision name="c"><geometry><box><size>1.2 0.6 0.6</size></box></geometry></collision>
175
+ <visual name="v">
176
+ <geometry><box><size>1.2 0.6 0.6</size></box></geometry>
177
+ <material><ambient>0.3 0.7 0.4 1</ambient><diffuse>0.3 0.8 0.4 1</diffuse></material>
178
+ </visual>
179
+ </link>
180
+ </model>
181
+
182
+ </world>
183
+ </sdf>
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env bash
2
+ # configure_for_sim.sh
3
+ #
4
+ # One-shot helper: copy the simulation-tuned AgenticROS config template into
5
+ # ~/.agenticros/config.json. Use this when you want the MCP server + OpenClaw
6
+ # plugin to talk to the sim AMR's topics (which use no robot-namespace
7
+ # prefix - so a fresh "real robot" config with a UUID namespace would miss
8
+ # every topic).
9
+ #
10
+ # Usage:
11
+ # ./scripts/configure_for_sim.sh # writes ~/.agenticros/config.json
12
+ # ./scripts/configure_for_sim.sh --backup # back up an existing config first
13
+ # ./scripts/configure_for_sim.sh --print # print the template to stdout
14
+ #
15
+ # After running, restart the MCP server (or run `agenticros up sim-amr`).
16
+
17
+ set -euo pipefail
18
+
19
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
20
+ SRC="$ROOT/ros2_ws/src/agenticros_sim/config/agenticros-sim.config.json"
21
+ DEST_DIR="$HOME/.agenticros"
22
+ DEST="$DEST_DIR/config.json"
23
+
24
+ PRINT_ONLY=false
25
+ DO_BACKUP=false
26
+
27
+ while [[ $# -gt 0 ]]; do
28
+ case "$1" in
29
+ --print) PRINT_ONLY=true; shift ;;
30
+ --backup) DO_BACKUP=true; shift ;;
31
+ -h|--help) sed -n '2,16p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0 ;;
32
+ *) echo "Unknown arg: $1" >&2; exit 2 ;;
33
+ esac
34
+ done
35
+
36
+ if [[ ! -f "$SRC" ]]; then
37
+ echo "Template missing: $SRC" >&2
38
+ echo "Did you build the ros2 workspace? (cd $ROOT/ros2_ws && colcon build)" >&2
39
+ exit 1
40
+ fi
41
+
42
+ if [[ "$PRINT_ONLY" == "true" ]]; then
43
+ cat "$SRC"
44
+ exit 0
45
+ fi
46
+
47
+ mkdir -p "$DEST_DIR"
48
+
49
+ if [[ -f "$DEST" ]]; then
50
+ if [[ "$DO_BACKUP" == "true" ]]; then
51
+ BAK="${DEST}.real.$(date +%Y%m%d-%H%M%S).bak"
52
+ cp -a "$DEST" "$BAK"
53
+ echo "[configure_for_sim] Backed up existing config -> $BAK"
54
+ else
55
+ echo "[configure_for_sim] $DEST already exists. Re-run with --backup to keep a copy." >&2
56
+ echo "[configure_for_sim] Aborting (use --backup to overwrite)." >&2
57
+ exit 1
58
+ fi
59
+ fi
60
+
61
+ cp "$SRC" "$DEST"
62
+ echo "[configure_for_sim] Wrote $DEST"
63
+ echo "[configure_for_sim] Inspect with: agenticros config show"
64
+ echo "[configure_for_sim] Bring up sim with: agenticros up sim-amr"
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env bash
2
+ # scripts/sim/run_sim.sh
3
+ #
4
+ # Worker script invoked by `agenticros up sim-amr` (and later `sim-arm`). Sources
5
+ # ROS 2 + the AgenticROS overlay, runs `ros2 launch agenticros_sim ...`, writes
6
+ # its PID into /tmp/agenticros-sim.pid so `agenticros down` can stop it, and
7
+ # tees output to /tmp/agenticros-sim.log so `agenticros logs sim` works.
8
+ #
9
+ # Usage:
10
+ # run_sim.sh --robot amr [--namespace sim_robot] [--rviz] [--no-gui]
11
+ #
12
+ # Flags:
13
+ # --robot amr|arm Which sim launch to start (default: amr).
14
+ # --namespace <ns> Robot namespace; exported as AGENTICROS_ROBOT_NAMESPACE.
15
+ # --rviz Bring up RViz alongside Gazebo.
16
+ # --no-gui Run gz-sim headless (CI / docker).
17
+ # --ros-distro <distro> Override ROS 2 distro (auto-detect by default).
18
+ # --colcon-ws <path> Override the colcon workspace (default: <repo>/ros2_ws).
19
+ # --help Print this help and exit.
20
+ #
21
+ # Exit codes:
22
+ # 0 sim exited cleanly
23
+ # 1 missing dependency (gz, ros2, ros_gz_*, our launch file)
24
+ # 2 bad CLI usage
25
+ # 3 sim crashed at runtime — check /tmp/agenticros-sim.log
26
+
27
+ # Strict mode, but `set -u` clashes with ROS setup scripts that reference
28
+ # AMENT_TRACE_SETUP_FILES etc. We toggle nounset off around each `source`.
29
+ set -eo pipefail
30
+ shopt -s expand_aliases || true
31
+
32
+ # ---------- args ----------
33
+ ROBOT="amr"
34
+ NAMESPACE=""
35
+ USE_RVIZ="false"
36
+ GUI="true"
37
+ ROS_DISTRO_OVERRIDE=""
38
+ COLCON_WS=""
39
+
40
+ while [[ $# -gt 0 ]]; do
41
+ case "$1" in
42
+ --robot) ROBOT="$2"; shift 2 ;;
43
+ --namespace) NAMESPACE="$2"; shift 2 ;;
44
+ --rviz) USE_RVIZ="true"; shift ;;
45
+ --no-gui) GUI="false"; shift ;;
46
+ --ros-distro) ROS_DISTRO_OVERRIDE="$2"; shift 2 ;;
47
+ --colcon-ws) COLCON_WS="$2"; shift 2 ;;
48
+ -h|--help)
49
+ sed -n '2,24p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'
50
+ exit 0 ;;
51
+ *) echo "Unknown arg: $1" >&2; exit 2 ;;
52
+ esac
53
+ done
54
+
55
+ if [[ "$ROBOT" != "amr" && "$ROBOT" != "arm" ]]; then
56
+ echo "--robot must be 'amr' or 'arm' (got '$ROBOT')" >&2
57
+ exit 2
58
+ fi
59
+
60
+ # ---------- paths ----------
61
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
62
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
63
+ COLCON_WS="${COLCON_WS:-$REPO_ROOT/ros2_ws}"
64
+
65
+ LOG_FILE="/tmp/agenticros-sim.log"
66
+ PID_FILE="/tmp/agenticros-sim.pid"
67
+
68
+ log() { printf "\033[36m[run_sim]\033[0m %s\n" "$*"; }
69
+ err() { printf "\033[31m[run_sim]\033[0m %s\n" "$*" >&2; }
70
+
71
+ # ---------- ROS 2 distro detection ----------
72
+ if [[ -n "$ROS_DISTRO_OVERRIDE" ]]; then
73
+ ROS_DISTRO="$ROS_DISTRO_OVERRIDE"
74
+ elif [[ -n "${ROS_DISTRO:-}" ]]; then
75
+ : # already sourced
76
+ else
77
+ for d in humble jazzy iron rolling; do
78
+ if [[ -f "/opt/ros/$d/setup.bash" ]]; then ROS_DISTRO="$d"; break; fi
79
+ done
80
+ fi
81
+ if [[ -z "${ROS_DISTRO:-}" ]] || [[ ! -f "/opt/ros/$ROS_DISTRO/setup.bash" ]]; then
82
+ err "ROS 2 not found under /opt/ros/. Install Humble or Jazzy first."
83
+ exit 1
84
+ fi
85
+
86
+ log "ROS_DISTRO=$ROS_DISTRO"
87
+ log "COLCON_WS=$COLCON_WS"
88
+ log "robot=$ROBOT namespace=${NAMESPACE:-<none>} rviz=$USE_RVIZ gui=$GUI"
89
+
90
+ # shellcheck disable=SC1090
91
+ source "/opt/ros/$ROS_DISTRO/setup.bash"
92
+
93
+ # ---------- Build agenticros_sim if not yet built ----------
94
+ if [[ ! -f "$COLCON_WS/install/agenticros_sim/share/agenticros_sim/launch/sim_amr.launch.py" ]]; then
95
+ log "agenticros_sim not built in $COLCON_WS — building now..."
96
+ (cd "$COLCON_WS" && colcon build --symlink-install --packages-select agenticros_sim agenticros_msgs)
97
+ fi
98
+
99
+ # shellcheck disable=SC1090
100
+ source "$COLCON_WS/install/setup.bash"
101
+
102
+ # ---------- Dependency checks ----------
103
+ for bin in gz ros2 rviz2; do
104
+ if ! command -v "$bin" >/dev/null; then
105
+ if [[ "$bin" == "rviz2" ]] && [[ "$USE_RVIZ" != "true" ]]; then
106
+ continue
107
+ fi
108
+ err "Required binary '$bin' not found on PATH."
109
+ exit 1
110
+ fi
111
+ done
112
+
113
+ # ---------- Wire up environment ----------
114
+ if [[ -n "$NAMESPACE" ]]; then
115
+ export AGENTICROS_ROBOT_NAMESPACE="$NAMESPACE"
116
+ fi
117
+
118
+ LAUNCH_ARGS=(
119
+ "use_rviz:=$USE_RVIZ"
120
+ "gui:=$GUI"
121
+ )
122
+
123
+ # ---------- Pick launch file ----------
124
+ case "$ROBOT" in
125
+ amr) LAUNCH_FILE="sim_amr.launch.py" ;;
126
+ arm) LAUNCH_FILE="sim_arm.launch.py" ;; # Phase 3
127
+ esac
128
+
129
+ if ! ros2 launch --help >/dev/null 2>&1; then
130
+ err "ros2 launch not available — is ROS sourced properly?"
131
+ exit 1
132
+ fi
133
+
134
+ log "Logging to $LOG_FILE"
135
+ log "ros2 launch agenticros_sim $LAUNCH_FILE ${LAUNCH_ARGS[*]}"
136
+ log "Press Ctrl+C to stop (or run \`agenticros down\` from another terminal)."
137
+
138
+ # Run in foreground so Ctrl+C in the parent shell still works, but also tee to
139
+ # the log so `agenticros logs sim -f` can follow concurrently. The PID we record
140
+ # is this script's own PID so `agenticros down` SIGTERMs the whole subtree.
141
+ echo "$$" > "$PID_FILE"
142
+
143
+ # Use `exec` so the ros2 process replaces our shell — that way signals from the
144
+ # CLI (or Ctrl+C) hit ros2 directly instead of bash.
145
+ exec 1> >(tee -a "$LOG_FILE") 2>&1
146
+ exec ros2 launch agenticros_sim "$LAUNCH_FILE" "${LAUNCH_ARGS[@]}"