How to use ackermann plugin in ROS2 Humble

477 views Asked by At

I'm working on a urdf model of an ackermann car with 4 wheels. I want to use the ackerman gazebo plugin, in the github i found an example of usage that is the following:

<gazebo>
    <plugin name="gazebo_ros_ackermann_drive" filename="libgazebo_ros_ackermann_drive.so">

  <ros>
    <namespace>ackermann</namespace>
    <remapping>cmd_vel:=cmd_vel</remapping>
    <remapping>odom:=odom</remapping>
    <remapping>distance:=distance</remapping>
  </ros>

  <update_rate>100.0</update_rate>

  <!-- wheels -->
  <front_left_joint>front_left_joint</front_left_joint>
  <front_right_joint>front_eight_joint</front_right_joint>
  <rear_left_joint>rear_left_joint</rear_left_joint>
  <rear_right_joint>rear_right_joint</rear_right_joint>
  <left_steering_joint>left_steering_joint</left_steering_joint>
  <right_steering_joint>right_steering_joint</right_steering_joint>
  <steering_wheel_joint>steering_joint</steering_wheel_joint>
  

  <!-- Max absolute steer angle for tyre in radians-->
  <!-- Any cmd_vel angular z greater than this would be capped -->
  <max_steer>0.6458</max_steer>

  <!-- Max absolute steering angle of steering wheel -->
  <max_steering_angle>7.85</max_steering_angle>

  <!-- Max absolute linear speed in m/s -->
  <max_speed>20</max_speed>

  <!-- PID tuning -->
  <left_steering_pid_gain>1500 0 1</left_steering_pid_gain>
  <left_steering_i_range>0 0</left_steering_i_range>
  <right_steering_pid_gain>1500 0 1</right_steering_pid_gain>
  <right_steering_i_range>0 0</right_steering_i_range>
  <linear_velocity_pid_gain>1000 0 1</linear_velocity_pid_gain>
  <linear_velocity_i_range>0 0</linear_velocity_i_range>

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

  <odometry_frame>odom</odometry_frame>
  <robot_base_frame>base_footprint</robot_base_frame>

</plugin>
</gazebo>

My problem is on the joints because I made 4 continuous joints to make the wheels roll and two revolute joints to make the front wheels rotate along the z axis. These 4 joints are the first four joints that you can see in the plugin tags. My question is, what actually is the steering wheel joint? Where do I have to put it and how should it be linked to the other part of the car? If I remove that I don't actually have an error message but all my wheels move under the car to the center. If I just display the urdf on Rviz the model seems good. My urdf structure is made by a base_link for the body of the car, 4 wheels and a base_footprint.

This is the model launched only using Rviz:

Model when I only launch Rviz

This is when i launch gazebo and the plugin:

Model when I launch Gazebo and the plugin too

1

There are 1 answers

0
Ruggero Simonelli On

In general, the ackermann_drive plugin works by subscribing to a topic named cmd_vel (or with a different name, if you remap in the urdf file) of type geometry_msgs::msg::Twist, which means a message containing a target linear speed and a target yaw rate for the whole vehicle. Based on this targets, individual torque commands are generated for the driving and steering wheels with the PID controllers you set in the urdf.

In this sense, there is no steering wheel here, you are steering with this twist command. From what I understand by looking at the code, the steering_wheel_joint is not strictly needed, but you should not delete it, because, as you noticed, the whole links/joints structure is compromised. I guess that, if you have some link connected to the steering_wheel_joint, then it will be rendered as though it were the actual steering wheel, from the average of the left and right steering wheel (as opposite as to what happens in physical reality).

To look up this, you should actually open the plugin file at gazebo_ros_ackermann_drive.cpp

Just a snippet (lines 533-543, comments from me):

// computing the steering wheel angle averaging left and right
auto steer_wheel_angle = (left_steering_angle + right_steering_angle) * 0.5 / steering_ratio_;
// setting the steer torque on the steering wheels
joints_[STEER_LEFT]->SetForce(0, left_steering_cmd);
joints_[STEER_RIGHT]->SetForce(0, right_steering_cmd);
// setting the driving torque on the driving wheels
joints_[REAR_RIGHT]->SetForce(0, linear_cmd);
joints_[REAR_LEFT]->SetForce(0, linear_cmd);

if (joints_.size() == 7) {
  // setting the steer angle
  joints_[STEER_WHEEL]->SetPosition(0, steer_wheel_angle);
}

Also (lines 224-229):

// if the steering_wheel_joint is deleted
if (!impl_->joints_[GazeboRosAckermannDrivePrivate::STEER_WHEEL]) {
RCLCPP_WARN(
  impl_->ros_node_->get_logger(),
  "Steering wheel joint [%s] not found.", steering_wheel_joint.c_str());
  // the joints are potentially messed up
  impl_->joints_.resize(6);
}

For more detailed answer I would need more details from you :)

Hope this can help