ROS 1 環境下での Gazebo Classic による差分駆動ロボットの SDF 建模

環境の概要とバージョン選定

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 ファイルを実行することで、定義した物理環境内にロボットモデルが配置され、シミュレーションが開始されます。

タグ: ros1 gazebo-11 sdf robot-simulation differential-drive

10月9日 18:07 投稿