<div style="color:black;font: 10pt Arial, Helvetica, sans-serif;">
<div><span style="font-size: 13.3333px;">Possible source of oscillation: Will Kuhnle warned me to not put encoders on the wheels or on the output shaft of the gearbox, else the windup and unwrapping of the gears would cause oscillation and gearbox damage. Analog controls such as PID need to be before the gearbox. I may have misunderstood, and I may be misrepresenting the admonition Will gave me, but it does sound right to me.</span></div>

<div><span style="font-size: 13.3333px;"><br>
</span></div>

<div><span style="font-size: 13.3333px;">Bob Pease wrote about PID tuning and how it is no different than fuzzy logic in the sense that one can be transformed into the other with exactly the same response.</span></div>

<div><span style="font-size: 13.3333px;"><br>
</span></div>

<div><span style="font-size: 13.3333px;">I thought someone posted a PID tuning algorithm long ago here. I don't care about it very much, so I haven't looked for it. I think maybe Will or Ron made a presentation on it. It doesn't require tweaking. It chooses the correct settings merely based on the system's response.</span></div>

<div><span style="font-size: 13.3333px;"><br>
</span></div>

<div><span style="font-size: 13.3333px;">If you can kick the thing, you can measure its impulse response and made a filter without doing any tuning. I think the reason that isn't done more often is that it's nearly impossible to give the thing a good impulse kick. But it's definitely what the large FIRST teams do. Their very heavy, very tall robots fling themselves across large arenas and stop with no wiggling even though their frames are not completely rigid. I know at least one team does this with frequency response plots.</span></div>

<div><span style="font-size: 13.3333px;"><br>
</span></div>

<div><span style="font-size: 13.3333px;">None of this requires ML or AI, and ML and AI do not make it better, easier, faster, or cheaper.</span></div>

<div><span style="font-size: 13.3333px;"><br>
</span></div>

<div><span style="font-size: 13.3333px;">Later,</span></div>

<div><span style="font-size: 13.3333px;">John Swindle</span></div>
<br>
<br>

<div style="font-family:arial,helvetica;font-size:10pt;color:black">-----Original Message-----<br>
From: Carl Ott via DPRGlist <dprglist@lists.dprg.org><br>
To: Murray Altheim <murray18@altheim.com><br>
Cc: DPRG <dprglist@lists.dprg.org><br>
Sent: Sat, Jan 23, 2021 7:57 am<br>
Subject: Re: [Dprglist] Assisting PID odometry with an IMU<br>
<br>

<div id="yiv8488832392">
<div>
<div dir="ltr">
<div dir="ltr">
<div><br clear="none"></div>

<div>Hi Murray,</div>

<div><br clear="none"></div>

<div>regarding PID tuning of your heading loop -</div>

<div><br clear="none"></div>

<div>have you tried to examine the heading loop step response?</div>

<div><br clear="none"></div>

<div>For example - what happens if you place your robot on that turntable at your desk -</div>

<div>turn on the PID loop so that the robot tries to maintain a constant heading, without any forward motion -</div>

<div>then give the turntable various disturbances - especially abrupt step-function changes - where you slew the table 30 or 40 degrees, with the slew-rate change in table rotation speed as high as possible (ie. zero to max turn-rate as quickly as possible, then max turn-rate to zero as quickly as possible).</div>

<div><br clear="none"></div>

<div>If you had a super-beefy motor you could automate turn-table rotation to make a repeatable test-bed.  Otherwise you could just do it by hand.</div>

<div><br clear="none"></div>

<div>
<div>The robot should try to re-orient itself to maintain the same heading even as you rotate the table underneath it.</div>

<div><br clear="none"></div>

<div>As you observe the robot response - look to see if the heading correction overshoots and rings before it settles on the correct heading, or if it just takes 'forever' to finally creep to the right heading / if it ever even reaches the right heading.</div>

<div><br clear="none"></div>

<div>OR - on a stable surface without the turntable complication -</div>

<div>perhaps you could do an even better step-response test by adding a tiny bit of code...</div>

<div><br clear="none"></div>

<div>what about adding a software motor drive enable/disable switch, one that you could toggle wirelessly from your laptop?</div>

<div><ol><li>Give the robot a 'zero' heading set-point with the PID loop and motor drive on - </li><ul><li>let it settle on that heading.</li></ul><li>Then turn the motor drive off, </li><ul><li><b>but leave the PID loop on</b>.</li></ul><li>Then manually turn the robot something like 45 degrees and take your hands off of it.</li><ul><li>At this point, you have introduced a large step error - </li><li>and you're about to ask for the maximum possible slew rate response - a step response</li></ul><li>Then turn the motor drive back on, </li><ul><li>and watch the robot's 'return-to-zero' behavior.</li></ul><li>At first you could iterate steps 1..4 and dial-in PID values just by eyeballing the step-response.</li><ul><li>Your goal is to have the robot 'return-to-zero' as quickly as possible, without overshooting</li></ul><li>But to really dial things in, you could use a video to accurately look for overshoot and measure timing.<br clear="none"></li></ol></div>

<div><br clear="none"></div>

<div>- Carl</div>

<div><br clear="none"></div>

<div><br clear="none"></div>

