ev3dev / ev3dev-lang-python

Pure python bindings for ev3dev
MIT License
428 stars 145 forks source link

GyroSensor.reset() failing on EV3 #676

Closed kutting closed 4 years ago

kutting commented 4 years ago

The GyroSensor reset method is throwing an exception for me. I'm using an EV3 with a 01N7 gyro on port 2 (I've tried other ports as well). I run the following code:

#!/usr/bin/env micropython

from sys import stderr
from ev3dev2.sensor.lego import GyroSensor
from ev3dev2._platform.ev3 import INPUT_2

gyro = GyroSensor()

print("gyro mode: {0}, angle {1}".format(gyro.mode, gyro.angle), file=stderr)
gyro.reset()
print("gyro mode: {0}, angle {1}".format(gyro.mode, gyro.angle), file=stderr)

while gyro.angle != 0:
    print("gyro mode: {0}, angle {1}".format(gyro.mode, gyro.angle), file=stderr)

And I get something like this as a result:

gyro mode: GYRO-ANG, angle 42
gyro mode: GYRO-ANG, angle 42
gyro mode: GYRO-ANG, angle 42
    ...<98 identical lines snipped>...
gyro mode: GYRO-ANG, angle 42
gyro mode: GYRO-ANG, angle 42
Traceback (most recent call last):
  File "/home/robot/Samples/gyro_reset_test.py", line 14, in <module>
  File "ev3dev2/sensor/lego.py", line 596, in angle
  File "ev3dev2/sensor/__init__.py", line 280, in _ensure_mode
  File "ev3dev2/sensor/__init__.py", line 182, in mode
  File "ev3dev2/__init__.py", line 322, in set_attr_string
  File "ev3dev2/__init__.py", line 264, in _set_attribute
  File "ev3dev2/__init__.py", line 264, in _set_attribute
  File "ev3dev2/__init__.py", line 282, in _raise_friendly_access_error
  File "ev3dev2/__init__.py", line 36, in chain_exception
ValueError: One or more arguments were out of range or invalid, value b'GYRO-ANG'
----------
Exited with error code 1.

When I run the code again, it returns quickly and successfully because the gyro, in fact, has now been reset to 0. So I lift up the robot and turn it a little, and get the same broken result above.

WasabiFan commented 4 years ago

@dlech do you have any insight here?

bpmerkel commented 4 years ago

@kutting Ken, does introducing a sleep for maybe 100ms help with the Gyro's inherent lag? There are several posts on forums.usfirst.org about the Gyro's challenges, and I think the conclusion is "avoid Gyro resets at all costs" but cannot recall why. An alternate pattern would be to measure the Gyro angle at the start and capture into a variable, then subtract within code, rather than relying on a reset().

Namely, review the documents posted to this thread, about 80% down the scroll: https://forums.usfirst.org/forum/general-discussions/first-programs/first-lego-league/the-challenge/products-equipment/ev3-specific/82010-the-ev3-input-port-timing-bug-related-to-gyro-drift

dlech commented 4 years ago

https://github.com/ev3dev/ev3dev/issues/1269

I haven't had time to dig into it.

kutting commented 4 years ago

@kutting Ken, does introducing a sleep for maybe 100ms help with the Gyro's inherent lag? There are several posts on forums.usfirst.org about the Gyro's challenges, and I think the conclusion is "avoid Gyro resets at all costs" but cannot recall why. An alternate pattern would be to measure the Gyro angle at the start and capture into a variable, then subtract within code, rather than relying on a reset().

Namely, review the documents posted to this thread, about 80% down the scroll: https://forums.usfirst.org/forum/general-discussions/first-programs/first-lego-league/the-challenge/products-equipment/ev3-specific/82010-the-ev3-input-port-timing-bug-related-to-gyro-drift

@bpmerkel Brady, The original code where I encountered this issue incorporated calls to sleep, and I did mess around with various delays. But I felt that for this bug report I should simplify the code as much as possible.

You're right that there are ways to work around this issue. As you suggest, one way would be to have a wrapper class that just adjusts results based on the initial reading of the gyro. Another possibility is to read the angle_and_rate, instead of just the angle. I tried this and it seemed to have its own flaws (it didn't seem to read the correct angle), but I thought I would just start with this Issue and go from there.

I'll also note that I tried this code without doing the reset; just sitting in the loop, reading the angle. The code didn't crash in that case, so it seems to be related to doing the reset.

kutting commented 4 years ago

I changed my original code to catch the error, and added a Stopwatch to come up with timing info. And it appears that what happens is that a gyro reset puts the gyro into an unstable mode. For my robot and sensor, there is about a three second period where the mode goes through several different values, and where the angle either reports the original value or throws an error. Once the gyro reports an angle of zero, the gyro is stable and operates as expected.

I don't know what the best solution is here; maybe change the angle accessor to catch the error and report None? But I would think at a minimum, the docs should be changed to indicate that the gyro will be unavailable / unstable for awhile after calling reset.

dlech commented 4 years ago

Fixed in https://github.com/ev3dev/ev3dev-lang-python/pull/692

WasabiFan commented 4 years ago

Fix released in v2.0.0.