To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.roboticsOpen lugnet.robotics in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / 3488
3487  |  3489
Subject: 
LONG!!! - RCX Radarbots and distance measurement
Newsgroups: 
lugnet.robotics
Date: 
Fri, 5 Feb 1999 20:20:05 GMT
Viewed: 
1081 times
  
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.

Here's the code I ended up implementing.  I don't know NQC, so it's in
sort-of-Spirit instead.  I've used constants for the arguments where it
helps readability, and when there are a pair of "Source,Number"
arguments, I've used something like "VAR3" to represent variable 3 and
an unadorned number to represent a constant.

BeginOfTask(0)
SetSensorType(2,LIGHT)
SetSensorMode(2,RAW,0)

SetVar(1,0)
Loop(30)
   SetVar(3,IVA2)
   SumVar(1,VAR3)
EndLoop
DivVar(1,30)                        VAR 1 =  average ambient light value

SetVar(2,615)
Sub(2,VAR1)
DivVar(2,6)                          VAR2 = The diff - a meaningful
difference in light reading
If(VAR2,>,-6)                            Is negative and no greater than
-5
   SetVar(2,-6)
EndIf


SetVar(4,0)                              DEFCON - number of diffs the
last min is below ambient
SetVar(5,VAR1)                       The current minimum flash read -
init to ambient
SetVar(6,0)                              Flag that the last min was
higher than the one before
SetVar(7,VAR1)                       Previous raw reading
SetVar(8,0)                              Flag that raw readings are
descending

SetFwd(c)
SetRwd(a)
SetPower(ac,7)
On(ac)                                    Let's go!

While(VAR4,<,3)                     We quit when we get to DEFCON 3 or
higher
   SetVar(3,IVA2)                      Take ambient reading ...
   MulVar(1,4)
   SumVar(1,VAR3)
   DivVar(1,5)                       ... and keep a moving avg of it in
VAR 1

   SetVar(2,615)
   SubVar(2,VAR1)
   DivVar(2,6)                          VAR2 = The diff - a meaningful
difference in light reading
   If(VAR2,>,-6)                            Is negative and no greater
than -5
      SetVar(2,-6)
   EndIf

   SendPBMessage(255)             Flash
   Wait(3)
   SetVar(3,IVA2)
   If(VAR3,<,VAR5)                   New minimum!
      SetVar(5,VAR3)                  Reset the effective min
      SetVar(6,0)                         Clear the rising mins flag
      SetVar(8,1)                         Set the descending flag
      SetVar(4,VAR5)
      SubVar(4,VAR1)
      DivVar(4,VAR2)             Calculate DEFCON
   Else
      If(VAR3,>,VAR7)                 Ascending
         If(VAR8,=,1)                    Was descending must be a higher
min
            If(VAR6,=,1)                  It's the second one! Reset the
effective min
               SetVar(5,VAR7)         Reset the effective min
               SetVar(4,VAR5)
               SubVar(4,VAR1)
               DivVar(4,VAR2)             Calculate DEFCON
            Else
               SetVar(6,1)
            EndIf
         EndIf
         SetVar(8,0)
      Else
         SetVar(8,1)                                   Descending
      EndIf
   EndIf

   SetVar(7,VAR3)
   If(VAR4,>,2)
      SetPower(ac,4)                           Slow down!
   Else
      SetPower(ac,7)
   EndIf
EndWhile

AlterDir(ac)
Wait(50)
Off(ac)

END TASK

The basic strategy is to measure DEFCON, in variable 4.  The higher
DEFCON gets, the closer we are to the object.

The variables used are:
VAR1 - Maintains the initial ambient light value, and a moving average
of same
VAR2 - The difference - a number that represents how much brighter the
raw reading has to be to raise DEFCON one level.
VAR3 - the latest light sensor raw reading
VAR4 - DEFCON
VAR5 - The current effective minimum (brightest) raw reading
VAR6 - 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.
VAR7 - the reading prior to VAR3, used to determine if things are
getting brighter or darker
VAR8 - a flag that readings are currently descending (getting brighter)

First, it takes a few samples of the ambient light and calculates the
average in Var 1.  Next, based on the ambient light level, it calculates
difference in Var 2.  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 Variable 3.  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 Variable 1.
For the same reason, it also recaclulates difference into Var 2.

Next, it flashes and takes a reading into Var 3.  Var 5 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 Var 5 instead, b)clear Var 6
to indicate that minimum readings are definitely getting brighter, c)
set Var 8 to indicate that sequential readings are descending d)
calculate DEFCON as the number of difference levels (Var 2) 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 Var 5.  Check Var 6 - 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 Var 5 to Var 7'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 Var 6 and try again.

There's also code in there to have the bot slow down at DEFCON 2, and
back up and quit at DEFCON 3, but it's up to you what you do with the
distance info - you might want to speed up and ram.

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!



Message has 1 Reply:
  Re: LONG!!! - RCX Radarbots and distance measurement
 
This is the best yet! I have taken the liberty of converting it to NQC and removing the motor control commands. This gives a task that publishes DEFCON and AVG_AMBIENT that can be used in a monitor loop. This is so sensitive that DEFCON 1 is pretty (...) (26 years ago, 8-Feb-99, to lugnet.robotics)

2 Messages in This Thread:

Entire Thread on One Page:
Nested:  All | Brief | Compact | Dots
Linear:  All | Brief | Compact
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR