Stage_Ros2仿真平臺
stage_ros2是基於Stage模擬器的ROS2功能包,用於在虛擬環境中模擬和控制機器人的行爲。它提供了強大的工具和通信接口,可用於開發、測試和驗證機器人系統。通過stage_ros2,用戶可以輕鬆創建虛擬環境,並使用ROS 2發送指令控制機器人的運動,同時接收傳感器數據。這個功能包可以幫助用戶以更低的成本和風險進行機器人開發,提供了高效且靈活的機器人仿真環境。
stage使用手冊:
http://rtv.github.io/Stage/modules.html
( 可以不學 ,連ROS2官方都已經移除掉了Stage, 用更牛X的Gazebo更好 ,但學一學也問題不大)
stage_ros2安裝與運行
1.安裝
因爲ROS2官方已經移除掉了Stage,所以我們要通過源碼編譯手動安裝,已經有大佬適配了ROS2版本的Stage:
請先調用如下指令安裝依賴:
sudo apt-get install git cmake g++ libjpeg8-dev libpng-dev libglu1-mesa-dev libltdl-dev libfltk1.1-dev
進入ROS2工作空間的src目錄,調用如下指令下載相關倉庫:
git clone https://github.com/damuxt/Stage.git
git clone https://github.com/damuxt/stage_ros2.git
進入工作空間目錄,使用colcon build指令進行構建。
(這是第三方作者適配Humble版本的,暫時不支持Jazzy版本,Jazzy版本目前編譯會報錯,可能作者會更新Jazzy版本的)
2.節點說明
stage_ros2節點是stage_ros2功能包的核心節點之一。它通過加載world文件來創建一個仿真場景,包括地圖、障礙物和機器人等元素。world文件描述了虛擬環境的屬性,節點會根據文件中的描述構建對應的環境。stage_ros2節點利用這個虛擬環境來模擬機器人的運動、感知和控制。通過該節點和world文件的結合,可以進行機器人的仿真和測試。
3.使用
在功能包下,已經內置了使用示例,終端下可以執行如下指令啓動示例:
ros2 launch stage_ros2 my_house.launch.py
模擬器以及rviz2將被啓動,並且在rviz2中可以顯示里程計、激光雷達以及深度相機等相關信息,運行結果如下。

stage_ros2仿真框架搭建
本節開始,我們將介紹如何通過stage_ros2自定義仿真環境。
1.準備工作
首先請創建一個功能包,指令如下:
ros2 pkg create demo_stage_sim --dependencies stage_ros2
然後在功能包下新建launch、world、config目錄,並修改功能包下的CMakeLists.txt文件,添加如下代碼:
install(DIRECTORY launch world config DESTINATION share/${PROJECT_NAME})
其中,launch目錄用於存儲launch文件,config用於存儲rviz2的配置文件,world用於存儲仿真相關文件。world目錄中請新建maps目錄,並將課程配套資料中的圖片素材複製進去。
2.搭建代碼框架
在功能包的launch目錄下,新建stage_sim.launch.py文件,並輸入如下內容:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
this_directory = get_package_share_directory('demo_stage_sim')
return LaunchDescription([
Node(
package='stage_ros2',
executable='stage_ros2',
name='stage',
parameters=[{"world_file": os.path.join(this_directory,'world','sim.world')}],
)
])
該launch文件將運行stage_ros2節點,並加載world目錄下的sim.world文件。
在world目錄下,新建sim.world文件,並輸入如下內容:
# -----------------------------------------------------------------------------
# 设置窗体
# 设置模拟器地图分辨率(以 米/像素 为单位)
resolution 0.02
# 设置模拟器的时间步长(以 毫秒 为单位)
interval_sim 100
sim.world文件當前只是聲明瞭仿真環境的一些通用參數。
3.編譯
終端中進入當前工作空間,編譯功能包:
colcon build --packages-select demo_stage_sim
4.執行
當前工作空間下,啓動終端,並輸入如下指令:
. install/setup.bash
ros2 launch demo_stage_sim stage_sim.launch.py
執行該launch文件後,將生成一個窗口,該窗口中並無任何內容,下一步我們就可以着手創建具體的仿真內容了。

5.world文件參數
摘要和默認值
name <worldfile name>
interval_sim 100
quit_time 0
resolution 0.02
show_clock 0
show_clock_interval 100
threads 0
詳解
- name
- 用於世界的識別名稱,例如在圖形用戶界面的標題欄中使用。
- interval_sim
- 每次調用 World::Update() 時運行的模擬時間量。每個模型都有其自己可配置的更新間隔,可以大於或小於此值,但比此值更短的間隔在圖形用戶界面或 World 更新回調中是不可見的。您可能不需要改變默認值100毫秒:此值在客戶端內部使用,如Player和WebSim。
- quit_time
在模擬時間達到指定的秒數後停止模擬。在 libstage 中,World::Update() 返回 true。在帶有圖形用戶界面的 Stage 中,模擬被暫停。在沒有圖形用戶界面的 Stage 中,Stage 會退出。 - resolution
底層位圖模型的分辨率(以米爲單位)。較大的值可以加快射線追蹤速度,但會以碰撞檢測和感知精度爲代價。通常情況下,默認值是一個合理的選擇。 - show_clock
- 如果非零,每經過 $show_clock_interval 次更新就在標準輸出上打印模擬時間。這對於觀察非 GUI 模擬的進展非常有用。
- show_clock_interval
- 設置在啓用 $show_clock 的情況下,在標準輸出上打印時間之間的更新次數。默認值是每經過 10 秒模擬時間打印一次。較小的值會稍微降低模擬速度。
- threads
- 要生成的工作線程數。一些模型可以並行更新(例如激光器、測距儀),在這裏運行 2 個或更多線程可能會使模擬運行更快,取決於可用的 CPU 內核數量和世界文件的情況。如果您有啓用並行的高分辨率模型(例如帶有數百或數千個樣本的激光器或大量模型),則每個內核使用一個線程。
stage_ros2設置窗體
stage 窗體由菜單欄和模擬世界的視圖組成。我們可以放大和縮小視圖,並滾動視圖以查看模擬世界的更多內容。模擬的機器人設備、障礙物等被渲染爲彩色多邊形。窗體中還可以實現各種傳感器和執行器模型的數據和配置的可視化。菜單則具有用於控制呈現哪些數據和配置的選項。本節我們將介紹如何設置以及操作stage窗體。
1.設置窗體
設置窗體相關參數,可以在stage_sim.launch.py文件中添加如下內容:
# 配置窗体参数
window
(
size [ 700.000 700.000 ] # 窗体尺寸(以 像素 为单位)
scale 35 # 缩放比
center [ 0 0 ] # 地图相对于窗体的偏移量(以 米 为单位)
rotate [ 0 0 ] # 地图旋转角度
show_data 1 # 是否显示传感器数据 1=on 0=off
)
上述代碼創建了一個窗體對象,該窗體分辨率爲700*700,使用了35倍縮放比,後續加載的地圖相對於窗體無偏移無旋轉且會以可視化的方式顯示傳感器數據。
2.編譯執行
構建功能包並執行launch文件後,運行結果如下。

3.窗體參數
摘要和默認值
window
(
size [ 400 300 ]
# camera options
center [ 0 0 ]
rotate [ 0 0 ]
scale 1.0
# perspective camera options
pcam_loc [ 0 -4 2 ]
pcam_angle [ 70 0 ]
# GUI options
show_data 0
show_flags 1
show_blocks 1
show_clock 1
show_footprints 0
show_grid 1
show_trailarrows 0
show_trailrise 0
show_trailfast 0
show_occupancy 0
show_tree 0
pcam_on 0
screenshots 0
)
詳解
- speedup
- Stage 將嘗試以實時的這個倍數運行。如果設置爲 -1,Stage 將盡可能以最快速度運行,並且不會嘗試跟蹤實時時間。
- size [width:intheight:int ]
- 窗口的大小(以像素爲單位)。
- center [<x:float><y:float> ]
- 窗口中心的位置,使用世界座標表示(以米爲單位)。
- rotate [pitch:floatyaw:float ]
- 相對於垂直向上的角度,旋轉角度(以度爲單位)。
- scale
- 世界座標到像素座標的比例(窗口縮放)。
- pcam_loc [<x:int><y:int><z:int> ]
- 透視攝像機的位置(以米爲單位)。
- pcam_angle [pitch:floatyaw:float ]
- 透視攝像機的垂直和水平角度。
- pcam_on
- 是否啓用透視攝像機(0/1)。
4.操作窗體
滾動視圖
在背景上左鍵單擊並拖動以移動你對世界的視圖。
縮放視圖
滾動鼠標滾輪可放大或縮小鼠標光標處的位置。
保存世界
你可以保存當前世界中所有事物的位置,使用“文件/保存”菜單項。警告:保存的位置將覆蓋當前的世界文件。在保存之前,先複製你的世界文件,以保留舊的位置。另外,可以使用“文件/另存爲”菜單項將其保存到一個新的世界文件中。
暫停和恢復時鐘
按下“p”鍵可以暫停或恢復模擬。按下“.”(句號)鍵可以運行一個模擬步驟。按住“.”鍵可以重複多次步進。步進會讓模擬暫停,所以按下“p”鍵可以恢復運行。可以在世界文件中使用“paused”屬性來設置初始的暫停/運行狀態。
選擇模型
可以通過點擊左鍵來選擇模型。通過按住Shift鍵並點擊多個模型,也可以選擇多個模型。選擇的模型可以通過拖動來移動,或者通過按住右鍵並移動鼠標來旋轉。點擊世界中的空白位置可以清除選擇。在清除選擇後,最後選中的單個模型將被保存爲影響特定模型的幾個視圖選項的目標。
視圖選項
視圖菜單提供了許多影響世界渲染方式的功能。在每個選項的右側,通常有一個按鍵快捷鍵,可快速切換相關選項。
“Data”選項(快捷鍵'd')可切換傳感器數據可視化。濾波器數據選項(快捷鍵Shift+'d')打開對話框,可啓用或禁用特定傳感器的可視化。對話框中的“Visualize All”選項可切換是否爲所有模型啓用傳感器可視化,還是僅爲當前選擇的模型啓用。
“Follow”選項可保持視圖始終在最後選擇的模型上。
“Perspective camera”選項可以從正交視圖切換到透視視圖。
保存截圖
要保存世界的一系列截圖,從視圖菜單中選擇“Save screenshots”選項以開始錄製圖像,然後再次從菜單中選擇該選項以停止。
stage_ros2基本模型
基本模型(model)模擬具有基本屬性的對象;位置、大小、速度、顏色、對各種傳感器的可見性等。基本模型還具有由線性列表組成的主體。在內部,基本模型被用作所有其他模型類型的基類。我們可以使用基本模型來模擬環境對象。在stage中,底盤模型、雷達模型、相機模型等都可以看作是基本模型的子類。

1.添加基本模型
在stage_sim.launch.py文件中添加如下內容:
# -----------------------------------------------------------------------------
# 添加障碍物
model( pose [ -2 -4 0 0 ] color "green")
# define a block
define my_block model
(
size [1.0 1.0 1.0]
gui_nose 0
gui_grid 0
gui_outline 0
)
# throw in a block
my_block( pose [ 0 4 0 90 ] color "red" bitmap "maps/ghost.png")
上述代碼中,直接使用默認的基礎model創建了一個綠色模型對象,並且還自定義了繼承自model的my_block模型,然後創建了該模型對象。
2.編譯執行
構建功能包並執行launch文件後,運行結果如下。

