Skip to content
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 kinematics pose estimation #1089

Merged
merged 29 commits into from
Feb 16, 2023
Merged
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
1ce5b00
Add tachometer, odometer and kinematics part
Ezward Jan 1, 2023
deeb6fc
refactor pose estimation into a single part
Ezward Jan 8, 2023
d31b163
comment out logging of pose to quiet the console
Ezward Jan 8, 2023
9710c16
add arduino encoder sketches
Ezward Jan 16, 2023
6d66d2c
remove unicode characters that prevent compilation of arduino sketch
Ezward Jan 17, 2023
ff95fdf
clean up comments a little
Ezward Jan 17, 2023
e2a9a54
Add more documentation to the quadrature_encoder.ino sketch
Ezward Jan 18, 2023
325e89b
Add interrupt mode to the mono encoder
Ezward Jan 24, 2023
a5c6a44
Remove spurious unicode beta character
Ezward Jan 24, 2023
ae4ab8f
removed digital write high in mono encoder
Ezward Jan 24, 2023
8f2f859
Fix syntax error if only using one channel in int mode
Ezward Jan 26, 2023
e6eb5cf
Added a quadrature encoder sketch with no libraries
Ezward Jan 28, 2023
162ff35
Fix bug in mono encoder sketch
Ezward Jan 28, 2023
5d05b11
Fix bug in quadrature nolib sketch
Ezward Jan 28, 2023
a4ede0a
minor change to quadrature nolib
Ezward Jan 28, 2023
896cc26
Updated quadrature_encoder.ino to not require library
Ezward Jan 31, 2023
1cf569d
fix merge error in path_follow.py
Ezward Feb 4, 2023
a90421d
Fix RPi_GPIO_Servo part so it does not need GPIO in constructor
Ezward Feb 5, 2023
92af322
added non-threaded run() to UnicyclePose and BicyclePose for testing
Ezward Feb 8, 2023
4e6c371
Improved accuracy of MockEncoder by propagating fractional ticks
Ezward Feb 8, 2023
6d4f506
Updated add_odometry() so we could add as non-threaded for testing.
Ezward Feb 8, 2023
9f2ab20
Vehicle loop prints out number of iterations and total time
Ezward Feb 8, 2023
e9cac78
Rewrite of the kinematics unit tests
Ezward Feb 8, 2023
0cda9b0
Adjust bicycle kinematics to use front wheel reference
Ezward Feb 9, 2023
a1d4f78
relax orientation test to 3% accuracy
Ezward Feb 9, 2023
024fc0f
updated based on PR feedback
Ezward Feb 9, 2023
0ae8db9
removed hard-coded logging level
Ezward Feb 12, 2023
ee22a1b
Update vehicle.py
Ezward Feb 13, 2023
78711a7
Update setup.py version="4.4.dev5"
Ezward Feb 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add interrupt mode to the mono encoder
- Interrupts mode can handle much higher tick rates, but does
  a poor job of debouncing.  It is appropriate for high resolution
  optical encoders.
  • Loading branch information
Ezward committed Feb 14, 2023
commit 325e89b2e1dc94ae523f9aa4572fda26bd1b6b18
130 changes: 105 additions & 25 deletions arduino/mono_encoder/mono_encoder.ino
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,46 @@
*
* Sends the encoder ticks and a timestamp
* as a comma delimited pair: ticks,timeMs
*
* If USE_ENCODER_INTERRUPTS is defined then ticks
* will be maintained with an interrupt service routines.
* In this case the pins must be interrupt capabled.
* On the Arduino Uno/Nano pins 2 and 3 are interrupt
* capable, so the sketch uses those two pins by default.
* If your board uses different pins then modify the sketch
* before downloading to your microcontroller board.
* The advantage of this mode is that is can a high rate
* of ticks as one would see with a high resolution encoder.
* The disadvantage is that is does a poor job of debouncing,
* so it is not appropriate for mechanical encoders.
*
* If USE_ENCODER_INTERRUPTS is NOT defined, then polling
* will be used to maintain the tick count. The code
* implements a robust debouncing technique.
* The advantage of this mode is the debounce logic;
* it can robustly cound ticks even from a noisy
* mechanical encoder like a KY-040 rotary encoder.
* The disadvantage is that this cannot handle high rates
* of ticks as would be delivered by a high resolution optical
* encoder. See the comments in the code below for how
* to determine the upper bound that this method can handle.
*
*
*/
#include <Arduino.h>
#define ENCODER_PIN (7) // input pin for first encoder
#define ENCODER_2_PIN (9) // input pin for second encoder

#define ENCODER_PIN (2) // input pin for first encoder
#define ENCODER_2_PIN (3) // input pin for second encoder
#define POLL_DELAY_MICROS (100UL) // microseconds between polls
#define USE_ENCODER_INTERRUPTS (1) // if defined then use interrupts to read ticks
// otherwise use polling.

//
// state for an encoder pin
//
struct EncoderState {
int pin; // gpio pin number
long ticks; // current tick count
volatile long ticks; // current tick count
uint16_t readings; // history of last 16 readings
uint16_t transition; // value of last 16 readings for next stable state transition
unsigned long pollAtMicros; // time of next poll
Expand All @@ -49,6 +75,28 @@ boolean continuous = false; // true to send continuously, false to only send on
unsigned long sendAtMs = 0; // next send time in continuous mode
unsigned long delayMs = 0; // time between sends in continuous mode

#ifdef USE_ENCODER_INTERRUPTS
typedef void (*gpio_isr_type)();

//
// count the interrupts
//
void encode_0() {
++encoders[0].ticks;
}

#ifdef ENCODER_2_PIN
void encode_1() {
++encoders[1].ticks;
}
#endif

gpio_isr_type _isr_routines[ENCODER_COUNT] = {
encode_0,
encode_1
};
#endif



//
Expand All @@ -74,25 +122,27 @@ unsigned long delayMs = 0; // time between sends in continuous mode
// suit your encoder and use case.
//
void pollEncoder(EncoderState &encoder) {
DocGarbanzo marked this conversation as resolved.
Show resolved Hide resolved
unsigned long nowMicros = micros();
if (nowMicros >= encoder.pollAtMicros) {
//
// shift state left and add new reading
//
encoder.readings = (encoder.readings << 1) | digitalRead(encoder.pin);

//
// if readings match target transition
// then count the ticks and
// start looking for the next target transion
//
if (encoder.readings == encoder.transition) {
encoder.ticks += 1;
encoder.transition = ~encoder.transition; // invert transition
}
#ifndef USE_ENCODER_INTERRUPTS
unsigned long nowMicros = micros();
if (nowMicros >= encoder.pollAtMicros) {
//
// shift state left and add new reading
//
encoder.readings = (encoder.readings << 1) | digitalRead(encoder.pin);

encoder.pollAtMicros = nowMicros + POLL_DELAY_MICROS;
}
//
// if readings match target transition
// then count the ticks and
// start looking for the next target transion
//
if (encoder.readings == encoder.transition) {
encoder.ticks += 1;
encoder.transition = ~encoder.transition; // invert transition
}

encoder.pollAtMicros = nowMicros + POLL_DELAY_MICROS;
}
#endif
}
void pollEncoders() {
for(int i = 0; i < ENCODER_COUNT; i += 1) {
Expand All @@ -104,9 +154,31 @@ void pollEncoders() {
// reset tick counters to zero
//
void resetEncoders() {
#ifdef USE_ENCODER_INTERRUPTS
noInterrupts();
#endif

for(int i = 0; i < ENCODER_COUNT; i += 1) {
encoders[i].ticks = 0;
}

#ifdef USE_ENCODER_INTERRUPTS
interrupts();
#endif
}

void readEncoders(long ticks[ENCODER_COUNT]) {
#ifdef USE_ENCODER_INTERRUPTS
noInterrupts();
#endif

for(int i = 0; i < ENCODER_COUNT; i += 1) {
ticks[i] = encoders[i].ticks;
}

#ifdef USE_ENCODER_INTERRUPTS
interrupts();
#endif
}


Expand All @@ -117,12 +189,15 @@ void resetEncoders() {
// "{ticks},{ticksMs}"
//
void writeTicks(unsigned long ticksMs) {
Serial.print(encoders[0].ticks);
long ticks[ENCODER_COUNT];
readEncoders(ticks);

Serial.print(ticks[0]);
Serial.print(',');
Serial.print(ticksMs);
for(int i = 1; i < ENCODER_COUNT; i += 1) {
Serial.print(";");
Serial.print(encoders[i].ticks);
Serial.print(ticks[i]);
Serial.print(',');
Serial.print(ticksMs);
}
Expand All @@ -133,7 +208,12 @@ void writeTicks(unsigned long ticksMs) {
void setup() {
// set all encoder pins to inputs
for(int i = 0; i < ENCODER_COUNT; i += 1) {
pinMode(encoders[i].pin, INPUT);
int pin = encoders[i].pin;
pinMode(pin, INPUT);
digitalWrite(pin, HIGH);
#ifdef USE_ENCODER_INTERRUPTS
attachInterrupt(digitalPinToInterrupt(pin), _isr_routines[i], CHANGE);
#endif
}
Serial.begin(115200);
}
Expand Down