Robotics StackExchange | Archived questions

implement ros2 control for a 4 wheel differential drive robot

Hello. I am trying to implement ros2 control (controller manager(YAML) and resource manager(URDF)) for controlling a 4 wheel robot. I have been following this video https://youtu.be/4QKsDf1c4hc but the problem is this video is for a 2 wheel robot and i want the same for a 4 wheel robot. I made the changes that if felt like but it dose'nt seems to work. The robot isnt moving at all. To keep things simple i am only using the frromnt 2 wheels and have set the friction of others 2 wheels near to zero.

Version: ROS2 Foxy

NOET: The formatting of this question is not good as i don't use answers.ros.org much.

Here is the Terminal window. It says "No Parameter file provided. Configuration might be wrong.".

[INFO] [launch]: Default logging verbosity is set to INFO [INFO] [robotstatepublisher-1]: process started with pid [8629] [INFO] [gzserver-2]: process started with pid [8631] [INFO] [gzclient -3]: process started with pid [8633] [INFO] [spawnentity.py-4]: process started with pid [8637] [robotstatepublisher-1] Parsing robot urdf xml string. [robotstatepublisher-1] Link chassis had 0 children [robotstatepublisher-1] Link leftbackwheel had 0 children [robotstatepublisher-1] Link leftfrontwheel had 0 children [robotstatepublisher-1] Link rightbackwheel had 0 children [robotstatepublisher-1] Link rightfrontwheel had 0 children [robotstatepublisher-1] [INFO] [1690008080.390969324] [robotstatepublisher]: got segment baselink [robotstatepublisher-1] [INFO] [1690008080.391176286] [robotstatepublisher]: got segment chassis [robotstatepublisher-1] [INFO] [1690008080.391219615] [robotstatepublisher]: got segment leftbackwheel [robotstatepublisher-1] [INFO] [1690008080.391240687] [robotstatepublisher]: got segment leftfrontwheel [robotstatepublisher-1] [INFO] [1690008080.391258528] [robotstatepublisher]: got segment rightbackwheel [robotstatepublisher-1] [INFO] [1690008080.391274062] [robotstatepublisher]: got segment rightfrontwheel [spawnentity.py-4] [INFO] [1690008081.377614596] [spawnentity]: Spawn Entity started [spawnentity.py-4] [INFO] [1690008081.378793862] [spawnentity]: Loading entity published on topic robotdescription [spawnentity.py-4] [INFO] [1690008081.383456827] [spawnentity]: Waiting for entity xml on robotdescription [spawnentity.py-4] [INFO] [1690008081.397657830] [spawnentity]: Waiting for service /spawnentity, timeout = 30 [spawnentity.py-4] [INFO] [1690008081.398936932] [spawnentity]: Waiting for service /spawnentity [spawnentity.py-4] [INFO] [1690008082.415332383] [spawnentity]: Calling service /spawnentity [spawnentity.py-4] [INFO] [1690008082.801100218] [spawnentity]: Spawn status: SpawnEntity: Successfully spawned entity [my_bot] [gzserver-2] [INFO] [1690008082.863398740] [gazeboros2control]: Loading gazeboros2control plugin [gzserver-2] [INFO] [1690008082.881170339] [gazeboros2control]: Starting gazeboros2control plugin in namespace: / [gzserver-2] [INFO] [1690008082.883576700] [gazeboros2control]: Starting gazeboros2control plugin in ros 2 node: gazeboros2_control [gzserver-2] [ERROR] [1690008082.884737693] [gazeboros2control]: No parameter file provided. Configuration might be wrong [gzserver-2] [ERROR] [1690008082.885931611] [gazeboros2control]: failed to parse input yaml file(s) [INFO] [spawn_entity.py-4]: process has finished cleanly [pid 8637]

The ".yaml" file:

controllermanager: rosparameters: updaterate: 30 usesim_time: true

  diff_cont:
    type: diff_drive_controller/DiffDriveController

  joint_broad:
    type: joint_state_broadcaster/JointStateBroadcaster

diffcont: ros_parameters:

publish_rate: 50.0

base_frame_id: base_link

left_wheel_names: ['left_front_wheel_joint']
right_wheel_names: ['right_front_wheel_joint']
wheel_separation: 0.36
wheel_radius: 0.1

use_stamped_vel: false

# open_loop: false    

# wheels_per_side: x
# wheel_separation_multiplier: x
# left_wheel_radius_multiplier: x
# right_wheel_radius_multiplier: x

