Subject:
|
Re: New RIK-user hints, bumpers, many topics
|
Newsgroups:
|
lugnet.robotics
|
Date:
|
Sat, 17 Apr 1999 02:51:38 GMT
|
Original-From:
|
John Cooper <ROBOTS@JPSCstopspammers.CO.UK>
|
Reply-To:
|
robots@jpsc/avoidspam/.co.uk
|
Viewed:
|
1397 times
|
| |
| |
> > > Using the 'DEFCON' IRPD code from John and James Cooper
>
>
> Where might this code be found. It sounds interesting, and I don't
> recall finding this anywhere on my journeys through the net.
>
> Thanks.
It'll be in the archive, I don't know the message number, but the original was
http://www.lugnet.com/news/display.cgi?lugnet.robotics:3488 so you'll be able
to browse the thread.
In the next few days I'll put it on my web site, along with my current FORTH
attempt to match it. http://www.jpsc.co.uk/robots
..later
Actually I've just reviewed my latest version and it is significantly defferent
from the original (I've taken advantage of the new expressions in NQC) that I
think I'll put it up here again. Apologies to anyone if they think this message
is too long, in future I'll get my site together and publish links to that.
/*
Mark R. David markdavid@mediaone.net
RCX Radarbots and distance measurement
While I like the idea of a radarbot, most of the algorithms I've seen
for implementing it were basically "You're close when the return signal
starts to get really noisy." I wanted to know more about what was going
on, see if I could be more precise about it, and particularly try to
come up with a way of measuring how far away I was from collision.
Here's what I came up with.
I did a bunch of trials in which I measured light sensor readings for
both ambient light (no infrared flashing) and while I was broadcasting
an infrared message. I did it first at a series of stationary, fixed
distances from an object (2-24 inches), and then with a robot moving
steadily toward the object from 8 feet. I repeated measurements in a few
different ambient light conditions (all indoors), including a sunny day,
an overcast day, and a dimly lit nighttime room. I logged 40 readings
for each test in the datalog, loaded them up to the computer and into a
spreadsheet, and then played with and charted the results.
The ambient readings were VERY consistent, so the noisiness in the
signal does not seem to be a feature of the light sensor itself. It only
becomes noisy when the RCX is broadcasting infrared messages. The closer
it gets to the object, the noisier it becomes, as measured by a moving
statistical variance of the readings.
I tried many techniques for deriving a measure of distance from the
readings, including moving averages, standard deviation envelopes, first
and second derivatives and filters. I couldn't get any of these to work
in multiple ambient light environments. In bright environments, the
overall level is higher, and the infrared transmission doesn't brighten
it up much more. In dark environments, the difference the signal makes
in the overall light level is many times more pronounced.
What I finally noticed was that, as the bot moved closer to the object,
it got 3 kinds of readings: very bright readings, more-or-less ambient
readings, and in-between readings. The very bright readings got brighter
and brighter as the bot got closer. Thus, if you ignored everything
except the bright readings, you traced a pretty good parabola on the
graph as a function of distance.
My guess is that this occurs because you can't synch the light sensor
read with an on bit in the RCX message in any guaranteed way. Sometimes
you get an on bit, sometimes an off. I think I've read somewhere that
the length of a broadcast bit is 417 micro-secs. Perhaps the light
sensor read is several bits long.
*/
#define RAW_LIGHT IN_2
#define SAMPLE_COUNT 30
int AVG_AMBIENT,DiffRaw,ThisRaw,DEFCON,MinRaw,RisingMins,LastRaw,DescendingRaw;
int Temp;
task ProximityDriver
// converted from code by Mark R. David (markdavid@mediaone.net)
{
Sensor(RAW_LIGHT, IN_CFG(STYPE_LIGHT, SMODE_RAW));
IRMode(IR_HI);
Temp = 0;
repeat (SAMPLE_COUNT) {
Temp += RAW_LIGHT;
}
Temp /= SAMPLE_COUNT;
AVG_AMBIENT = Temp; // average starting ambient
light value
DEFCON = 0; // DEFCON - number of
diffs the last min is below ambient
MinRaw = AVG_AMBIENT; // The current minimum
flash read - init to ambient
RisingMins = FALSE; // Flag that the last
min was higher than the one before
LastRaw = AVG_AMBIENT; // Previous raw reading
DescendingRaw = FALSE; // Flag that raw
readings are descending
loop { // monitor forever
ThisRaw = RAW_LIGHT; // Take ambient
reading ...
Temp = (AVG_AMBIENT*4 + ThisRaw) / 5;
AVG_AMBIENT = Temp; // ... and keep a moving
avg of it
DiffRaw = (615-AVG_AMBIENT)/6; // DiffRaw = The diff -
a meaningful difference in light reading
if (DiffRaw > -6) { // Is negative and
no greater than -5
DiffRaw = -6; // DiffRaw = Min(-6, (615 -
AVG_AMBIENT) / 6)
}
SendMessage(255); // Flash
Sleep(3);
ThisRaw = RAW_LIGHT;
if (ThisRaw < MinRaw) { // New minimum!
MinRaw = ThisRaw; // Reset the effective min
RisingMins = FALSE; // Clear the rising
mins flag
DescendingRaw = TRUE; // Set the descending
flag
Temp = (MinRaw-AVG_AMBIENT) / DiffRaw;
DEFCON = Temp; // DEFCON = (MinRaw -
AVG_AMBIENT) / DiffRaw
} else {
if (ThisRaw > LastRaw) { // Ascending
if (DescendingRaw==TRUE) { // Was descending must
be a higher min
if (RisingMins==TRUE) { // It's the second
one! Reset the effective min
MinRaw = LastRaw; // Reset the effective min
Temp = (MinRaw-AVG_AMBIENT) / DiffRaw;
DEFCON = Temp; // Calculate DEFCON again
} else {
RisingMins = TRUE;
}
}
DescendingRaw = FALSE;
} else {
DescendingRaw = TRUE; // Descending
}
}
LastRaw = ThisRaw;
} //loop forever
}
/*
The basic strategy is to measure DEFCON.
The variables used are:
AVG_AMBIENT - Maintains the initial ambient light value, and a moving
average of same
DEFCON - The higher DEFCON gets, the closer we are to the object.
DiffRaw - The difference - a number that represents how much brighter
the raw reading has to be to raise DEFCON one level.
ThisRaw - the latest light sensor raw reading
MinRaw - The current effective minimum (brightest) raw reading
RisingMins - Flag that indicates that our most recent minimum was
actually higher (darker) than the currently effective minimum. We might
no longer be getting closer to the object, but we'll give it one more
chance.
LastRaw - the reading prior to ThisRaw, used to determine if things are
getting brighter or darker
DescendingRaw - a flag that readings are currently descending (getting
brighter)
Temp - temporary variable
First, it takes a few samples of the ambient light and calculates the
average in AVG_AMBIENT. Next, based on the ambient light level, it
calculates difference in DiffRaw. It initializes the rest of the
variables, and then begins to loop. Within the loop, it first measures
the ambient light again, storing it in ThisRaw. It then calculates a
pseudo-exponential 5-period moving average of the ambient level in case
we move from light into dark or something, and stores it in AVG_AMBIENT.
For the same reason, it also recaclulates difference into DiffRaw.
Next, it flashes and takes a reading into ThisRaw. MinRaw has stored in
it our most recent local minimum (brightest raw) reading. If we just got
a brighter one then we a) store it in MinRaw instead, b)clear RisingMins
to indicate that minimum readings are definitely getting brighter, c)
set DescendingRaw to indicate that sequential readings are descending d)
calculate DEFCON as the number of difference levels (DiffRaw) that we
are below (brighter than) ambient.
If the latest reading wasn't brighter than our minimum, than a number of
things could be happening. If it was brighter than the previous reading
(but not bright enough to set a new min), than let's just loop and see
what develops. If it was darker than the last reading (ascending), but
we used to be getting lighter (ascending), then we have just detected a
local minimum, and that minimum must be higher (darker) than the current
effective brightest minimum in MinRaw. Check RisingMins - if it's set
then this is the second time in a row that that's happened, and we
conclude that we are no longer moving toward the object (it moved, we
turned, whatever) and we reset MinRaw to LastRaw's value, the minimum we
just detected, and lower DEFCON. If this is only the first time,
however, we don't want to be too hasty; just set RisingMins and try
again.
With the parameters I've used, DEFCON 3 seems pretty reliably reached at
a head-on distance of 12-18 inches, DEFCON 4 at 3-6 inches. The higher
end of those ranges occurs in darker environments - I need to play with
parameters some more to eliminate this bias. Basically, difference is
calculated linearly from the ambient light level - a much more
simplistic solution than many I tried, but it seems to work most
reliably. The calculation shown ends up with a difference of -6 raw
units at an ambient reading of 651 (sunny room) or brighter, and -35
units at 825 (really dark).
As a note, the moving average calculation is credited to Welles Wilder,
a commodities market technical analysis guru from the 80's. It's great
for smoothing noisy data, doesn't exhibit large discontinuities like a
linear moving average, and is easy to calculate. Basically, for an
n-period average on period t - A(n,t) - with a current datapoint Ot:
A(n,t) =( (A(n,t-1) * (n - 1) ) + Ot ) / n
Thus, in a 5-period average, as above, the most recent value counts for
1/5 of the new average, and the old average counts for 4/5.
Have fun!
*/
--
John & James Cooper, Wallington, UK
--
Did you check the web site first?: http://www.crynwr.com/lego-robotics
|
|
Message is in Reply To:
7 Messages in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|