Robotics StackExchange | Archived questions

ros_control code sample for a diff_drive

I am hoping your answer will serve as template for setting up diff_drive on a physical robot. Such a resource is missing, and is strongly needed.

Could you please create a small amount of code that will produce the equivalent of a hello world program for a hardwareinterface that utilizes a diffdrive controller? or asked another way, could you please provide a hardwareinterface implementation sample that utilizes a diffdrive controller? Please ignore advanced capabilities such as real-time capability, transmissions, limits, or any of that fancy stuff.

Why don't I do it myself? On account of a lack of documentation for ros_control and my lack of C++ skills I am not able to convert valuable examples I found into my own working code. Valuable examples being:

Could you please help by writing the simplest most minimalistic C++ code for these files:

and

Code that is external to roscontrol that hardwareinterface node calls in read() and write(), such as converting diffdrive output (radians/second) to wheel motion, collecting feedback from the robot, as well as the URDF file is finished can be found here: https://github.com/Toronto-Robotics-club/diffdrive-tutorial.

If someone chooses to answer this question, I will integrate the code you provide, with my code and test it out on a physical robot. By testing I mean I will use rospub to publish to the topic to which the diff drive subscribes to for geometry_msgs/Twist messages and observe the robot’s physical motion, and if needed modify the code you provided (with your permission) to verify that it works and is solid resource for the community.

Thanks.

Asked by BuilderMike on 2019-07-26 10:13:29 UTC

Comments

There might be readers here who would not have time / be in a position to write a complete hardware_interface for you, but who may be able to help you if you could describe what it is that you don't understand in the repositories / examples that you link to.

Asked by gvdhoorn on 2019-07-28 12:07:57 UTC

@gvdhoorn Since I am not a programmer, when I encounter complex code with no documentation (such as in this case) usually I am not able to hack my way to a working solution. I do know that the examples I mentioned are good, but they do not have a standardized structure, they have a bunch of code that I cannot distinguish as relevant to me or not, and generally without some guidance I have not been able to get very far. believe me I tried. If I begin to ask questions about what I do not understand, there will be at least 50 "noob" type questions that are not going to be very impressive. My thoughts were to get someone to finally create an answer that others like me (those who rely on simple documentation to build from) can use to implement a diff_drive controller. Such a resource can then be used by many to spin off their own code, and when they encounter failure, then, they can ask specific questions that can be of use to others. What do you think about my thoughts? Am I way off?

Asked by BuilderMike on 2019-08-02 20:20:04 UTC

My thoughts were to get someone to finally create an answer that others like me [..] can use to implement a diff_drive controller

A controller, or a hardware_interface? diff_drive_controller already exists, and you shouldn't need to create it for your own system.


Edit: if you're actually asking for an example hardware_interface implementation then the answer would be relative simple to give, but it would also miss quite some implementation details (specifically: how it interfaces with the underlying hw, which is the job of a hardware_interface).

If you're really asking for a controller, that would be something else.

Asked by gvdhoorn on 2019-08-03 06:07:58 UTC

