-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
921 tachometer odometer kinematics parts #1003
Conversation
- mono and quadrature encoder implementations - both use the same serial protocol * Implements the r/p/c command protocol * for on-demand sending of encoder value * and continuous sending with provided delay.
- Used by serial encoder - Wrapper for serial port connect/read/write. Use this rather than raw pyserial api. It provides a layer that automatically catches exceptions and encodes/decodes between bytes and str. It also provides a layer of indirection so that we can mock this for testing.
is_linux, is_mac, is_windows, is_jetson
- encoders support pin schemes, so the gpio encoder can use RPi.GPIO or PiGPIO - The serial encoder using the arduino sketches which support mono-encoders and quadrature encoders - The gpio encoders have been tested on RPi - The serial encoders have been tested in RPi and jetson. - The self test __main__ in tachometers is a simple way to test a given hardware setup and pin configuration without having to run full donkeycar.
- Fixed capacity circular buffer that can be used as a queue, stack or array - Used by odometer to keep fixed-size history of tachometer readings so it can calculate a smoothed velocity.
- An Odometer takes the output of a Tachometer (revolutions) and turns those into a distance and velocity. Velocity can be optionally smoothed across a given number of readings. - This moves the calculation of distance and velocity, including smoothing, out of each separate encoder implementation. Now we have a clean separation of encoders:ticks, tachometers:revolutions, odometers:distance&velocity
- use tachometer.py and odometer.py instead.
- Unicycle kinematics for differential drive - Bicycle kinematics for car-like vehicles - These are used to estimate pose (x,y,heading) - Eventually these will be incorporated into path follow template.
- required by tachometer unit test.
- added get_ticks() to MockEncoder
666151b
to
072d4f6
Compare
- update comment in limit_angle and fix tests to reflect that angle is limited betwee pi and -pi
- This allows us to add arbitrary logging of memory values without having to edit parts.
- 'steering' should be 'angle'. this caused None values to be sent to the kinematics parts - fix unterminated/merged string that caused off-by-one values in the Bicycle kinematics.
- no functional changes
Status is that the kinematics are producing a repeatable path, but it is not accurate. so the strange results is that if you record a path and put it in path follow mode then it will looks like it is doing a great job. However, if you look at the path (I've added the ability to save path as .csv) in something like https://www.csvplot.com/ the path will not look anything like what your recorded. So the path looks totally wrong, but because it is repeatably and reliably wrong in the same way each time the PID path follow algorithm can still 'follow' the wrong path and get the correct real-world output. We've added in support for odometry/kinematics in the simulator and it seems to produce a similar issue. NOTE that all of these tests are currently with a differential encoder setup. I've checked and rechecked the math; it looks correct; same math as I have used in other projects and their paths look correct. My current thinking is that we don't have a fast enough update loop. The encoders and kinematics are running in non-threaded mode, so locked in at 20hz, which may be too slow for good pose estimation. The kinematics formulas assume that vehicles has driven in a straight line between estimates; we may be build error very quickly because we break this assumption. This theory is supported by the behavior we see; the path look correct if you just go straight, but creates weird loops when attempting to turn. The other potential issue is the lag between getting an encoder update and making a pose estimate; because these are all separate parts and we may get interrupted by threaded tasks (we have a lot of those), we may have varying latency between when we get an update an when we apply it. So I think the next thing to do is make sure the serial encoder and kinematics can run in threaded mode. We may also want to make those a single process so that we update the pose immediately after getting an encoder update. Another potential way to handle this is to change the vehicle loop so that it runs as fast as it can. By default we will still only call non-threaded parts at 20hz. However, we can add a part as non-throttled so it will get called as fast as the loop can go. Doing that we could avoid a lot of issues with trying to coordinate a bunch of separate threaded parts. This effectively what I do in the Esp32CameraRover project; it's update loop runs at full speed. Some things throttle themselves based on current time. Others greedily run as fast as they can. It can do pose estimation and line following and it is using a microcontroller (Esp32) not a full SBC. |
Superceded by PR #1089 |
Add new encoder, tachometer, odometer and kinematics parts
All of these parts have been run-tested for a few months in another branch using a highly modified path_follow.py. That branch has a lot of changes, so I've created this pull request just for the encoder/odometer/kinematics pipeline. Future pull requests will 1) add changes to path_follow to bring it up to snuff with the complete template 2) add closed-loop speed control and a velocity-based neural network model.
This is draft because I still need to test it on track.