<div></div>
</div>
</div>
</div>
<br clear="none">
<div class="yiv8488832392yqt2510908167" id="yiv8488832392yqt35510">
<div class="yiv8488832392gmail_quote">
<div class="yiv8488832392gmail_attr" dir="ltr">On Sat, Jan 23, 2021 at 1:28 AM Murray Altheim via DPRGlist <<a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:dprglist@lists.dprg.org" target="_blank" href="mailto:dprglist@lists.dprg.org">dprglist@lists.dprg.org</a>> wrote:<br clear="none"></div>
<blockquote class="yiv8488832392gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex;">Hi Doug,<br clear="none">
<br clear="none">
My initial question was asking what might be the algorithm for<br clear="none">
handling the rug bumps. Finding a Python library that handles this<br clear="none">
is great, but I must admit I was still a bit adrift as to how to<br clear="none">
actually incorporate it into my robot's behaviour. It'll take me a<br clear="none">
bit of time to digest what you've written, and try it out in code<br clear="none">
on my robot, but you've actually answered that question, i.e., how<br clear="none">
to work out how to take that IMU error and incorporate it into the<br clear="none">
robot's motor outputs.<br clear="none">
<br clear="none">
Thanks very much for that!<br clear="none">
<br clear="none">
One of the things I keep getting reminded of is that while there's<br clear="none">
a lot of focus on fancy sensors and such (but of course!), some of<br clear="none">
the more "basic" stuff in robotics is actually pretty tricky to get<br clear="none">
right. Precise navigation and odometry is quite difficult, which is<br clear="none">
what makes it all the more impressive to see done well.<br clear="none">
<br clear="none">
Cheers,<br clear="none">
<br clear="none">
Murray<br clear="none">
<br clear="none">
On 23/01/21 7:17 pm, <a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:secretary@dprg.org" target="_blank" href="mailto:secretary@dprg.org">secretary@dprg.org</a> wrote:<br clear="none">
> Murray,<br clear="none">
> <br clear="none">
> One approach is to take the theta value from the IMU instead<br clear="none">
> of calculating it from the encoders, and then adding the <br clear="none">
> heading error to the summing node of the negative feedback loop.<br clear="none">
> <br clear="none">
> Taking the theta value form the IMU:<br clear="none">
> <br clear="none">
> /* accumulate total rotation around our center */<br clear="none">
> /*theta += (left_inches - right_inches) / WHEEL_BASE; */<br clear="none">
> <br clear="none">
> /* replace theta value with IMU yaw value */<br clear="none">
> theta = read_IMU_yaw();  /* make sure that the units and orientation are correct */<br clear="none">
> <br clear="none">
> /* and clip the rotation to plus or minus 360 degrees */<br clear="none">
> theta -= (float)((int)(theta/TWOPI))*TWOPI;<br clear="none">
> <br clear="none">
> Now the theta value is from the IMU and should show the impact of<br clear="none">
> your rug/floor disturbance.<br clear="none">
> <br clear="none">
> The next part is to add the heading error (heading error = heading<br clear="none">
> target – theta) to the input summing node of your negative feedback<br clear="none">
> loop. The heading error is zero when you are going in the right <br clear="none">
> direction, elsewise it will have either a negative or positive <br clear="none">
> value. It will be summed in with your reference value (desired <br clear="none">
> speed in this case) and the -feedback value (PID error). If you <br clear="none">
> view it in terms of your PID error, it is like you are changing <br clear="none">
> the reference value.<br clear="none">
> <br clear="none">
> I hope this helps.<br clear="none">
...........................................................................<br clear="none">
Murray Altheim <murray18 at altheim dot com>                       = =  ===<br clear="none">
<a rel="nofollow noopener noreferrer" shape="rect" target="_blank" href="http://www.altheim.com/murray/">http://www.altheim.com/murray/</a>                                     ===  ===<br clear="none">
                                                                    = =  ===<br clear="none">
     In the evening<br clear="none">
     The rice leaves in the garden<br clear="none">
     Rustle in the autumn wind<br clear="none">
     That blows through my reed hut.<br clear="none">
            -- Minamoto no Tsunenobu<br clear="none">
<br clear="none">
_______________________________________________<br clear="none">
DPRGlist mailing list<br clear="none">
<a rel="nofollow noopener noreferrer" shape="rect" ymailto="mailto:DPRGlist@lists.dprg.org" target="_blank" href="mailto:DPRGlist@lists.dprg.org">DPRGlist@lists.dprg.org</a><br clear="none">
<a rel="nofollow noopener noreferrer" shape="rect" target="_blank" href="http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org">http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org</a><br clear="none">
</blockquote></div>
</div>

</div>
</div>

<div class="yqt2510908167" id="yqt34980">_______________________________________________<br clear="none">DPRGlist mailing list<br clear="none"><a shape="rect" ymailto="mailto:DPRGlist@lists.dprg.org" href="mailto:DPRGlist@lists.dprg.org">DPRGlist@lists.dprg.org</a><br clear="none"><a shape="rect" href="http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org" target="_blank">http://lists.dprg.org/listinfo.cgi/dprglist-dprg.org</a><br clear="none"></div>
</div>
</div>