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.
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +37 -1
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/down.d.ts +6 -4
- package/dist/commands/down.d.ts.map +1 -1
- package/dist/commands/down.js +16 -6
- package/dist/commands/down.js.map +1 -1
- package/dist/commands/logs.js +2 -2
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +10 -6
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/up.d.ts +1 -0
- package/dist/commands/up.d.ts.map +1 -1
- package/dist/commands/up.js +12 -0
- package/dist/commands/up.js.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/runners/sim.d.ts +2 -0
- package/dist/runners/sim.d.ts.map +1 -1
- package/dist/runners/sim.js +2 -0
- package/dist/runners/sim.js.map +1 -1
- package/package.json +1 -1
- package/runtime/BUNDLE.json +1 -1
- package/runtime/packages/core/src/transport/local/transport.ts +25 -5
- package/runtime/ros2_ws/src/agenticros_sim/CMakeLists.txt +24 -0
- package/runtime/ros2_ws/src/agenticros_sim/README.md +120 -0
- package/runtime/ros2_ws/src/agenticros_sim/config/agenticros-sim.config.json +28 -0
- package/runtime/ros2_ws/src/agenticros_sim/config/amr_bridge.yaml +111 -0
- package/runtime/ros2_ws/src/agenticros_sim/config/amr_view.rviz +172 -0
- package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.dsv.in +3 -0
- package/runtime/ros2_ws/src/agenticros_sim/env-hooks/gz_resource_path.sh.in +7 -0
- package/runtime/ros2_ws/src/agenticros_sim/launch/sim_amr.launch.py +159 -0
- package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.config +17 -0
- package/runtime/ros2_ws/src/agenticros_sim/models/agenticros_amr/model.sdf +244 -0
- package/runtime/ros2_ws/src/agenticros_sim/package.xml +27 -0
- package/runtime/ros2_ws/src/agenticros_sim/worlds/agenticros_indoor.sdf +183 -0
- package/runtime/scripts/configure_for_sim.sh +64 -0
- package/runtime/scripts/sim/run_sim.sh +146 -0
- package/runtime/scripts/test-follow-me-sim.mjs +135 -0
- package/runtime/scripts/test-mcp-e2e.mjs +184 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "AgenticROS config template tuned for sim-amr. Drop this in ~/.agenticros/config.json (or run `agenticros init` and answer 'simulation') to point the MCP server + OpenClaw plugin at the sim's topics. All values match agenticros_sim/config/amr_bridge.yaml. NOTE: robot.namespace is intentionally empty - the sim bridge publishes /cmd_vel, /scan, /imu/data, etc. at the graph root (no robot prefix), so AgenticROS must NOT namespace topics. For multi-robot sim, prefix the topics in amr_bridge.yaml and set namespace here to match.",
|
|
3
|
+
"transport": {
|
|
4
|
+
"mode": "local"
|
|
5
|
+
},
|
|
6
|
+
"robot": {
|
|
7
|
+
"namespace": "",
|
|
8
|
+
"name": "Sim AMR",
|
|
9
|
+
"cameraTopic": "/camera/camera/color/image_raw"
|
|
10
|
+
},
|
|
11
|
+
"safety": {
|
|
12
|
+
"maxLinearVelocity": 0.5,
|
|
13
|
+
"maxAngularVelocity": 1.0
|
|
14
|
+
},
|
|
15
|
+
"teleop": {
|
|
16
|
+
"cmdVelTopic": "/cmd_vel",
|
|
17
|
+
"speedDefault": 0.2,
|
|
18
|
+
"cameraTopics": [
|
|
19
|
+
{ "topic": "/camera/camera/color/image_raw", "label": "Sim RGB" },
|
|
20
|
+
{ "topic": "/camera/camera/depth/image_rect_raw", "label": "Sim depth" }
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"skills": {
|
|
24
|
+
"followme": {
|
|
25
|
+
"depthTopic": "/camera/camera/depth/image_rect_raw"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# amr_bridge.yaml
|
|
2
|
+
#
|
|
3
|
+
# Maps Gazebo Harmonic topics produced by the AMR model + world plugins to
|
|
4
|
+
# ROS 2 topics on the names the real-robot AgenticROS plugin already expects.
|
|
5
|
+
# Used by ros_gz_bridge's parameter_bridge node via the `config_file` arg.
|
|
6
|
+
#
|
|
7
|
+
# Key invariant: the camera topic names below match the RealSense ROS driver
|
|
8
|
+
# defaults (`/camera/camera/color/image_raw`, `/camera/camera/depth/image_rect_raw`)
|
|
9
|
+
# so plugin code that targets real hardware works against sim without any
|
|
10
|
+
# config change. Same for /cmd_vel, /odom, /scan, /imu/data, /tf.
|
|
11
|
+
#
|
|
12
|
+
# Direction notation: GZ_TO_ROS — gazebo publishes, ros subscribes (sensors)
|
|
13
|
+
# ROS_TO_GZ — ros publishes, gazebo subscribes (cmd_vel)
|
|
14
|
+
# BIDIRECTIONAL — rare, /tf for example
|
|
15
|
+
#
|
|
16
|
+
# Field reference: https://github.com/gazebosim/ros_gz/blob/humble/ros_gz_bridge/README.md
|
|
17
|
+
|
|
18
|
+
# ---------------- cmd_vel (ROS -> GZ) ----------------
|
|
19
|
+
- ros_topic_name: "/cmd_vel"
|
|
20
|
+
gz_topic_name: "/model/agenticros_amr/cmd_vel"
|
|
21
|
+
ros_type_name: "geometry_msgs/msg/Twist"
|
|
22
|
+
gz_type_name: "gz.msgs.Twist"
|
|
23
|
+
direction: ROS_TO_GZ
|
|
24
|
+
|
|
25
|
+
# ---------------- odometry (GZ -> ROS) ----------------
|
|
26
|
+
# Note: the gz-sim diff-drive system publishes <odom_topic> as a bare topic
|
|
27
|
+
# (no /model/<name>/ prefix), unlike <topic> which DOES get prefixed.
|
|
28
|
+
- ros_topic_name: "/odom"
|
|
29
|
+
gz_topic_name: "/odometry"
|
|
30
|
+
ros_type_name: "nav_msgs/msg/Odometry"
|
|
31
|
+
gz_type_name: "gz.msgs.Odometry"
|
|
32
|
+
direction: GZ_TO_ROS
|
|
33
|
+
|
|
34
|
+
# ---------------- /tf (GZ -> ROS) ----------------
|
|
35
|
+
- ros_topic_name: "/tf"
|
|
36
|
+
gz_topic_name: "/tf"
|
|
37
|
+
ros_type_name: "tf2_msgs/msg/TFMessage"
|
|
38
|
+
gz_type_name: "gz.msgs.Pose_V"
|
|
39
|
+
direction: GZ_TO_ROS
|
|
40
|
+
|
|
41
|
+
# ---------------- pose info (GZ -> ROS) ----------------
|
|
42
|
+
- ros_topic_name: "/tf_static"
|
|
43
|
+
gz_topic_name: "/model/agenticros_amr/pose_static"
|
|
44
|
+
ros_type_name: "tf2_msgs/msg/TFMessage"
|
|
45
|
+
gz_type_name: "gz.msgs.Pose_V"
|
|
46
|
+
direction: GZ_TO_ROS
|
|
47
|
+
|
|
48
|
+
# ---------------- joint states (GZ -> ROS) ----------------
|
|
49
|
+
- ros_topic_name: "/joint_states"
|
|
50
|
+
gz_topic_name: "/joint_states"
|
|
51
|
+
ros_type_name: "sensor_msgs/msg/JointState"
|
|
52
|
+
gz_type_name: "gz.msgs.Model"
|
|
53
|
+
direction: GZ_TO_ROS
|
|
54
|
+
|
|
55
|
+
# ---------------- Depth camera (GZ -> ROS) ----------------
|
|
56
|
+
# The rgbd_camera plugin publishes under <topic>camera</topic>, which becomes:
|
|
57
|
+
# /camera/image (RGB)
|
|
58
|
+
# /camera/depth_image (depth, 32FC1)
|
|
59
|
+
# /camera/points (PointCloud2)
|
|
60
|
+
# /camera/camera_info (CameraInfo)
|
|
61
|
+
# We remap each to the RealSense layout the real-robot plugin expects.
|
|
62
|
+
- ros_topic_name: "/camera/camera/color/image_raw"
|
|
63
|
+
gz_topic_name: "/camera/image"
|
|
64
|
+
ros_type_name: "sensor_msgs/msg/Image"
|
|
65
|
+
gz_type_name: "gz.msgs.Image"
|
|
66
|
+
direction: GZ_TO_ROS
|
|
67
|
+
|
|
68
|
+
- ros_topic_name: "/camera/camera/color/camera_info"
|
|
69
|
+
gz_topic_name: "/camera/camera_info"
|
|
70
|
+
ros_type_name: "sensor_msgs/msg/CameraInfo"
|
|
71
|
+
gz_type_name: "gz.msgs.CameraInfo"
|
|
72
|
+
direction: GZ_TO_ROS
|
|
73
|
+
|
|
74
|
+
- ros_topic_name: "/camera/camera/depth/image_rect_raw"
|
|
75
|
+
gz_topic_name: "/camera/depth_image"
|
|
76
|
+
ros_type_name: "sensor_msgs/msg/Image"
|
|
77
|
+
gz_type_name: "gz.msgs.Image"
|
|
78
|
+
direction: GZ_TO_ROS
|
|
79
|
+
|
|
80
|
+
- ros_topic_name: "/camera/camera/depth/camera_info"
|
|
81
|
+
gz_topic_name: "/camera/depth_image/camera_info"
|
|
82
|
+
ros_type_name: "sensor_msgs/msg/CameraInfo"
|
|
83
|
+
gz_type_name: "gz.msgs.CameraInfo"
|
|
84
|
+
direction: GZ_TO_ROS
|
|
85
|
+
|
|
86
|
+
- ros_topic_name: "/camera/camera/depth/points"
|
|
87
|
+
gz_topic_name: "/camera/points"
|
|
88
|
+
ros_type_name: "sensor_msgs/msg/PointCloud2"
|
|
89
|
+
gz_type_name: "gz.msgs.PointCloudPacked"
|
|
90
|
+
direction: GZ_TO_ROS
|
|
91
|
+
|
|
92
|
+
# ---------------- 2D LIDAR (GZ -> ROS) ----------------
|
|
93
|
+
- ros_topic_name: "/scan"
|
|
94
|
+
gz_topic_name: "/scan"
|
|
95
|
+
ros_type_name: "sensor_msgs/msg/LaserScan"
|
|
96
|
+
gz_type_name: "gz.msgs.LaserScan"
|
|
97
|
+
direction: GZ_TO_ROS
|
|
98
|
+
|
|
99
|
+
# ---------------- IMU (GZ -> ROS) ----------------
|
|
100
|
+
- ros_topic_name: "/imu/data"
|
|
101
|
+
gz_topic_name: "/imu"
|
|
102
|
+
ros_type_name: "sensor_msgs/msg/Imu"
|
|
103
|
+
gz_type_name: "gz.msgs.IMU"
|
|
104
|
+
direction: GZ_TO_ROS
|
|
105
|
+
|
|
106
|
+
# ---------------- Clock (GZ -> ROS) ----------------
|
|
107
|
+
- ros_topic_name: "/clock"
|
|
108
|
+
gz_topic_name: "/clock"
|
|
109
|
+
ros_type_name: "rosgraph_msgs/msg/Clock"
|
|
110
|
+
gz_type_name: "gz.msgs.Clock"
|
|
111
|
+
direction: GZ_TO_ROS
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Panels:
|
|
2
|
+
- Class: rviz_common/Displays
|
|
3
|
+
Help Height: 0
|
|
4
|
+
Name: Displays
|
|
5
|
+
Property Tree Widget:
|
|
6
|
+
Expanded:
|
|
7
|
+
- /TF1
|
|
8
|
+
Splitter Ratio: 0.5
|
|
9
|
+
Tree Height: 600
|
|
10
|
+
- Class: rviz_common/Views
|
|
11
|
+
Expanded:
|
|
12
|
+
- /Current View1
|
|
13
|
+
Name: Views
|
|
14
|
+
Splitter Ratio: 0.5
|
|
15
|
+
Visualization Manager:
|
|
16
|
+
Class: ""
|
|
17
|
+
Displays:
|
|
18
|
+
- Alpha: 0.5
|
|
19
|
+
Cell Size: 1
|
|
20
|
+
Class: rviz_default_plugins/Grid
|
|
21
|
+
Color: 160; 160; 164
|
|
22
|
+
Enabled: true
|
|
23
|
+
Line Style:
|
|
24
|
+
Line Width: 0.03
|
|
25
|
+
Value: Lines
|
|
26
|
+
Name: Grid
|
|
27
|
+
Normal Cell Count: 0
|
|
28
|
+
Offset:
|
|
29
|
+
X: 0
|
|
30
|
+
Y: 0
|
|
31
|
+
Z: 0
|
|
32
|
+
Plane: XY
|
|
33
|
+
Plane Cell Count: 20
|
|
34
|
+
Reference Frame: <Fixed Frame>
|
|
35
|
+
Value: true
|
|
36
|
+
- Class: rviz_default_plugins/TF
|
|
37
|
+
Enabled: true
|
|
38
|
+
Frame Timeout: 15
|
|
39
|
+
Frames:
|
|
40
|
+
All Enabled: true
|
|
41
|
+
Marker Scale: 0.5
|
|
42
|
+
Name: TF
|
|
43
|
+
Show Arrows: true
|
|
44
|
+
Show Axes: true
|
|
45
|
+
Show Names: true
|
|
46
|
+
Update Interval: 0
|
|
47
|
+
Value: true
|
|
48
|
+
- Alpha: 1
|
|
49
|
+
Autocompute Intensity Bounds: true
|
|
50
|
+
Autocompute Value Bounds:
|
|
51
|
+
Max Value: 10
|
|
52
|
+
Min Value: -10
|
|
53
|
+
Value: true
|
|
54
|
+
Axis: Z
|
|
55
|
+
Channel Name: intensity
|
|
56
|
+
Class: rviz_default_plugins/LaserScan
|
|
57
|
+
Color: 255; 255; 255
|
|
58
|
+
Color Transformer: Intensity
|
|
59
|
+
Decay Time: 0
|
|
60
|
+
Enabled: true
|
|
61
|
+
Invert Rainbow: false
|
|
62
|
+
Max Color: 255; 255; 255
|
|
63
|
+
Max Intensity: 4096
|
|
64
|
+
Min Color: 0; 0; 0
|
|
65
|
+
Min Intensity: 0
|
|
66
|
+
Name: LaserScan
|
|
67
|
+
Position Transformer: XYZ
|
|
68
|
+
Queue Size: 10
|
|
69
|
+
Selectable: true
|
|
70
|
+
Size (Pixels): 3
|
|
71
|
+
Size (m): 0.05
|
|
72
|
+
Style: Points
|
|
73
|
+
Topic:
|
|
74
|
+
Depth: 5
|
|
75
|
+
Durability Policy: Volatile
|
|
76
|
+
Filter size: 10
|
|
77
|
+
History Policy: Keep Last
|
|
78
|
+
Reliability Policy: Reliable
|
|
79
|
+
Value: /scan
|
|
80
|
+
Use Fixed Frame: true
|
|
81
|
+
Use rainbow: true
|
|
82
|
+
Value: true
|
|
83
|
+
- Class: rviz_default_plugins/Image
|
|
84
|
+
Enabled: true
|
|
85
|
+
Image Topic:
|
|
86
|
+
Depth: 5
|
|
87
|
+
Durability Policy: Volatile
|
|
88
|
+
History Policy: Keep Last
|
|
89
|
+
Reliability Policy: Reliable
|
|
90
|
+
Value: /camera/camera/color/image_raw
|
|
91
|
+
Max Value: 1
|
|
92
|
+
Median window: 5
|
|
93
|
+
Min Value: 0
|
|
94
|
+
Name: RGB
|
|
95
|
+
Normalize Range: true
|
|
96
|
+
Value: true
|
|
97
|
+
- Alpha: 1
|
|
98
|
+
Autocompute Intensity Bounds: true
|
|
99
|
+
Autocompute Value Bounds:
|
|
100
|
+
Max Value: 10
|
|
101
|
+
Min Value: -10
|
|
102
|
+
Value: true
|
|
103
|
+
Axis: Z
|
|
104
|
+
Channel Name: intensity
|
|
105
|
+
Class: rviz_default_plugins/PointCloud2
|
|
106
|
+
Color: 255; 255; 255
|
|
107
|
+
Color Transformer: AxisColor
|
|
108
|
+
Decay Time: 0
|
|
109
|
+
Enabled: true
|
|
110
|
+
Invert Rainbow: false
|
|
111
|
+
Max Color: 255; 255; 255
|
|
112
|
+
Max Intensity: 4096
|
|
113
|
+
Min Color: 0; 0; 0
|
|
114
|
+
Min Intensity: 0
|
|
115
|
+
Name: DepthCloud
|
|
116
|
+
Position Transformer: XYZ
|
|
117
|
+
Queue Size: 10
|
|
118
|
+
Selectable: true
|
|
119
|
+
Size (Pixels): 3
|
|
120
|
+
Size (m): 0.02
|
|
121
|
+
Style: Points
|
|
122
|
+
Topic:
|
|
123
|
+
Depth: 5
|
|
124
|
+
Durability Policy: Volatile
|
|
125
|
+
Filter size: 10
|
|
126
|
+
History Policy: Keep Last
|
|
127
|
+
Reliability Policy: Best Effort
|
|
128
|
+
Value: /camera/camera/depth/points
|
|
129
|
+
Use Fixed Frame: true
|
|
130
|
+
Use rainbow: true
|
|
131
|
+
Value: true
|
|
132
|
+
Enabled: true
|
|
133
|
+
Global Options:
|
|
134
|
+
Background Color: 48; 48; 48
|
|
135
|
+
Fixed Frame: odom
|
|
136
|
+
Frame Rate: 30
|
|
137
|
+
Name: root
|
|
138
|
+
Tools:
|
|
139
|
+
- Class: rviz_default_plugins/Interact
|
|
140
|
+
Hide Inactive Objects: true
|
|
141
|
+
- Class: rviz_default_plugins/MoveCamera
|
|
142
|
+
- Class: rviz_default_plugins/Select
|
|
143
|
+
- Class: rviz_default_plugins/FocusCamera
|
|
144
|
+
- Class: rviz_default_plugins/Measure
|
|
145
|
+
Line color: 128; 128; 0
|
|
146
|
+
Transformation:
|
|
147
|
+
Current:
|
|
148
|
+
Class: rviz_default_plugins/TF
|
|
149
|
+
Value: true
|
|
150
|
+
Views:
|
|
151
|
+
Current:
|
|
152
|
+
Class: rviz_default_plugins/Orbit
|
|
153
|
+
Distance: 7
|
|
154
|
+
Enable Stereo Rendering:
|
|
155
|
+
Stereo Eye Separation: 0.0599999987
|
|
156
|
+
Stereo Focal Distance: 1
|
|
157
|
+
Swap Stereo Eyes: false
|
|
158
|
+
Value: false
|
|
159
|
+
Focal Point:
|
|
160
|
+
X: 0
|
|
161
|
+
Y: 0
|
|
162
|
+
Z: 0
|
|
163
|
+
Focal Shape Fixed Size: true
|
|
164
|
+
Focal Shape Size: 0.05
|
|
165
|
+
Invert Z Axis: false
|
|
166
|
+
Name: Current View
|
|
167
|
+
Near Clip Distance: 0.01
|
|
168
|
+
Pitch: 0.5
|
|
169
|
+
Target Frame: <Fixed Frame>
|
|
170
|
+
Value: Orbit (rviz)
|
|
171
|
+
Yaw: -0.785
|
|
172
|
+
Saved: ~
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Generated env hook — prepends the agenticros_sim share/ tree onto the
|
|
2
|
+
# Gazebo Harmonic resource search path so `gz sim agenticros_indoor.sdf` and
|
|
3
|
+
# `<uri>model://agenticros_amr</uri>` resolve without absolute paths.
|
|
4
|
+
|
|
5
|
+
ament_prepend_unique_value GZ_SIM_RESOURCE_PATH "@CMAKE_INSTALL_PREFIX@/share/@PROJECT_NAME@"
|
|
6
|
+
ament_prepend_unique_value GZ_SIM_RESOURCE_PATH "@CMAKE_INSTALL_PREFIX@/share/@PROJECT_NAME@/models"
|
|
7
|
+
ament_prepend_unique_value GZ_SIM_RESOURCE_PATH "@CMAKE_INSTALL_PREFIX@/share/@PROJECT_NAME@/worlds"
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""sim_amr.launch.py
|
|
2
|
+
|
|
3
|
+
Bring up the AgenticROS 2-wheel AMR in Gazebo Harmonic with full ROS-side
|
|
4
|
+
plumbing:
|
|
5
|
+
* gz sim agenticros_indoor.sdf (the world + everything in it)
|
|
6
|
+
* ros_gz_sim create (spawn the AMR if it isn't
|
|
7
|
+
already baked into the world)
|
|
8
|
+
* ros_gz_bridge parameter_bridge config_file (gz <-> ROS topic bridge)
|
|
9
|
+
* Optional RViz (--rviz launch arg)
|
|
10
|
+
|
|
11
|
+
Launch args:
|
|
12
|
+
world (default 'agenticros_indoor.sdf') Override the world file.
|
|
13
|
+
use_rviz (default 'false') Show RViz with the AMR config.
|
|
14
|
+
use_sim_time (default 'true') /clock is bridged; downstream
|
|
15
|
+
nodes should honour this.
|
|
16
|
+
x, y, z, yaw Spawn pose for the AMR.
|
|
17
|
+
bridge_config_file Override the bridge YAML.
|
|
18
|
+
gui (default 'true') Headless if 'false' (CI / docker).
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
ros2 launch agenticros_sim sim_amr.launch.py
|
|
22
|
+
ros2 launch agenticros_sim sim_amr.launch.py use_rviz:=true
|
|
23
|
+
ros2 launch agenticros_sim sim_amr.launch.py gui:=false # headless
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import os
|
|
29
|
+
|
|
30
|
+
from ament_index_python.packages import get_package_share_directory
|
|
31
|
+
from launch import LaunchContext, LaunchDescription
|
|
32
|
+
from launch.actions import (
|
|
33
|
+
DeclareLaunchArgument,
|
|
34
|
+
IncludeLaunchDescription,
|
|
35
|
+
OpaqueFunction,
|
|
36
|
+
)
|
|
37
|
+
from launch.conditions import IfCondition
|
|
38
|
+
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
|
39
|
+
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
|
40
|
+
from launch_ros.actions import Node
|
|
41
|
+
from launch_ros.substitutions import FindPackageShare
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
PKG_NAME = "agenticros_sim"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def generate_launch_description() -> LaunchDescription:
|
|
48
|
+
pkg_share = get_package_share_directory(PKG_NAME)
|
|
49
|
+
default_world = os.path.join(pkg_share, "worlds", "agenticros_indoor.sdf")
|
|
50
|
+
default_bridge = os.path.join(pkg_share, "config", "amr_bridge.yaml")
|
|
51
|
+
default_rviz = os.path.join(pkg_share, "config", "amr_view.rviz")
|
|
52
|
+
model_sdf = os.path.join(pkg_share, "models", "agenticros_amr", "model.sdf")
|
|
53
|
+
|
|
54
|
+
# --- Launch arguments ---
|
|
55
|
+
world_arg = DeclareLaunchArgument(
|
|
56
|
+
"world", default_value=default_world,
|
|
57
|
+
description="SDF world file to load (absolute path).",
|
|
58
|
+
)
|
|
59
|
+
use_rviz_arg = DeclareLaunchArgument(
|
|
60
|
+
"use_rviz", default_value="false",
|
|
61
|
+
description="Open RViz with the AMR view config.",
|
|
62
|
+
)
|
|
63
|
+
use_sim_time_arg = DeclareLaunchArgument(
|
|
64
|
+
"use_sim_time", default_value="true",
|
|
65
|
+
description="Tell ROS nodes to use /clock published by gz.",
|
|
66
|
+
)
|
|
67
|
+
x_arg = DeclareLaunchArgument("x", default_value="0.0", description="AMR spawn X (m)")
|
|
68
|
+
y_arg = DeclareLaunchArgument("y", default_value="0.0", description="AMR spawn Y (m)")
|
|
69
|
+
z_arg = DeclareLaunchArgument("z", default_value="0.1", description="AMR spawn Z (m)")
|
|
70
|
+
yaw_arg = DeclareLaunchArgument("yaw", default_value="0.0", description="AMR yaw (rad)")
|
|
71
|
+
bridge_arg = DeclareLaunchArgument(
|
|
72
|
+
"bridge_config_file", default_value=default_bridge,
|
|
73
|
+
description="ros_gz_bridge parameter_bridge config YAML.",
|
|
74
|
+
)
|
|
75
|
+
gui_arg = DeclareLaunchArgument(
|
|
76
|
+
"gui", default_value="true",
|
|
77
|
+
description="If 'false', run gz-sim headless (-s -r).",
|
|
78
|
+
)
|
|
79
|
+
rviz_config_arg = DeclareLaunchArgument(
|
|
80
|
+
"rviz_config", default_value=default_rviz,
|
|
81
|
+
description="RViz config path (used when use_rviz is true).",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# ---------- Spawn the AMR ----------
|
|
85
|
+
spawn_amr = Node(
|
|
86
|
+
package="ros_gz_sim",
|
|
87
|
+
executable="create",
|
|
88
|
+
name="spawn_agenticros_amr",
|
|
89
|
+
output="screen",
|
|
90
|
+
arguments=[
|
|
91
|
+
"-name", "agenticros_amr",
|
|
92
|
+
"-file", model_sdf,
|
|
93
|
+
"-x", LaunchConfiguration("x"),
|
|
94
|
+
"-y", LaunchConfiguration("y"),
|
|
95
|
+
"-z", LaunchConfiguration("z"),
|
|
96
|
+
"-Y", LaunchConfiguration("yaw"),
|
|
97
|
+
],
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# ---------- gz <-> ROS bridge ----------
|
|
101
|
+
bridge = Node(
|
|
102
|
+
package="ros_gz_bridge",
|
|
103
|
+
executable="parameter_bridge",
|
|
104
|
+
name="agenticros_amr_bridge",
|
|
105
|
+
output="screen",
|
|
106
|
+
parameters=[{
|
|
107
|
+
"config_file": LaunchConfiguration("bridge_config_file"),
|
|
108
|
+
"qos_overrides./tf_static.publisher.durability": "transient_local",
|
|
109
|
+
"use_sim_time": LaunchConfiguration("use_sim_time"),
|
|
110
|
+
}],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# ---------- Optional RViz ----------
|
|
114
|
+
rviz = Node(
|
|
115
|
+
package="rviz2",
|
|
116
|
+
executable="rviz2",
|
|
117
|
+
name="rviz2",
|
|
118
|
+
output="screen",
|
|
119
|
+
condition=IfCondition(LaunchConfiguration("use_rviz")),
|
|
120
|
+
arguments=["-d", LaunchConfiguration("rviz_config")],
|
|
121
|
+
parameters=[{"use_sim_time": LaunchConfiguration("use_sim_time")}],
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# The gz sim launcher needs a single space-separated `gz_args` string. We
|
|
125
|
+
# build it inside an OpaqueFunction so the conditional headless flag is
|
|
126
|
+
# evaluated at launch-time (substitutions can't do string concatenation).
|
|
127
|
+
return LaunchDescription([
|
|
128
|
+
world_arg,
|
|
129
|
+
use_rviz_arg,
|
|
130
|
+
use_sim_time_arg,
|
|
131
|
+
x_arg, y_arg, z_arg, yaw_arg,
|
|
132
|
+
bridge_arg,
|
|
133
|
+
gui_arg,
|
|
134
|
+
rviz_config_arg,
|
|
135
|
+
OpaqueFunction(function=_launch_gz_sim),
|
|
136
|
+
spawn_amr,
|
|
137
|
+
bridge,
|
|
138
|
+
rviz,
|
|
139
|
+
])
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def _launch_gz_sim(context: LaunchContext, *_, **__):
|
|
143
|
+
"""Resolve launch args and emit the gz_sim IncludeLaunchDescription action."""
|
|
144
|
+
gui = context.launch_configurations.get("gui", "true").lower() == "true"
|
|
145
|
+
world = context.launch_configurations.get(
|
|
146
|
+
"world",
|
|
147
|
+
os.path.join(get_package_share_directory(PKG_NAME), "worlds", "agenticros_indoor.sdf"),
|
|
148
|
+
)
|
|
149
|
+
gz_args = f"-r {world}" if gui else f"-r -s --headless-rendering {world}"
|
|
150
|
+
|
|
151
|
+
gz_launch = IncludeLaunchDescription(
|
|
152
|
+
PythonLaunchDescriptionSource(
|
|
153
|
+
PathJoinSubstitution(
|
|
154
|
+
[FindPackageShare("ros_gz_sim"), "launch", "gz_sim.launch.py"]
|
|
155
|
+
)
|
|
156
|
+
),
|
|
157
|
+
launch_arguments=[("gz_args", gz_args)],
|
|
158
|
+
)
|
|
159
|
+
return [gz_launch]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0"?>
|
|
2
|
+
<model>
|
|
3
|
+
<name>AgenticROS AMR</name>
|
|
4
|
+
<version>0.1</version>
|
|
5
|
+
<sdf version="1.10">model.sdf</sdf>
|
|
6
|
+
<author>
|
|
7
|
+
<name>PlaiPin</name>
|
|
8
|
+
<email>hello@plaipin.com</email>
|
|
9
|
+
</author>
|
|
10
|
+
<description>
|
|
11
|
+
Two-wheel differential-drive AMR with a forward-facing RealSense-D435-style
|
|
12
|
+
depth camera, a 2D GPU lidar, and an IMU. Topic layout matches the real
|
|
13
|
+
AgenticROS robot (camera/camera/color/image_raw, camera/camera/depth/
|
|
14
|
+
image_rect_raw, scan, imu/data, odom, cmd_vel) so plugin code is identical
|
|
15
|
+
in real and sim.
|
|
16
|
+
</description>
|
|
17
|
+
</model>
|