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
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