環境の概要とバージョン選定
ROS 1 (Noetic Ninjemys) を利用する場合、標準で統合されているシミュレータは Gazebo 11 (Classic) です。近年開発が進んでいる Ignition Gazebo (現 Gazebo Sim) とはアーキテクチャが異なり、ROS 1 との連携においては Classic 版本のドキュメントおよび SDF (Simulation Description Format) の仕様に準拠する必要があります。
本解説では、ROS 1 環境において独立した世界ファイルとモデルファイルを定義し、差分駆動型の車両モデルを構築する手順を示します。
シミュレーション世界ファイルの定義
まず、物理エンジンや照明、地面を含む環境定義ファイルを作成します。ここでは `ground_plane.world` として保存します。
<?xml version="1.0" ?>
<sdf version="1.7">
<world name="simulation_env">
<!-- 物理エンジンの設定 -->
<physics name="default_physics" type="ode">
<max_step_size>0.002</max_step_size>
<real_time_factor>1.0</real_time_factor>
</physics>
<!-- 必要なシステムプラグイン -->
<plugin filename="libgazebo_ros_factory.so" name="gazebo_ros_factory"/>
<plugin filename="libgazebo_ros_force.so" name="gazebo_ros_force"/>
<!-- 光源定義 (方向光) -->
<light name="sun_light" type="directional">
<cast_shadows>true</cast_shadows>
<pose>0 0 15 0 0 0</pose>
<diffuse>1.0 1.0 1.0 1</diffuse>
<specular>0.1 0.1 0.1 1</specular>
<direction>-0.5 0 -0.9</direction>
</light>
<!-- 地面モデル (静的オブジェクト) -->
<model name="static_ground">
<static>true</static>
<link name="ground_link">
<collision name="collision_plane">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>200 200</size>
</plane>
</geometry>
</collision>
<visual name="visual_plane">
<geometry>
<plane>
<normal>0 0 1</normal>
<size>200 200</size>
</plane>
</geometry>
<material>
<ambient>0.5 0.5 0.5 1</ambient>
<diffuse>0.5 0.5 0.5 1</diffuse>
</material>
</visual>
</link>
</model>
</world>
</sdf>
ロボットモデル (SDF) の作成
次に、車体と車輪を含むロボットモデルを定義します。ファイル名は `diff_drive_robot.sdf` とします。各リンクの慣性テンソルや質量は、形状から計算された仮定値です。
<sdf version="1.7">
<model name="diff_drive_bot" canonical_link="base_body">
<pose relative_to="world">0 0 0.5 0 0 0</pose>
<!-- 車体ベースリンク -->
<link name="base_body">
<inertial>
<mass>2.5</mass>
<inertia>
<ixx>0.15</ixx><ixy>0</ixy><ixz>0</ixz>
<iyy>0.25</iyy><iyz>0</iyz>
<izz>0.35</izz>
</inertia>
</inertial>
<visual name="chassis_vis">
<geometry>
<box>
<size>1.2 0.6 0.3</size>
</box>
</geometry>
<material>
<ambient>0.6 0.6 0.6 1</ambient>
<diffuse>0.6 0.6 0.6 1</diffuse>
</material>
</visual>
<collision name="chassis_col">
<geometry>
<box>
<size>1.2 0.6 0.3</size>
</box>
</geometry>
</collision>
</link>
<!-- 左車輪リンク -->
<link name="wheel_left">
<pose relative_to="base_body">-0.4 0.35 0 1.5707 0 0</pose>
<inertial>
<mass>0.8</mass>
<inertia>
<ixx>0.03</ixx><ixy>0</ixy><ixz>0</ixz>
<iyy>0.03</iyy><iyz>0</iyz>
<izz>0.05</izz>
</inertia>
</inertial>
<visual name="wheel_l_vis">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.15</length>
</cylinder>
</geometry>
<material>
<ambient>0.1 0.1 0.1 1</ambient>
<diffuse>0.1 0.1 0.1 1</diffuse>
</material>
</visual>
<collision name="wheel_l_col">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.15</length>
</cylinder>
</geometry>
</collision>
</link>
<!-- 右車輪リンク -->
<link name="wheel_right">
<pose relative_to="base_body">-0.4 -0.35 0 1.5707 0 0</pose>
<inertial>
<mass>0.8</mass>
<inertia>
<ixx>0.03</ixx><ixy>0</ixy><ixz>0</ixz>
<iyy>0.03</iyy><iyz>0</iyz>
<izz>0.05</izz>
</inertia>
</inertial>
<visual name="wheel_r_vis">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.15</length>
</cylinder>
</geometry>
<material>
<ambient>0.1 0.1 0.1 1</ambient>
<diffuse>0.1 0.1 0.1 1</diffuse>
</material>
</visual>
<collision name="wheel_r_col">
<geometry>
<cylinder>
<radius>0.3</radius>
<length>0.15</length>
</cylinder>
</geometry>
</collision>
</link>
<!-- 関節定義 (回転関節) -->
<joint name="joint_left" type="revolute">
<parent>base_body</parent>
<child>wheel_left</child>
<axis>
<xyz>0 1 0</xyz>
<limit>
<lower>-3.14</lower>
<upper>3.14</upper>
</limit>
</axis>
</joint>
<joint name="joint_right" type="revolute">
<parent>base_body</parent>
<child>wheel_right</child>
<axis>
<xyz>0 1 0</xyz>
<limit>
<lower>-3.14</lower>
<upper>3.14</upper>
</limit>
</axis>
</joint>
</model>
</sdf>
モデル設定ファイル (model.config)
SDF モデルを Gazebo が認識するためには、同一ディレクトリに `model.config` が必要です。
<?xml version="1.0"?>
<model>
<name>diff_drive_bot</name>
<version>1.0</version>
<sdf version="1.7">diff_drive_robot.sdf</sdf>
<author>
<name>Simulation User</name>
</author>
<description>Simple differential drive robot model</description>
</model>
Launch ファイルによる統合
最後に、世界ファイルとモデルファイルを読み込む ROS launch ファイルを作成します。`start_sim.launch` として保存し、引数を通じてパスを管理します。
<launch>
<arg name="world_name" default="$(find my_pkg)/worlds/ground_plane.world"/>
<arg name="model_name" default="diff_drive_bot"/>
<arg name="model_path" default="$(find my_pkg)/models/$(arg model_name)/$(arg model_name).sdf"/>
<!-- Gazebo の起動 -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(arg world_name)"/>
<arg name="paused" value="false"/>
<arg name="use_sim_time" value="true"/>
</include>
<!-- モデルのスポーン -->
<node name="spawn_robot" pkg="gazebo_ros" type="spawn_model" output="screen"
args="-sdf -file $(arg model_path) -model $(arg model_name) -x 0 -y 0 -z 0.5"/>
</launch>
上記の launch ファイルを実行することで、定義した物理環境内にロボットモデルが配置され、シミュレーションが開始されます。