# odom_frame_id: x
# pose_covariance_diagonal: x
# twist_covariance_diagonal: x
# open_loop: x
# enable_odom_tf: x

# cmd_vel_timeout: x
# publish_limited_velocity: x
# velocity_rolling_window_size: x


# linear.x.has_velocity_limits: false
# linear.x.has_acceleration_limits:

false # linear.x.hasjerklimits: false # linear.x.maxvelocity: NAN # linear.x.minvelocity: NAN # linear.x.maxacceleration: NAN # linear.x.minacceleration: NAN # linear.x.maxjerk: NAN # linear.x.minjerk: NAN

# angular.z.has_velocity_limits: false
# angular.z.has_acceleration_limits:

false # angular.z.hasjerklimits: false # angular.z.maxvelocity: NAN # angular.z.minvelocity: NAN # angular.z.maxacceleration: NAN # angular.z.minacceleration: NAN # angular.z.maxjerk: NAN # angular.z.minjerk: NAN

joint_broad:

ros__parameters:

The Launch File:

import os

from amentindexpython.packages import getpackageshare_directory

from launch import LaunchDescription from launch.actions import IncludeLaunchDescription from launch.launchdescriptionsources import PythonLaunchDescriptionSource

from launch_ros.actions import Node

def generatelaunchdescription():

# Include the robot_state_publisher launch file, provided by our own package. Force sim time to be enabled
# !!! MAKE SURE YOU SET THE PACKAGE NAME CORRECTLY !!!

package_name='my_bot' #<--- CHANGE ME

rsp = IncludeLaunchDescription(
            PythonLaunchDescriptionSource([os.path.join(
                get_package_share_directory(package_name),'launch','rsp.launch.py'
            )]), launch_arguments={'use_sim_time': 'true'}.items()
)

