ROS-Arduino-Bridge Twist message problem

297 views
Skip to first unread message

gerard M Kelly

unread,
Jul 19, 2015, 1:19:08 AM7/19/15
to hbrob...@googlegroups.com
Hi, I hope this is the correct place for this question.
I am using the ROS-Arduino-Bridge on a robot built on the Baron platform. All is going fairly well but am having issue when I wanted to calibrate the movement from twist messages and not sure where to look to debug. Small values cause no motor movement at all with 'm 0 0 ' commands being sent to the Arduino.
{linear: {x: .1, y: 0,z: 0}, caused motor zero to be sent
{linear: {x: 1, y: 0,z: 0}, caused motors to move very slow like 'm 4 4'

This platform has very low res encoders and slow motors. The settings for drivetrain in YAMl are:


# === Robot drivetrain parameters
wheel_diameter: 0.065
wheel_track: 0.14
encoder_resolution: 26
#gear_reduction: 1.0
motors_reversed: True

Any help on where I should look would be great. Could the low encoder tick count be a issue with the twist to M command math?

Thanks
Gerard

P Tiago Pereira

unread,
Jul 19, 2015, 11:01:38 AM7/19/15
to hbrob...@googlegroups.com
Gerard,

Quick question, 


the product page mentions 20 PPR, not 26 ?
  

Tiago

Rudy Rimland, CISSP

unread,
Jul 19, 2015, 8:10:11 PM7/19/15
to hbrob...@googlegroups.com
Answering because this looks like a good problem. And we will both
learn even if my answer is totally wrong. Please note I've read just
enough about ROS to be dangerous, so take what I say with a grain of
salt until someone with a clue checks it... But I think you are on the
right track with the low encoder resolution.

Looking at this code (which I am guessing(!) you are running, except
maybe indigo version?):

https://github.com/hbrobotics/ros_arduino_bridge/blob/hydro-devel/ros_arduino_firmware/src/libraries/ROSArduinoBridge/diff_controller.h

Looking at a few lines in the doPID method (Treat my comments as
hypothesis to test):
input = p->Encoder - p->PrevEnc; //Since you have few encoder
updates, input is generally 0, rarely 1
// I think you count 1 tick
every 13 degrees or so

Perror = p->TargetTicksPerFrame - input; // resetPID sets
TargetTicksPerFrame to 0.0
// I can't see where it is
ever changed after that
// I'm missing something here,
this is probably set somewhere else earlier

output = (Kp * Perror - Kd * (input - p->PrevInput) + p->ITerm) / Ko;
// So this looks like a small
number divided by 50

p->PrevEnc = p->Encoder; // And this is usually a noop

output += p->output; // often 0 + 0 = 0

p->ITerm += Ki * Perror; // Ki = 0 after resetPID, ITerm
is initialized to 0
// 0 + (0 * Perror) = 0...

The updatePID method reads the encoders, decides if the PIDs need to be
reset, runs doPID, and calls setMotorSpeeds. Poking around in this (or
these) method(s) will tell you on what values you are basing the settings.

If this is the code managing your "twist to M command math", try
changing Ko to a smaller number. I don't think this is the right fix,
but your wheels should spin faster! (You do have your 'bot on a stand,
right?) At least it will confirm you are running this code (or you
aren't). Kp is more likely to be a correct tuning parameter, but I'm a
little rusty on PID control right now.

And looking at this code from another angle, using your wheel diameter
and encoder ticks, your target distance of 0.1 meters is about a 1/2
rotation, so about 13 ticks of the encoder away (applying small angle
approximation for sines). Therefore I think Perror should start at
about 13, so where does targetTicksPerFrame get set, what is its value?
Perror depends on this. Then I would expect output = (20*13 - 0 + 0)/50
= 5.2 as the initial move using the default PID tuning parameters. This
is Kp*Perror - the derivative term (you haven't moved yet) + the
integral term (again, you haven't moved yet). But you are getting 0,
not 5... So hmm... What is the value of targetTicksPerFrame? Assuming
this *is* the correct piece of code...

Regards and good luck,
Rudy

gerard M Kelly

unread,
Jul 19, 2015, 9:42:00 PM7/19/15
to hbrob...@googlegroups.com

Rudy
  Yes the PID did need some tweaking for the low resolution encoders. Sounds like you know this well, but that is working ok now and tracks well when the Arduino receives a "M x x" command. My issue is the base controller node is only sending "m 0 0" on small  X movement requests.

gerard M Kelly

unread,
Jul 19, 2015, 9:42:00 PM7/19/15
to hbrob...@googlegroups.com
Tiago
   Yes that is them and you are correct, I was playing with number to see what effect it had on the math in the base controller.py.  My real issue is that when I send the small x numbers like .1 the base controller never sends anything but "M 0 0" so no movment

Rudy Rimland, CISSP

unread,
Jul 19, 2015, 11:03:26 PM7/19/15
to hbrob...@googlegroups.com
Just noticed, the output variable is a long in updatePID, but is passed as an int when calling setMotorSpeeds in motorDrivers.h according to:

http://docs.ros.org/hydro/api/ros_arduino_firmware/html/motor__driver_8h.html#a87bd5cdc156e3b2d512f5c82bebbd250

Wonder what the type definitions and conversion rules are on your platform (since you aren't getting compile errors because of this)...  Are your values so small that they are effectively rounding down?  To 0?  Or am I looking at docs which have nothing to do with each other...

Can you give post some pointers to which versions and platforms you are using?  And your PID tweaks?

Oh, and using 20 instead of 26 counts/revolution changes my analysis from 13 to 10 encoder counts, so I would expect exactly 4 (instead of 5[.2]) where you get 0 using default PID parameters.  I would also predict 40 for a 1 meter move, not the 4 you now get.  But this may all change with your modified PID parameters.

Which also brings me back to wanting to know the initial value of TargetTicksPerFrame.  I don't yet know what a frame is in this context.

Regards,
Rudy


On 7/19/15 8:37 PM, gerard M Kelly wrote:

Rudy
  Yes the PID did need some tweaking for the low resolution encoders. Sounds like you know this well, but that is working ok now and tracks well when the Arduino receives a "M x x" command. My issue is the base controller node is only sending "m 0 0" on small  X movement requests.
--
You received this message because you are subscribed to the Google Groups "HomeBrew Robotics Club" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hbrobotics+...@googlegroups.com.
To post to this group, send email to hbrob...@googlegroups.com.
Visit this group at http://groups.google.com/group/hbrobotics.
For more options, visit https://groups.google.com/d/optout.

Mark Johnston

unread,
Jul 20, 2015, 1:45:47 AM7/20/15
to hbrob...@googlegroups.com

I'm not looking at any code but a classic way to make a small number go to 0 is to assign a float like the wheel rotation into an integer.  Since for really small encoder counts you may run into a place that assumed a lot of counts per revolution and it keeps setting some float like  0.35 into an int and keeps adding them up.   Well ...   0 + 0 + 0 + 0 and so on will be a lot smaller than  4 * 0.35     just watch for that one.
Good luck.

P Tiago Pereira

unread,
Jul 20, 2015, 4:13:11 AM7/20/15
to hbrob...@googlegroups.com
Gerard,

you can't use the arduinoROSBridge as it is with your encoders, although you can try to hack or adjust the code for your needs.

There are no issues with code, and it works very well with decent encoders.

some math/facts:

Based on your numbers, for 1 meter per second, your encoders output are 98 ticks, for 10 cm are 9,8 ticks.

Both the ArduinoRosBridge Python code and the Arduino ROS Bridge have a hardcoded PID at 30Hz per sec.

python code (line 43-44):


firmware code (line 104):



for 0.1 m/s => 9.8 ticks => 9.8 \ 30 => 0

change the Python code and setup the PID RATE to 1, this way the python code will send to the firmware the desired ticks per second regardless of the PID RATE.

on the firmware code, you will get the value, and you will need to decide if you want to run a PID at lower rates 1, 2 times per second which is not good for a PID algorithm. If you ran a pid 2 Hz means 9.8 ticks / 2 => 4 ticks per PID interval.

if you don't want to embrace big code hacks, you can try to change the PID rate to 2, 3 on both sides, and see if you can get any results.

more...

If you send a m 9 9, the firmware code has a fail safe stop line 114, of 2 seconds, this means if you don't send another m command, the firmware will stop the motors. If you are tweaking for testing you should increase this value, to avoid stopping your efforts.

If you run a PID at lower rates, and the PWM value starts from 1, this means it will take a lot of time to reach the desired speed, unless you find a good PID algorithm/variables, it will be difficult to be successful adjusting the motor speeds at lower intervals.

some folks will argue to measure time between ticks versus counting ticks, i tried that too without success, if you want to try and to have some consistent values you need to measure the same transition e.g. 0->1 or 1->0 otherwise the 1 or 0 intervals will be different.

if anyone has a good idea to implement a PID/algorithm with lower encoders, i'm interested too.

Cheers,
Tiago

gerard M Kelly

unread,
Jul 20, 2015, 9:38:29 AM7/20/15
to hbrob...@googlegroups.com
Tiago you are dead on. Last night I found the pid rate and intervals in the PY code while debugging. I had changed the Arduino pid interval a while back to 2 HZ and set some agresive parameters to bring it up to speed faster but did not no about the PY parameters. Changed PY parameters to 2 HZ and now it works......but like you say not the best or most reliable. I will have to study and decide how to make it as accurate as possible. On the good side when running the ROS by. Example RBX linear calibration test the movement is quite accurate at any given speed. The bad news is it is diffrent at diffrent speeds.

Thanks to all that commented it was a great help and anyone with some good ideas on adjustments keep it coming.
Reply all
Reply to author
Forward
0 new messages