<div style="color:black;font: 10pt Arial, Helvetica, sans-serif;">
<div>Murray,</div>
<div><br>
</div>
<div>Good diagnostic tests.</div>
<div><br>
</div>
<div>I am clueless about Python, but, Yes, your timestamps show something you didn't intend. I've read the rationale of Python and some of the code documentation, but I still can't read and understand a single line of it.</div>
<div><br>
</div>
<div>When I read that Python is still an interpreted language with very slow execution rates and non-deterministic rates, I quit learning about it. It's OK for things where time doesn't matter, like web pages or bulk transfers, but not for real-time things. Maybe I'm overlooking a real-time Python.</div>
<div><br>
</div>
<div>So, I wonder if the lack of 50ms repeatable intervals is due to the way Python works, and not your fault.</div>
<div><br>
</div>
<div>When I see stuff like this in my code, I try to force the interval by using a timer that I trust, or a loop that tunes itself, kinda like a PLL. PITA.</div>
<div><br>
</div>
<div><br>
</div>
<div>Sorry to beat a dead horse, but wiggling the output gears might not tell you anything. The ratios may be so high, and there may be gear types in the gearbox that cannot transmit power backwards to the motor. The output shafts could be tight, and there could still be lots of gear slop on the input shaft. If you can spin the motors by manually spinning the wheels, then disregard this.</div>
<div><br>
</div>
<div>Good luck.</div>
<div><br>
</div>
<div>John Swindle</div>
<div><br>
</div>
<br>
<br>
<div style="font-family:arial,helvetica;font-size:10pt;color:black">-----Original Message-----<br>
From: Murray Altheim via DPRGlist <dprglist@lists.dprg.org><br>
To: dprglist@lists.dprg.org<br>
Sent: Tue, Jan 26, 2021 4:32 pm<br>
Subject: Re: [Dprglist] KD01 Rotate in Place video<br>
<br>
<div dir="ltr">Hi John,<br clear="none"><br clear="none">It looks like the surge is entirely software and not related at all to<br clear="none">hardware, motors, gears or caster. It happens on the test bench with<br clear="none">the robot not actually moving, and just to check if the gearboxes are<br clear="none">under any tension I wiggled the wheels when they come to rest to jiggle<br clear="none">the gearboxes -- this has no effect, the surge still occurs.<br clear="none"><br clear="none">It looks like the surge is due to either the PID controllers maintaining<br clear="none">state or the PID loop somehow not getting called on time. I'll describe<br clear="none">this in more detail below.<br clear="none"><br clear="none">Just to clarify what the manual velocity test actually does, it performs<br clear="none">this sequence:<br clear="none"><br clear="none"> a. accelerate from zero to target velocity, same direction on both<br clear="none"> motors (i.e., rotate in place). First cycle counter-clockwise.<br clear="none"> b. cruise for 5 seconds<br clear="none"> c. decelerate to zero<br clear="none"> d. wait 5 seconds<br clear="none"> e. spit out PID state data (then reset)<br clear="none"> f. accelerate from zero to target velocity, same direction on both<br clear="none"> motors (i.e., rotate in place). Second cycle is clockwise.<br clear="none"> g. cruise for f seconds<br clear="none"> h. decelerate to zero<br clear="none"><br clear="none">The Python code can be found at:<br clear="none"><br clear="none"> <a shape="rect" href="https://github.com/ifurusato/ros/blob/master/manual_velocity_test.py" target="_blank">https://github.com/ifurusato/ros/blob/master/manual_velocity_test.py</a><br clear="none"><br clear="none">Upon returning from rotating counter-clockwise to clockwise (or vice-versa) that<br clear="none">first acceleration at (f) from 0 to 1 to 2 to 3 (eventually to 50) the PID<br clear="none">controllers aren't actually starting a stateless transition. I.e., to be clear<br clear="none">if we only do one of the two acceleration-cruise-deceleration cycles (either a-c<br clear="none">or f-h) the surge doesn't occur. So I started resetting the PIDs by clearing out<br clear="none">any state variables at (e), but sadly this didn't cure the woes.<br clear="none"><br clear="none">Looking at the console output when starting up at (f) we see:<br clear="none"><br clear="none">2021-01-27T11:24:26.135.905504Z : pid:port : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.148.790836Z : pid:stbd : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.186.000347Z : pid:port : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.198.897362Z : pid:stbd : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.225.871086Z : main : INFO : accelerating to set point: 50.00...<br clear="none">2021-01-27T11:24:26.226.798534Z : pid:port : INFO : reset ===============<br clear="none">2021-01-27T11:24:26.227.556705Z : pid:stbd : INFO : reset ===============<br clear="none">2021-01-27T11:24:26.228.170633Z : main : INFO : set point: 0.00 ; velocity: 0.00 / 0.00;<br clear="none">2021-01-27T11:24:26.236.160994Z : pid:port : INFO : __call__ dt: 0.0087<br clear="none">2021-01-27T11:24:26.236.850977Z : pid:port : INFO : __call__() last output: 0.00<br clear="none">2021-01-27T11:24:26.249.022245Z : pid:stbd : INFO : __call__ dt: 0.0209<br clear="none">2021-01-27T11:24:26.249.667406Z : pid:stbd : INFO : __call__() last output: 0.00<br clear="none">2021-01-27T11:24:26.286.290646Z : pid:port : INFO : __call__ dt: 0.0588<br clear="none">2021-01-27T11:24:26.299.113750Z : pid:stbd : INFO : __call__ dt: 0.0710<br clear="none">2021-01-27T11:24:26.329.402447Z : main : INFO : set point: 1.00 ; velocity: 1.00 / -1.00;<br clear="none">2021-01-27T11:24:26.336.445808Z : pid:port : INFO : __call__ dt: 0.0502<br clear="none">2021-01-27T11:24:26.349.218369Z : pid:stbd : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.386.672974Z : pid:port : INFO : __call__ dt: 0.0502<br clear="none">2021-01-27T11:24:26.399.346352Z : pid:stbd : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.431.238651Z : main : INFO : set point: 2.00 ; velocity: 2.00 / -2.00;<br clear="none">2021-01-27T11:24:26.436.789513Z : pid:port : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.449.603558Z : pid:stbd : INFO : __call__ dt: 0.0503<br clear="none">2021-01-27T11:24:26.486.915588Z : pid:port : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.499.716043Z : pid:stbd : INFO : __call__ dt: 0.0501<br clear="none">2021-01-27T11:24:26.533.149719Z : main : INFO : set point: 3.00 ; velocity: 3.00 / -3.00;<br clear="none"><br clear="none">it's clear that the normal 'dt' delay of 0.501 (50ms, 20Hz) PID calls are for<br clear="none">some reason suddenly coming in at 0.0087 (about 9ms), then 0.0209, 0.0588,<br clear="none">0.0710, until coming back to their 50ms normal. I tried going clockwise first,<br clear="none">then counter-clockwise; it does the same thing. The test is entirely repeatable:<br clear="none">it will happen like this every time, and that timing error is always there.<br clear="none"><br clear="none">I'm at this point attributing the surge to this timing error (i.e., the calls not<br clear="none">occurring at 50ms intervals), and continue to investigate why this is occurring.<br clear="none">It's not due to threading or anything like that; it's clearly my code's fault.<br clear="none"><br clear="none">Cheers,<br clear="none"><br clear="none">Murray<br clear="none"><br clear="none">On 26/01/21 9:12 pm, John Swindle via DPRGlist wrote:<br clear="none">> The slight surge is likely due to windup. The gears were at limit when the first rotation stopped, so the second rotation would have a delay and then a jerk.<br clear="none">> <br clear="none">> Also, the caster has to rotate, and that creates an effect that the control system might not know about.<br clear="none">> <br clear="none">> Suggest a windup preamble in all motor commands.<br clear="none">> <br clear="none">> I am not a mech eng, but I joined DPRG to learn relevant mechanical things, and I've learned more than I expected.<br clear="none">> <br clear="none">> Later,<br clear="none">> John Swindle<br clear="none">> <br clear="none">> <br clear="none">> -----Original Message-----<br clear="none">> From: Murray Altheim via DPRGlist <<a shape="rect" ymailto="mailto:dprglist@lists.dprg.org" href="mailto:dprglist@lists.dprg.org">dprglist@lists.dprg.org</a>><br clear="none">> To: <a shape="rect" ymailto="mailto:dprglist@lists.dprg.org" href="mailto:dprglist@lists.dprg.org">dprglist@lists.dprg.org</a><br clear="none">> Sent: Mon, Jan 25, 2021 1:52 am<br clear="none">> Subject: Re: [Dprglist] KD01 Rotate in Place video<br clear="none">> <br clear="none">> I've just updated the KD01 Rotate-in-Place Test video on YouTube, which now<br clear="none">> performs a bit better than the previous version: the KD01 accelerates properly<br clear="none">> up to speed counter-clockwise, maintains that for 10 seconds, then decelerates<br clear="none">> to a stop, then does the same thing clockwise:<br clear="none">> <br clear="none">> KD01 Rotate in Place Test<br clear="none">> <a shape="rect" href="https://youtu.be/HICrQzAZPow" target="_blank">https://youtu.be/HICrQzAZPow</a><br clear="none">> <br clear="none">> The position of the robot at the end of the test is about 4cm from its initial<br clear="none">> position, which isn't too bad all things considered. There is a noticeable<br clear="none">> surge when the robot starts again clockwise after a pause. I'm not sure what<br clear="none">> this is caused by -- nothing in the code is indicative -- but I'm overall<br clear="none">> happy with the result. I think it helped that I ran the test this time on<br clear="none">> some smooth particle board.<br clear="none">> <br clear="none">> The NZPRG Python robot code can be found at:<br clear="none">> <br clear="none">> <a shape="rect" href="https://github.com/ifurusato/ros" target="_blank">https://github.com/ifurusato/ros</a><br clear="none">> <br clear="none">> with the rotate-in-place test file at:<br clear="none">> <br clear="none">> <a shape="rect" href="https://github.com/ifurusato/ros/blob/master/rotate_in_place.py" target="_blank">https://github.com/ifurusato/ros/blob/master/rotate_in_place.py</a><br clear="none">> <br clear="none">> The KD01 is a differential drive robot that uses a Raspberry Pi with a<br clear="none">> PiBorg ThunderBorg motor controller, an OSEPP drive train and hall effect<br clear="none">> motor encoders, a tiny Adafruit Mini PiTFT 135x240 Color display that I<br clear="none">> use as a console window, which includes two small buttons I've wired up<br clear="none">> to initiate/control the test. The rear caster is an OSEPP wheel installed<br clear="none">> into the frame of a commercially-available caster.<br clear="none">> <br clear="none">> Cheers,<br clear="none">> <br clear="none">> Murray<br clear="none">> <br clear="none">> On 23/01/21 4:04 pm, Murray Altheim via DPRGlist wrote:<br clear="none">> > Sometimes it's important to prove one is making progress. Not that this is<br clear="none">> > advancing the science at all but I've just posted a video showing the KD01<br clear="none">> > differential drive robot rotating in place using its PID controllers: [...]<br clear="none">> ...........................................................................<br clear="none">> Murray Altheim <murray18 at altheim dot com> = = ===<br clear="none">> <a shape="rect" href="http://www.altheim.com/murray/" target="_blank">http://www.altheim.com/murray/ </a><<a shape="rect" href="http://www.altheim.com/murray/" target="_blank">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 shape="rect" ymailto="mailto:DPRGlist@lists.dprg.org" href="mailto:DPRGlist@lists.dprg.org">DPRGlist@lists.dprg.org</a> <mailto:<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">> <br clear="none">> _______________________________________________<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>
<div class="yqt8045468441" id="yqtfd09871"><br clear="none">> <br clear="none"><br clear="none">-- <br clear="none"><br clear="none">...........................................................................<br clear="none">Murray Altheim <murray18 at altheim dot com> = = ===<br clear="none"><a shape="rect" href="http://www.altheim.com/murray/" target="_blank">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 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>
</div>