@gvdhoorn edit: I misspoke, I do not need to implement a diff_drive controller, I need help to implement the hardware_interface (as a complete sample) that utilizes a diff_drive controller. As for the underlying hw, that code is already written in the form of a library. My library needs a radians/sec input and then takes care of the corresponding wheel motion (can be found here: https://github.com/Toronto-Robotics-club/diff_drive-tutorial/tree/master/jimmycpp) . If someone could please provide a hardware_interface sample that utilizes a diff drive controller (including the src and include files), or provide a link to the most basic sample that would be very, very, very appreciated.

Asked by BuilderMike on 2019-08-03 11:25:31 UTC

Does my ugly code help? turtlebot3_custom_hardware.h: Set for two wheels, ignore the dynamic reconfigure part. Insert the hardware specific code in read() and write(). Or could you just add your code and tell us your error?

Asked by Humpelstilzchen on 2019-08-06 00:47:55 UTC

@humpelstilzchen what kind of hardware does your code speak to? I see that you are giving RPM targets over i2c. Is the pid handled by the controller?

Asked by wintermute on 2019-11-19 19:15:10 UTC

Yes, the pid is running on an AVR microcontroller.

Asked by Humpelstilzchen on 2019-11-20 00:38:35 UTC

@humpelstilzchen I am working on the same thing as OP. Can you help me understand a little of the code you linked to? Is the hardware_interface class running under ROS or on the Arduino which is controlling the motors? Also does your "ugly code" work well?

Asked by pitosalas on 2020-02-14 16:43:48 UTC

@pitosalas The hardware_interface class must run on under ROS, that is the whole point. The "ugly code" surely runs well, that is the point of ROS control, to get something working without much effort. Ignore the cbDynReconf() function in my code, the important once are read() and write(). What you need to do is 1. accept a velocity command in rad/s for each wheel in write() 2. read current velocity for each wheel in rad/s in read().

The hardware specific part is to 1. translate rad/s to PWM (write()) or 2. encoder values to rad/s (read()).

You can do that either on the Arduino or in the hardware_interface, this is up to you. E.g. in the case of the velocity command you could do for example: 1. The hardware_interface sends rad/s to the Arduino and the Arduino calculates the desired PWM with a PID. (Good idea since the Arduino can do realtime) 2. The hardware_interface calculates the PWM with a PID on a Linux/ROS Computer and sends raw PWM values to the Arduino.

Asked by Humpelstilzchen on 2020-02-14 17:27:32 UTC

Or from the other point of view when adapting a new robot to ROS first: 1. Make sure you can you send the speed for each wheel in rad/s to its hardware and read its current speed in rad/s. This is the hardware specific part where ROS can not help you. 2. Once you have done that you use ros_control to adapt your robot to the ROS ecosystem.

Asked by Humpelstilzchen on 2020-02-14 17:32:27 UTC

Or from the other point of view when adapting a new robot to ROS first: 1. Make sure you can you send the speed for each wheel in rad/s to its hardware and read its current speed in rad/s. This is the hardware specific part where ROS can not help you

+1 for the rest of the comments, but this is not true.

It's perfectly possible to run a closed-loop velocity controller on the ros_control side. Completely hard-real-time as well.

You just need to have the required resources available in your hw interface.

Asked by gvdhoorn on 2020-02-15 07:07:37 UTC

@gvdhoorn I can't follow you. Can you be a bit more verbose please? Sure with e.g. a patched Linux you can do real-time, but I would not recommend that for beginners. But what does this have to do with writing/reading wheel speeds?

Asked by Humpelstilzchen on 2020-02-15 07:22:36 UTC

You stated that "ROS can not help you" with setting up a velocity control loop over some wheels with an encoder. While it's true decoding the encoders is probably best done by dedicated hw, it is possible to do this within the ros_control context as well.

Seeing as there is a lot of confusion about ros_control, I wanted to make sure (future) readers don't get the wrong ideas about what is and what isn't possible.

Asked by gvdhoorn on 2020-02-15 07:32:20 UTC

Actually I meant the hardware access and algorithms behind that (how do I write a pwm value, read my encoders or calculate the current speed from encoder ticks, PID tuning...)

Asked by Humpelstilzchen on 2020-02-15 07:45:06 UTC

@humpelstilzchen Thanks for the fantastic links and code. And the commentary. I still think it would be nice if someone who knew could offer a baseline hardware_interface guide which is not a link to code for a robot that includes all the robot code, but rather a clean guide. I imagine a package with nothing else than the hardware_interface source and header file and spots to "insert your code here". Starting with the assumption that the reader knows exactly how to read and write their encoders and motors but needs guidance with the shim code. If you are willing to help me I would be glad to write and document just such a guide. (Believe me like OP has said, we've tried.) This would help others and alleviate some of the confusion that @gvdhoorn was discussing. What say you?

Asked by pitosalas on 2020-02-18 09:23:49 UTC

I imagine a package with nothing else than the hardware_interface source and header file and spots to "insert your code here".

that was / is the purpose of PickNikRobotics/ros_control_boilerplate.

Problem with such "guides" or "templates" is: they make assumptions (even implicit ones) about how you should structure your code, which may not be as portable to every use-case and implementation as imagined.

Asked by gvdhoorn on 2020-02-18 09:27:56 UTC

Wow, that looms promising. I have not come across that before. Maybe I missed it. I will study it and come back if necessary!

Asked by pitosalas on 2020-02-18 09:46:31 UTC

Answers

Of all the diff drive projects I was able to find, the best samples have been: https://github.com/eborghi10/my_ROS_mobile_robot and (https://github.com/husky/husky) Clearpath's Husky.

Asked by BuilderMike on 2020-01-02 21:00:40 UTC

Comments

this page also seems quite useful. I would appreciate if anyone else also let me/us know if there was a simple implementation, preferably without gazebo. I myself still haven't found my way in implementing the harware interface.

Asked by azerila on 2020-04-12 09:12:38 UTC

Comments