# Include the Gazebo launch file, provided by the gazebo_ros package
gazebo = IncludeLaunchDescription(
            PythonLaunchDescriptionSource([os.path.join(
                get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')]),
         )

# Run the spawner node from the gazebo_ros package. The entity name doesn't really matter if you only have a single robot.
spawn_entity = Node(package='gazebo_ros', executable='spawn_entity.py',
                    arguments=['-topic', 'robot_description',
                               '-entity', 'my_bot'],
                    output='screen')



# Launch them all!
return LaunchDescription([
    rsp,
    gazebo,
    spawn_entity,
])

The urdf file:

<?xml version="1.0"?>

<xacro:include filename="inertial_macros.xacro"/>

<material name="white">
    <color rgba="1 1 1 1" />
</material>

<material name="orange">
    <color rgba="1 0.3 0.1 1" />
</material>

<material name="blue">
    <color rgba="0.2 0.2 1 1" />
</material>

<material name="black">
    <color rgba="0 0 0 1" />
</material>


<!-- BASE LINK -->
<link name="base_link">

</link>


<!-- CHASSI LINK -->
<joint name="chassis_joint" type="fixed">
    <parent link="base_link"/>
    <child link="chassis"/>
    <origin xyz="-0.1 0 0"/>
</joint>

<link name="chassis">
    <visual>
        <!-- <origin xyz="0.15 0 0.075"/>   # This line is used to move the chasis relative to its link -->
        <geometry>
            <box size="0.5 0.3 0.05"/>
        </geometry>
        <material name="white"/>
    </visual>

    <collision>
        <!-- <origin xyz="0.3 0 0.075"/>   0.15 0 0.075 -->
        <geometry>
            <box size="0.5 0.3 0.3"/>
        </geometry>
    </collision>

    <xacro:inertial_box mass="0.5" x="0.5" y="0.3" z="0.05">
        <origin xyz="0 0 0" rpy="0 0 0"/>
    </xacro:inertial_box>
</link>

<gazebo reference="chassis">
    <material>Gazebo/Orange</material>
</gazebo>

<!-- LEFT FRONT WHEEL LINK -->
<joint name="left_front_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="left_front_wheel"/>        
    <origin xyz="0.15 0.18 0" rpy="-${pi/2} 0 0"/>
    <axis xyz="0 0 1"/>
</joint>

<link name="left_front_wheel">
    <visual>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
        <material name="blue"/>
    </visual>
    <collision>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
    </collision>

    <xacro:inertial_cylinder mass="0.1" length="0.04" radius="0.1">
        <origin xyz="0 0 0" rpy="0 0 0"/>
    </xacro:inertial_cylinder>
</link>

<gazebo reference="left_front_wheel">
    <material>Gazebo/Blue</material>
</gazebo>

<!-- RIGHT FRONT WHEEL LINK -->
<joint name="right_front_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="right_front_wheel"/>        
    <origin xyz="0.15 -0.18 0" rpy="${pi/2} 0 0"/>
    <axis xyz="0 0 -1"/>
</joint>

<link name="right_front_wheel">
    <visual>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
        <material name="blue"/>
    </visual>
    <collision>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
    </collision>    

    <xacro:inertial_cylinder mass="0.1" length="0.04" radius="0.1">
        <origin xyz="0 0 0" rpy="0 0 0"/>
    </xacro:inertial_cylinder>
</link>

<gazebo reference="right_front_wheel">
    <material>Gazebo/Blue</material>
</gazebo>

<!-- LEFT BACK WHEEL LINK -->
<joint name="left_back_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="left_back_wheel"/>        
    <origin xyz="-0.35 0.18 0" rpy="-${pi/2} 0 0"/>
    <axis xyz="0 0 1"/>
</joint>

<link name="left_back_wheel">
    <visual>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
        <material name="blue"/>
    </visual>
    <collision>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
    </collision>

    <xacro:inertial_cylinder mass="0.1" length="0.04" radius="0.1">
        <origin xyz="0 0 0" rpy="0 0 0"/>
    </xacro:inertial_cylinder>
</link>

<gazebo reference="left_back_wheel">
    <material>Gazebo/Blue</material>
    <mu1 value="0.001"/>
    <mu2 value="0.001"/>
</gazebo>

<!-- RIGHT BACK WHEEL LINK -->
<joint name="right_back_wheel_joint" type="continuous">
    <parent link="base_link"/>
    <child link="right_back_wheel"/>        
    <origin xyz="-0.35 -0.18 0" rpy="${pi/2} 0 0"/>
    <axis xyz="0 0 -1"/>
</joint>

<link name="right_back_wheel">
    <visual>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
        <material name="blue"/>
    </visual>
    <collision>
        <geometry>
            <cylinder radius="0.1" length="0.04"/>
        </geometry>
    </collision>

    <xacro:inertial_cylinder mass="0.1" length="0.04" radius="0.1">
        <origin xyz="0 0 0" rpy="0 0 0"/>
    </xacro:inertial_cylinder>
</link>

<gazebo reference="right_back_wheel">
    <material>Gazebo/Blue</material>
    <mu1 value="0.001"/>
    <mu2 value="0.001"/>
</gazebo>

Thanks

Asked by KalaDaku on 2023-07-22 02:04:29 UTC

Comments

Answers

The gazebo_ros_diff_drive plugin in the gazebo_ros_pkgs for ros2 allows you to control a robot with as many wheels as you want per side. Here is an example for a 8 wheeled vehicle:

 <gazebo>
    <plugin name='diff_drive' filename='libgazebo_ros_diff_drive_mod.so'>

    <ros>
      <namespace>/ARGJ801</namespace>
      <!--<remapping>cmd_vel:=cmd_demo</remapping>-->
      <remapping>odom:=odom_demo</remapping>
    </ros>

    <!-- wheels -->
    <num_wheel_pairs>4</num_wheel_pairs>
    <left_joint>jo_w1</left_joint>
    <left_joint>jo_w2</left_joint>
    <left_joint>jo_w3</left_joint>
    <left_joint>jo_w4</left_joint>

    <right_joint>jo_w5</right_joint>
    <right_joint>jo_w6</right_joint>
    <right_joint>jo_w7</right_joint>
    <right_joint>jo_w8</right_joint>
    <!-- kinematics -->
    <wheel_separation>1.35</wheel_separation>
    <wheel_diameter>0.64</wheel_diameter>

    <!-- limits -->
    <max_wheel_torque>500</max_wheel_torque>
    <max_wheel_acceleration>2.0</max_wheel_acceleration>

    <!-- output -->
    <publish_odom>true</publish_odom>
    <publish_odom_tf>false</publish_odom_tf>
    <publish_wheel_tf>false</publish_wheel_tf>

    <odometry_frame>odom</odometry_frame>
    <robot_base_frame>base_link</robot_base_frame>

  </plugin>
    </gazebo>

Asked by MSanMon on 2023-07-24 03:52:58 UTC

Comments