3.窗體參數
摘要和默認值
model (
pose [ 0.0 0.0 0.0 0.0 ]
size [ 0.1 0.1 0.1 ]
origin [ 0.0 0.0 0.0 0.0 ]
velocity [ 0.0 0.0 0.0 0.0 ]
color "red"
color_rgba [ 0.0 0.0 0.0 1.0 ]
bitmap ""
ctrl ""
# determine how the model appears in various sensors
fiducial_return 0
fiducial_key 0
obstacle_return 1
ranger_return 1
blob_return 1
laser_return LaserVisible
gripper_return 0
gravity_return 0
sticky_return 0
# GUI properties
gui_nose 0
gui_grid 0
gui_outline 1
gui_move 0 (1 if the model has no parents);
boundary 0
mass 10.0
map_resolution 0.1
say ""
alwayson 0
)
詳解
- pose [ x:
y: z: heading: ] 指定模型在其父座標系中的姿態。 - size [ x:
y: z: ] 指定模型在各個維度上的大小。 - origin [ x:
y: z: heading: ] 指定對象中心的位置,相對於其姿態。 - velocity [ x:
y: z: heading: omega: ] 指定模型的初始速度。請注意,如果模型撞到障礙物,其速度將被設置爲零。 - velocity_enable int (默認爲0) 大多數模型忽略其速度狀態。這樣可以節省處理時間,因爲大多數模型的速度永遠不會被設置爲非零值。一些子類(例如ModelPosition)會改變這個默認值,因爲它們期望移動。用戶可以在這裏指定一個非零值來啓用對該模型的速度控制。這與調用Model::VelocityEnable()的效果相同。
- color
使用X11數據庫(rgb.txt)中的顏色名稱指定對象的顏色。 - bitmap filename:
通過解釋位圖中的線條來繪製模型(支持bmp、jpeg、gif、png)。文件被打開並解析爲一組線條。這些線條被縮放以適應模型當前大小所定義的矩形內。 - ctrl
指定模型的控制器模塊及其參數字符串。例如,字符串"foo bar bash"將加載libfoo.so,其Init()函數將以整個字符串作爲參數進行調用(包括庫名稱)。控制器需要解析字符串(如果需要參數)。 - fiducial_return fiducial_id
如果非零,則通過fiducialfinder傳感器檢測到此模型。該值用作基準標識符。 - fiducial_key
僅當模型和fiducialfinder的fiducial_key值匹配時,fiducial_id模型纔會被fiducialfinder檢測到。這允許您在同一環境中擁有幾種獨立類型的基準標識,每種類型只顯示在爲其"調諧"的fiducialfinders中。 - obstacle_return
如果爲1,則此模型可以與具有此屬性設置的其他模型發生碰撞。 - ranger_return
如果爲1,則該模型可以被ranger傳感器檢測到。 - blob_return
如果爲1,則該模型可以在blob_finder中被檢測到(取決於其顏色)。 - laser_return
如果爲0,則此模型不會被激光傳感器檢測到。如果爲1,則該模型在激光傳感器中顯示爲正常(0)反射。如果爲2,則顯示爲高(1)反射。 - gripper_return
如果爲1,則該模型可以被夾爪夾取,並且可以通過與具有非零obstacle_return的任何東西的碰撞來推動。 - gui_nose
如果爲1,則在模型上繪製顯示其朝向的鼻子(正X軸)。 - gui_grid
如果爲1,則在模型上繪製比例網格。 - gui_outline
如果爲1,則在模型周圍繪製邊界框,指示其大小。 - gui_move
如果爲1,則模型可以在GUI窗口中通過鼠標移動。
stage_ros2添加地圖
本節我們將在仿真環境中,添加一張全局地圖,請先準備一張作爲全局地圖的圖片。
1.添加地圖
在stage_sim.launch.py文件中添加如下內容:
# -----------------------------------------------------------------------------
# 设置地图(定义模型)
define floorplan model
(
color "gray30" # 颜色
boundary 1 # 为地图设置边框
gui_nose 0
gui_grid 0
gui_outline 0
gripper_return 0
fiducial_return 0
laser_return 1
)
# 加载地图
floorplan
(
name "room"
size [16.000 16.000 0.800]
pose [0 0 0 0]
bitmap "maps/room.jpg"
gui_move 0
)
上述代碼自定義了floorplan模型,並根據此模型創建了一個加載了地圖數據的floorplan對象。
2.編譯執行
構建功能包並執行launch文件後,運行結果如下。

stage_ros2添加機器人
本節將在仿真環境中添加一個由底盤、攝像頭以及激光雷達組成的虛擬機器人。
1.代碼框架搭建
在world目錄下新建robot目錄,robot目錄中再創建car_base.inc、camera.inc、laser.inc以及mycar.inc等文件,各文件作用如下:
- car_base.inc:用於設置機器人底盤模塊;
- camera.inc:用於設置機器人相機模塊;
- laser.inc:用於設置機器人雷達模塊;
- mycar.inc:用於組裝機器人各模塊。
除此之外,還會在sim.world中包含mycar.inc並調用其生成機器人的功能。
2.設置機器人底盤
stage中的position模型可以以差速、全向或阿克曼的方式模擬移動機器人底盤。在car_base.inc中輸入如下代碼:
# 机器人底盘配置
define car_base position
(
color "red" # 车身颜色
drive "diff" # 车辆运动学模型
obstacle_return 1
ranger_return 1
blob_return 1
fiducial_return 1
localization "odom" # 定位方式
odom_error [ 0.05 0.05 0.0 0.1 ] # 里程计误差
# localization_origin [0 0 0 0] # 定位原点,默认为机器人的初始位置。
# [ xmin xmax ymin ymax zmin zmax amin amax ]
velocity_bounds [-1 1 0 0 0 0 -45.0 45.0 ] # 速度最值
acceleration_bounds [-0.5 0.5 0 0 0 0 -45 45.0 ] # 加速度最值
size [0.44 0.38 0.22] # 车体尺寸
origin [0 0 0 0] # 旋转中心与车体中心的偏移量
mass 23.0 # 车体质量,单位kg
gui_nose 0 # 是否绘制方向指示标记
block(
points 8
point[0] [-0.2 0.18]
point[1] [-0.2 -0.18]
point[2] [-0.15 -0.27]
point[3] [0.12 -0.23]
point[4] [0.2 -0.12]
point[5] [0.2 0.12]
point[6] [0.12 0.23]
point[7] [-0.15 0.27]
z [0 0.22]
)
)
position摘要和默認值
position(
drive "diff"
localization "gps"
localization_origin [<defaults to model's start pose>]
odom_error [0.03 0.03 0.00 0.05]
velocity_enable 1
)
詳解
- drive "diff", "omni" 或 "car" 選擇差速轉向模型、全向模式或類似汽車的阿克曼模式。
- localization "gps" 或 "odom" 如果選擇 “gps”,位置模型將以完全準確的精度報告位置。如果選擇 “odom”,將使用簡單的里程計模型,並且位置數據會隨時間與真實位置的差異而漂移。里程計模型由 odom_error 屬性參數化。
- localization_origin [x y z theta] 您可以使用 localization_origin 參數來設置定位座標系的原點。默認情況下,它將複製模型的初始姿態,因此機器人將報告相對於起始位置的位置。提示: 如果將 localization_origin 設置爲 [0 0 0 0] 並且定位方式爲 “gps”,模型將返回其真實的全局位置。這種設置是不現實的,但在希望抽象定位細節的研究中很有用。
- odom_error [x y z theta] 在選擇 “odom” 定位方式時用到的里程計誤差模型參數,每個值是計算里程計位置估計時積分 x、y 和 theta 速度的誤差比例的最大值。對於每個軸,如果在此處指定的值爲 E,則實際比例在啓動時在 -E/2 到 +E/2 的範圍內隨機選擇。請注意,由於舍入誤差,將這些值設置爲零並不能讓定位完美無誤 - 爲了實現這一點,您需要選擇 “gps” 定位方式。
3.設置攝像頭
stage中的camera模型可以模擬深度相機。在camera.inc中輸入如下代碼:
define my_camera camera
(
range [ 0.3 3.0 ] # 相机采样范围
resolution [ 160 90 ] #相机分辨率 1280 × 720 / 8
fov [ 87 58 ] # 相机视场
pantilt [ 0 0 ] # 相机姿态
alwayson 1 # 是否一直处于启动状态
size [ 0.025 0.09 0.025 ] # 相机尺寸
color "gray" # 相机颜色
)
camera摘要和默認值
camera(
resolution [ 32 32 ]
range [ 0.2 8.0 ]
fov [ 70.0 40.0 ]
pantilt [ 0.0 0.0 ]
size [ 0.1 0.07 0.05 ]
color "black"
watts 100.0
)
詳解
- resolution [ width:
height: ] 相機分辨率。 - range [ min:
max: ] 相機報告的距離範圍,以米爲單位。距離小於 min或大於max的物體將無法顯示。min數字越小,深度精度越低 - 不要將此值設置得太接近 0。 - fov [ horizontal:
vertical: ] 水平和垂直視野的角度,以度爲單位。 - pantilt [ pan:
tilt: ] 相機的朝向角度,以度爲單位。左右位置稱爲 pan,上下位置稱爲 tilt。
4.設置激光雷達
stage中的ranger模型可以模擬激光雷達。在laser.inc中輸入如下代碼:
define my_laser ranger
(
sensor(
range [ 0.0 15.0 ] # 雷达数据采集区间
fov 360.0 # 视角
samples 720 # 采样数
color_rgba [ 0 0 1 0.15 ] # 可视化光束颜色以及透明度
)
model # 雷达外观
(
pose [ 0 0 0 0 ] # 雷达位姿
size [ 0.07 0.07 0.05 ] # 雷达尺寸信息
color "blue" # 雷达颜色
)
)
ranger摘要和默認值
sensor(
samples 180
range_max 8.0
fov 360.0
resolution 1
size [ 0.15 0.15 0.2 ]
color "blue"
)
詳解
- samples
每次掃描的激光樣本數量。 - range_max
激光掃描儀所報告的最大距離,以米爲單位。掃描儀將不會檢測超出此範圍的物體。 - fov
激光掃描儀的角度視野。 - resolution
僅計算第 n 個激光樣本的真實距離。缺失的樣本將用線性插值填充。一般來說,使用較少的樣本會更好,但某些(實現不好的)程序需要固定數量的樣本數。設置此數字大於 1 可以減少所需的計算量,適用於固定大小的激光矢量。
5.組裝機器人
在mycar.inc中實現機器人的組裝:
# 组装机器人各个模块
include "robot/car_base.inc"
include "robot/camera.inc"
include "robot/laser.inc"
define my_car car_base(
my_camera(pose [0.15 0 0 0])
my_laser()
)
my_car模型是在car_base模型之上,集成了my_camera和my_laser模型。
6.在仿真環境中生成機器人
在sim.world中添加如下代碼生成一個機器人:
# -----------------------------------------------------------------------------
# 生成机器人
# 文件包含
include "robot/mycar.inc"
my_car(
name "robot_0"
color "red"
pose [ -3 -7 0 90 ]
)
7.構建執行
構建功能包並執行launch文件後,運行結果如下。
啓動rviz2可以查看仿真環境下傳感器相關數據,啓動鍵盤控制節點後,也可以控制機器人運動。


stage_ros2添加多機器人
在stage_ros2中也可以很方便的生成多個機器人。
1.生成多個機器人
在sim.world中還可以繼續創建my_car對象以生成新的機器人模型,添加代碼如下:
my_car(
name "robot_1"
color "yellow"
pose [ -1 -7 0 90 ]
)
2.構建執行
構建功能包並執行launch文件後,運行結果如下。

在多機器人運行時,不同的機器人發佈的話題會以各自對應的name值爲命名空間,且不同機器人發佈的座標變換也會以name值爲前綴。