ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

diff drive controller velocity limit

asked 2020-10-10 07:34:03 -0500

dinesh gravatar image

updated 2020-10-10 07:35:08 -0500

How does diff drive limits the maximum and minimum velocity limits exactly? I have set the max linear velocity of robot as 0.5 cm which has wheel radius of 0.05 m. When i debug the hardware interface and check the maximum angular velocity at full throttle it shows me w=v/r = 10 rad/sec which i have converted to range i.e [0,255] for pulse wide modulation of dc motors. Here the wheel encoders are sending the wheel angular velocity as 200 rad/sec to the hardware interface at same time. Now how is this actual velocity i.e 200 rad/sec going to be used by diff drive controller and the input velocity i.e 10 rad/sec be controlled ? Cas my robot is colliding with obstacle due to this large velocity of robot. Here are my parameters for the diff drive controller:

base_controller:
  type        : "diff_drive_controller/DiffDriveController"
  left_wheel  : 'wheel_left_joint'
  right_wheel : 'wheel_right_joint'
  publish_rate: 50.0               # default: 50
  pose_covariance_diagonal : [0.001, 0.001, 1000000.0, 1000000.0, 1000000.0, 1000.0]
  twist_covariance_diagonal: [0.001, 0.001, 1000000.0, 1000000.0, 1000000.0, 1000.0]
  # Wheel separation and diameter. These are both optional.
  # diff_drive_controller will attempt to read either one or both from the
  # URDF if not specified as a parameter
  wheel_separation : 1.0
  wheel_radius : 0.049

  # Wheel separation and radius multipliers
  wheel_separation_multiplier: 1.0 # default: 1.0
  wheel_radius_multiplier    : 1.0 # default: 1.0

  # Velocity commands timeout [s], default 0.5
  cmd_vel_timeout: 0.25

  # Base frame_id
  base_frame_id: base_link #default: base_link

  # Velocity and acceleration limits
  # Whenever a min_* is unspecified, default to -max_*
  linear:
    x:
      has_velocity_limits    : true
      max_velocity           : 0.5  # m/s
      min_velocity           : -0.5 # m/s
      has_acceleration_limits: true
      max_acceleration       : 0.2  # m/s^2
      min_acceleration       : -0.2 # m/s^2
      has_jerk_limits        : true
      max_jerk               : 1.0  # m/s^3
  angular:
    z:
      has_velocity_limits    : true
      max_velocity           : 1  # rad/s
      has_acceleration_limits: false
      max_acceleration       : 1.5  # rad/s^2
      has_jerk_limits        : false
      max_jerk               : 2.5  # rad/s^3

Here is the hardware interface:

#include <medicbot_control/medicbot_hw_interface.h>
#include <exception>
#include <algorithm>
#include <iostream>

#include <bits/stdc++.h> 
#include <boost/algorithm/string.hpp>

namespace rrbot_control
{

float myMap(float x, float in_min, float in_max, float out_min, float out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

std::string to_format(const int number,int decPlace) {
    std::stringstream ss;
    ss << std::setw(decPlace) << std::setfill('0') << number;
    return ss.str();
}

RRBotHWInterface::RRBotHWInterface(ros::NodeHandle &nh, urdf::Model *urdf_model)
  : ros_control_boilerplate::GenericHWInterface(nh, urdf_model)
{
    ROS_INFO_NAMED("rrbot_hw_interface", "RRBotHWInterface Ready.");
    Setup();
}

void RRBotHWInterface::read(ros::Duration &elapsed_time)
{
    const char* enc_ticks = Read();
    std::vector<std::string> result; 
    boost::split(result, enc_ticks, boost::is_any_of(",")); 
    for (int joint_id = 0; joint_id < result.size(); joint_id++) {
         float ang_vel = atof(result[joint_id].c_str());
         joint_velocity_[joint_id] = ang_vel*0.049;
         joint_position_[joint_id] += joint_velocity_[joint_id] * elapsed_time.toSec();
   }
   std::cout<<"joint_velocity_got:"<<joint_velocity_[0]<<"\t"<<joint_velocity_[1]<<std::endl;
   //std::cout<<"got data:"<<enc_ticks<<std::endl;

}

void RRBotHWInterface::write(ros::Duration &elapsed_time)
{
  // Safety
  enforceLimits(elapsed_time);

  // ----------------------------------------------------
  // ----------------------------------------------------
  // ----------------------------------------------------
  //
  // FILL IN YOUR WRITE COMMAND TO USB/ETHERNET/ETHERCAT/SERIAL ETC HERE
  //
  // FOR A EASY SIMULATION ...
(more)
edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
0

answered 2020-10-17 12:24:17 -0500

dinesh gravatar image

Ok i think i got the better answer and best approach. i.e ros control toolbox package already provides the classes for pid controller just needs to use them. http://docs.ros.org/en/jade/api/contr...

edit flag offensive delete link more
0

answered 2020-10-10 12:48:38 -0500

billy gravatar image

The link to the motor says it is 312RPM which would have a no-load max RPM of 32rad/sec. Your encoder however is likely on the motor end of the gear box and not on the wheel end, so you need to add in the gearing conversion before you try to convert encoder values to wheel rotation.

Then after you sort out how the gearing will impact encoder speed to wheel speed, you should take another look at this:

 if(joint_velocity_command_[0] < -1) 
      joint_velocity_command_[0] = -1;
  if(joint_velocity_command_[0] > 1)
      joint_velocity_command_[0] = 1;
  if(joint_velocity_command_[1] < -1)
          joint_velocity_command_[1] = -1;
  if(joint_velocity_command_[1] > 1)
      joint_velocity_command_[1] = 1;



float myMap(float x, float in_min, float in_max, float out_min, float out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

 float joint1_vel = myMap(joint_velocity_command_[0],-1,1,-255,255);

This limits inputs to -1 through +1, but you're attempting to input 10. By my accounting then the output from the equation should be 255 to the PWM <-- just as fast as it can go - so as far as I can tell, everything seems to be working correctly. Or rather, it's doing just what you told it to.

BTW: Regarding you're question about why ROS is not limiting speed to the max and min you set in the YAML file, it doesn't work the way you're thinking. It will limit the the path planning velocities(CMD_VEL) to the max and min in the YAML file but it is up to the HW driver to respond properly to the CMD_VEL. The path planner will not actively scale CMD_VEL if the HW is out of control.

edit flag offensive delete link more

Comments

so what is the best practice to make the actual linear velocity of robot to fit in min, max velocity range? And i found that the linear velocity is converted to angular velocity i.e joint velocity inside the hardware interfce.

dinesh gravatar image dinesh  ( 2020-10-11 00:41:47 -0500 )edit

You have encoder feed back. I suggest you use PID control the speed. Feed the CMD_VEL topic into a conversion to give you velocity requirements for each wheel and and then feed those velocity requirements into your PID functions, which will output the PWM values.

billy gravatar image billy  ( 2020-10-11 11:33:18 -0500 )edit

Isn't their PID control feature in the diff drive controller itself? I thought their is. So i have to make a function for this than?

dinesh gravatar image dinesh  ( 2020-10-11 12:22:40 -0500 )edit

I've not used it, so can't be sure but I just looked at this page and see no mention of anything related to tight closed loop control of the motors like PID. http://wiki.ros.org/diff_drive_contro...

billy gravatar image billy  ( 2020-10-11 22:03:03 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2020-10-10 07:34:03 -0500

Seen: 876 times

Last updated: Oct 17 '20