ev3dev / ev3dev-lang-python

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

Infrared sensor 'proximity' property #518

Closed ndward closed 5 years ago

ndward commented 6 years ago

ev3dev version: 4.14.61-ev3dev-2.2.2-ev3 ev3dev-lang-python version: ii python3-ev3dev 1.2.0 all Python language bindings for ev3dev ii python3-ev3dev2 2.0.0~beta1 all Python language bindings for ev3dev

In EV3-G the IR sensor has two distinct proximity modes, one for objects and one for the beacon. This image shows to two modes (we notice that in each mode the proximity icon is present). proximity_modes See also http://www.legoengineering.com/ev3-sensors/

In EV3 Python v2 the IR sensor has one proximity property for which this is the description: A measurement of the distance between the sensor and the remote, as a percentage. 100% is approximately 70cm/27in.

That would suggest that in EV3 Python v2 the proximity property cannot be used for object proximity, but when I try to use it in this way it seems to work (but with some spurious excessive values).

I placed the IR sensor 38cm from a white wall in a darkish room with no IR remote controls in use. I ran the following EV3-G program:

ir_proximity _ev3g

And got results always 40 or 41 – very consistent and remarkably close to the distance in cm.

Then I put a black surface against the wall and again got very consistent results between 88 and 90, confirming that the proximity value is calculated based on the intensity of the reflected IR radiation (much weaker in this case).

Then I put the sensor into beacon mode and fed the proximity to the display block which displayed no readings, confirming that the object proximity and beacon proximity modes are genuinely different.

Then I ran the following EV3 Python v2 script with the white wall at 38cm distance. (The script uses file=sys.stderr to print to the output panel of VS Code).

#!/usr/bin/env python3
from ev3dev2.sensor.lego import InfraredSensor
import sys
from time import sleep

ir = InfraredSensor()

for i in range(20):
    print(str(ir.proximity), end=' ', file=sys.stderr)
    sleep(1)
print('', file=sys.stderr)

And got the following results: 43 40 40 40 47 70 40 40 40 40 46 40 40 40 40 40 47 40 40 40 We note the presence of some spurious results such as (43, 46, 47, 47, 70) although the other results are all 40, very consistent with the EV3-G results. But these spurious results (always too high, never too low) are sometimes way off and have rendered some of my scripts useless.

With a sleep of 0.01s instead of 1s I got 50 69 62 48 47 48 47 47 42 42 41 41 49 47 47 47 40 47 48 49 so this short interval causes nearly all the results (except 5 in the range 40-42) to be much too high. What is the minimum delay that should be used be taking consecutive readings? Clearly 0.01s is much too little. Shouldn't there be something in the documentation about the need to leave time between successive readings?

With a sleep of 0.1s: 92 42 40 41 41 40 49 41 41 40 40 40 40 49 41 41 41 42 40 41 Nearly all of the readings (17 of 20) are in the range 40-42 but the first reading is 92. Using the old value() function in this script

#!/usr/bin/env python3
import sys
from time import sleep
from ev3dev.ev3 import *

ir = InfraredSensor() 

ir.mode = 'IR-PROX'

for i in range(20):
    print(str(ir.value()), end=' ', file=sys.stderr)
    sleep(1)

print('', file=sys.stderr)

with a sleep of 1s I get 41 40 40 40 40 40 40 40 40 40 40 40 40 40 40 41 41 40 40 40 which is extremely consistent, showing the problem with proximity did not exist with the old PROX values. And with a sleep of 0.01s: 52 52 52 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 which are consistent accurate values except for the first three. So the new proximity property has a problem with rapid readings being taken but the old value() function had much less of a problem.

I haven't tried using the sensor to detect beacon proximity but I wonder how the channel would be specified for this in EV3 Python (it seems to be specified in EV3-G as shown in the block above, presumably so that the sensor can detect the proximity of different beacons that might be visible simultaneously).

I think that:

WasabiFan commented 6 years ago

@dlech could you help us understand the situation regarding IR proximity? Only one "proximity" mode appears to be available... So what is the other EV3-G block doing? Perhaps is IR-SEEK the only one which tracks the remote and IR-PROX the object distance estimate?

ndward commented 6 years ago

I note that in the IR sensor documentation there is, in addition to proximity, also a distance() function: distance(channel=1) Returns distance (0, 100) to the beacon on the given channel. Returns None when beacon is not found.

I'm guessing that this distance() function corresponds to beacon proximity in EV3-G and that Python's proximity property is for object proximity, not beacon proximity as stated in the documentation.

distance() has a channel parameter (like for beacon proximity in EV3-G) whereas Python's proximity property does not.

By the way, I've tested the distance() function and I think it has major problems which I will address in a separate issue. The heading(), heading and_distance() and beacon() functions all aslo have major problems according to my tests.

dlech commented 6 years ago

I believe @ndward's guesses are correct.

this is wrong (in spite of being mostly right):

proximity

A measurement of the distance between the sensor and the remote, as a percentage. 100% is approximately 70cm/27in.

The distance measurement has nothing to do with the remote. The proximity property is the same as this block:

selection_015

The distance, heading and heading_and_distance methods all correspond to this block:

selection_016

The top_left, bottom_left, top_right, bottom_right and beacon methods all correspond to this block:

image

And the buttons_pressed method corresponds to a "secret" mode not available in the official LEGO software.

ndward commented 6 years ago

I'm glad that an error in the documentation has been identified but I'd just like to give a reminder that I have suggested that there may be two other problems:

These observations are valid only for the new proximity property. The old value() function did not have these problems.

ndward commented 6 years ago

There was confusion about whether the proximity property represents object proximity or beacon proximity. It turns out it's the former, and the distance property corresponds to the latter. It seems to me that ongoing confusion could be avoided if the properties were to be renamed object_proximity and beacon_proximity. This would also bring the names in line with EV3-G which refers to beacon proximity rather than distance.

WasabiFan commented 6 years ago

I'd just like to give a reminder that I have suggested that there may be two other problems:

As with other similar issues (e.g. #520), this should be resolved once we release the next version of the library. I will do so once we finish the fixes for motor issues which you reported.

It seems to me that ongoing confusion could be avoided if the properties were to be renamed object_proximity and beacon_proximity. This would also bring the names in line with EV3-G which refers to beacon proximity rather than distance.

What are the names that EV3-G uses for "object" distance? I'd be fine with changing the names to be the same as EV3-G.

ndward commented 6 years ago

In EV3-G the IR sensor block has a measure>proximity mode with a 'proximity' parameter that gives the proximity of objects, and a measure>beacon mode with a 'proximity' parameter that gives the proximity of the beacon. I think object_proximity and beacon_proximity are the best names for the corresponding EV3 python properties, though that implies that heading_and_distance will have to be renamed as heading_and_beacon_proximity which is uncomfortably long.