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

GET_MOTOR_STATUS returns fictional DPS after OFFSET_MOTOR_ENCODER command #336

Open
slowrunner opened this issue May 17, 2024 · 3 comments

Comments

@slowrunner
Copy link
Contributor

slowrunner commented May 17, 2024

I do not expect a GoPiGo3 firmware "fix" for this issue - simply documenting the existence of the issue

While the GoPiGo3 API is open-source, available for us to understand to the level of our curiosity, the code that runs inside the “red board” has always required us to use black box testing for any insight.

The Raspberry Pi uses the GoPiGo3 API to send commands across an SPI bus to the red board, and interpret any returned result data. The GET_MOTOR_STATUS_LEFT, and GET_MOTOR_STATUS_RIGHT commands via the gopigo3.get_motor_status() API return:

Returns a list:
            flags -- 8-bits of bit-flags that indicate motor status:
                bit 0 -- LOW_VOLTAGE_FLOAT - The motors are automatically disabled because the battery voltage is too low
                bit 1 -- OVERLOADED - The motors aren't close to the target (applies to position control and dps speed control).
            power -- the raw PWM power in percent (-100 to 100)
            encoder -- The encoder position
            dps -- The current speed in Degrees Per Second

So imagine my surprise when using the gopigo3.reset_motor_encoder() API (which sends an OFFSET_MOTOR_ENCODER SPI command) to see get_motor_status() return non-zero robot speeds, and in fact speeds far exceeding possible GoPiGo3 robot motion.

This is the result when resetting the encoders without moving the robot:

*** started moving
[INFO] [1715963280.121958244] [odometer]: start heading -0.0329 rads
[INFO] [1715963280.122452707] [odometer]: last heading -0.0329 rads
[INFO] [1715963280.123078985] [odometer]: current heading -0.0329 rads
[INFO] [1715963280.123697318] [odometer]: last_point - x: -0.1734 y: 0.0196 z: 0.0000 heading: -1.9
[INFO] [1715963280.124226837] [odometer]: current_point - x: -0.1734 y: 0.0196 z: 0.0000 heading: -1.9
[INFO] [1715963280.124845392] [odometer]: lSpeed,rSpeed: (2823.000,2880.000  lEncoder,rEncoder: (0.0,0.0)  lPwr,rPwr: (-128,-128)   

<<<---- ROBOT IS NOT MOVING BUT REPORTS 2880 DPS or 1.6m/s EQUIVALENT VELOCITY --->>>

[INFO] [1715963280.125430411] [odometer]: start_point - x: -0.173 y:  0.020 z:  0.000 heading:   -2
[INFO] [1715963280.218462322] [odometer]: 
*** stopped moving
[INFO] [1715963280.218914730] [odometer]: start heading -0.0329 rads
[INFO] [1715963280.219304433] [odometer]: last heading 0.0000 rads
[INFO] [1715963280.219889507] [odometer]: current heading 0.0000 rads
[INFO] [1715963280.220388767] [odometer]: start_point - x: -0.1734 y: 0.0196 z: 0.0000 heading: -1.9
[INFO] [1715963280.220965137] [odometer]: lSpeed,rSpeed: (0.000,0.000  lEncoder,rEncoder: (0.0,0.0)  lPwr,rPwr: (-128,-128)
[INFO] [1715963280.221521544] [odometer]: stop_point -  x:  0.000 y:  0.000 z:  0.000 heading:    0 - moved:  0.175 meters in 0.1s

Dave has a maximum measured velocity of 450 DPI which is 0.25 meters per second. There is absolutely no way any GoPiGo3 robot could move at 1.6 m/s. I have seen reported speeds over 5000 DPI returned when resetting the encoders.

The difficulty for Dave comes in trying to correctly identify when Dave is moving. I thought I could use motor_status.dps but the GoPiGo3 redboard is reporting fictional motion when resetting the encoders - bummer.

Manufacturer    :  Dexter Industries
Board           :  GoPiGo3
Serial Number   :  56ECD67E5152415447202020FF192614
Hardware version:  3.x.x
Firmware version:  1.0.0
Battery voltage :  9.868
5v voltage      :  4.979
@jharris1993
Copy link
Contributor

jharris1993 commented May 17, 2024 via email

@slowrunner
Copy link
Contributor Author

Fastest GoPiGo3 on Record (9.3m/s)

Confirmed also happens on a 7 year old GoPiGo3 (Carl) - reports traveling at 20 miles per hour briefly!
(Wheels actually flinched a little)

pi@Carl:~/Carl $ python3 ~/Dexter/GoPiGo3/Software/Python/Examples/Read_Info.py 
Manufacturer    :  Dexter Industries
Board           :  GoPiGo3
Serial Number   :  BA93EB4F514E3437324A2020FF040B1F
Hardware version:  3.x.x
Firmware version:  1.0.0
Battery voltage :  10.871
5v voltage      :  5.067

To Reproduce:

  1. drive GoPiGo a little to ensure non-zero encoders
  2. start read_motor_status.py in background
  • Prints initial motor_status
  • Loops at 100 Hz checking for non-zero read_motor_status().dps
    • prints motor status until DPS zero again
  1. run reset_encoders.py in foreground
pi@Carl:~/Carl/systests/fictionaldps $ ./read_motor_status.py &
[1] 26443
pi@Carl:~/Carl/systests/fictionaldps $ 
2024-05-17 22:47:34.018234: lSpeed,rSpeed: (0.000,0.000  lEncoder,rEncoder: (45349,-47045)  lPwr,rPwr: (-28,-28)

pi@Carl:~/Carl/systests/fictionaldps $ ./reset_encoders.py 
2024-05-17 22:47:44.488092: resetting encoders

2024-05-17 22:47:44.502749: lSpeed,rSpeed: (-16100.000,-134.000  lEncoder,rEncoder: (0,0)  lPwr,rPwr: (70,70)

2024-05-17 22:47:44.514082: lSpeed,rSpeed: (-16095.000,-130.000  lEncoder,rEncoder: (0,0)  lPwr,rPwr: (-7,-7)

2024-05-17 22:47:44.525271: lSpeed,rSpeed: (-16095.000,-125.000  lEncoder,rEncoder: (0,1)  lPwr,rPwr: (-2,-9)
pi@Carl:~/Carl/systests/fictionaldps $ 
2024-05-17 22:47:44.536336: lSpeed,rSpeed: (-16090.000,-120.000  lEncoder,rEncoder: (1,1)  lPwr,rPwr: (-4,-6)

2024-05-17 22:47:44.547352: lSpeed,rSpeed: (-16090.000,-120.000  lEncoder,rEncoder: (1,1)  lPwr,rPwr: (-4,-6)

2024-05-17 22:47:44.558347: lSpeed,rSpeed: (-16090.000,-125.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,1)

2024-05-17 22:47:44.569368: lSpeed,rSpeed: (-16090.000,-125.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

2024-05-17 22:47:44.580344: lSpeed,rSpeed: (-16090.000,-120.000  lEncoder,rEncoder: (1,1)  lPwr,rPwr: (-4,-11)

2024-05-17 22:47:44.591312: lSpeed,rSpeed: (-16090.000,-125.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,1)

2024-05-17 22:47:44.602348: lSpeed,rSpeed: (9.000,9.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

2024-05-17 22:47:44.613317: lSpeed,rSpeed: (4.000,4.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

2024-05-17 22:47:44.624303: lSpeed,rSpeed: (4.000,0.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

2024-05-17 22:47:44.635285: lSpeed,rSpeed: (0.000,-4.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

2024-05-17 22:47:44.646332: lSpeed,rSpeed: (0.000,-4.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

2024-05-17 22:47:44.657309: lSpeed,rSpeed: (0.000,-4.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

2024-05-17 22:47:44.668298: lSpeed,rSpeed: (0.000,0.000  lEncoder,rEncoder: (1,0)  lPwr,rPwr: (-4,-4)

read_motor_status.py:

#!/usr/bin/env python3

import gopigo3
import datetime as dt
import time

DT_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
def main():
    try:
        gpg = gopigo3.GoPiGo3()
        lF,lP,lE,lDPS = gpg.get_motor_status(gpg.MOTOR_LEFT)
        rF,rP,rE,rDPS = gpg.get_motor_status(gpg.MOTOR_RIGHT)
        tnow = dt.datetime.now().strftime(DT_FORMAT)
        print_msg="\n{}: lSpeed,rSpeed: ({:.3f},{:.3f}  lEncoder,rEncoder: ({},{})  lPwr,rPwr: ({},{})".format(tnow,lDPS,rDPS,lE,rE
,lP,rP)
        print(print_msg)

        while True:
            lF,lP,lE,lDPS = gpg.get_motor_status(gpg.MOTOR_LEFT)
            rF,rP,rE,rDPS = gpg.get_motor_status(gpg.MOTOR_RIGHT)
            tnow = dt.datetime.now().strftime(DT_FORMAT)
            if (abs(rDPS) > 0 or abs(lDPS) > 0):
                print_msg="\n{}: lSpeed,rSpeed: ({:.3f},{:.3f}  lEncoder,rEncoder: ({},{})  lPwr,rPwr: ({},{})".format(tnow,lDPS,rD
PS,lE,rE,lP,rP)
                print(print_msg)
                time.sleep(0.01)
                lF,lP,lE,lDPS = gpg.get_motor_status(gpg.MOTOR_LEFT)
                rF,rP,rE,rDPS = gpg.get_motor_status(gpg.MOTOR_RIGHT)
                tnow = dt.datetime.now().strftime(DT_FORMAT)
                print_msg="\n{}: lSpeed,rSpeed: ({:.3f},{:.3f}  lEncoder,rEncoder: ({},{})  lPwr,rPwr: ({},{})".format(tnow,lDPS,rD
PS,lE,rE,lP,rP)
                print(print_msg)
            time.sleep(0.01)
    except KeyboardInterrupt:
        pass


if __name__ == '__main__':
    main()

reset_encoders.py:

#!/usr/bin/env python3

import gopigo3
import datetime as dt
import time

DT_FORMAT = "%Y-%m-%d %H:%M:%S.%f"
def main():
    try:
        gpg = gopigo3.GoPiGo3()
        tnow = dt.datetime.now().strftime(DT_FORMAT)
        print("{}: resetting encoders".format(tnow))
        gpg.reset_motor_encoder(gpg.MOTOR_LEFT + gpg.MOTOR_RIGHT)
    except KeyboardInterrupt:
        pass


if __name__ == '__main__':
    main()

@slowrunner
Copy link
Contributor Author

Interestingly, using the EasyGoPiGo3.reset_encoders() method fictional speeds are reported but the power is set and maintained at 0, so using this method instead of reset_motor_encoder() does not cause the GoPiGo3 to flinch, (and allows my "is_moving" test to ignore the non-zero speeds if the power is 0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants