![]() |
![]() |
|
Sord's bEEtle was the reigning champion of the Hallway race for months before
being edged by a tenth of a second. Now he's laid out the details for all to
share. The first part is about the steering. Staying on the track is key.
The second part talks about the wiggle, which makes the bEEtle go very fast.
While staying on the track will only help you in the races, the wiggle effect can make your wheeled rover go faster anywhere. Enjoy. -Sprocket
Building | The bEEtle by Sord
|
The beetle has four physical components: a steering wheel, a large motor, and two track sensors. The motor should be set at 100% and the two track sensors need their range set (I found 1.3 to work well), but all other settings are set dynamically during the race and are not affected by the initial value.
Steering |
| Since our main goal is simply to stay on the track while going really fast, most of the beetles wiring is steering related. The beetle uses the system of feeling for the edges of the track and turning away whenever an edge is found. But rather than having a fixed angle on the feelers, the beetle attempts to set them to the widest angle possible.
Step 1 |
|
The first step is to setup the track sensors so that their angle is set based
on a variable, rather than being a fixed value. First we add a variable that
we will use to update the angles. For one sensor, the variable can be wired
directly to the track sensor. I picked the left track sensor because its angle
should be in a positive range and I'd like to set the variable to a positive
value.
Step 2 |
|
For the other track sensor, run the variables value through the value2 of a
subtract component to get the inverse. Use the output of the subtract to set
the track sensors angle. The subtract component's value1 also needs to be
fixed at 0, but since that is the default, it doesn't need to be changed.
At this point, we can set the angle of both track sensors by setting the variables value. The next step is to have the angle updated based on if the track sensors are on the track or off the track.
Step 3 |
|
We will need another variable to hold the current step size that we should
reduce or expand our angle. Since track sensors default to the off state, we
will set the initial variable value to the value we want when both track
sensors are off the track. My assumption is that if both sensors are off
track, then I am scanning too wide of an angle (one sensor is off the left side
and the other is off the right side). The are of course other possibilities,
but they generally mean I have lost the track and don't have a good chance of
recovery (we'll eventually try anyway, but it's not where I want to focus my
efforts). So, if I'm scanning too wide, I need to reduce my angle, so I set the
initial value to a negative number, -4 in this case.
Step 4 |
|
Now, eventually we will reduce the angle to the point that one of the track
sensors is back on the track. At this point we want to stop (or at least slow
down) the reduction rate. So in response to a TurnOn event, we will increment
the variable by +3. Once both track sensors are hooked up this way, if only
one registers as on track, we will still continue to reduce our angle (the
variable will have a value of -1), but if both sensors are on track, we will
start to increase our angle as the variable will now have a value of +2.
Step 5 |
|
Of course, if the track sensor goes back off the track, we need to undo our +3
increment. So in response to a TurnOff event, we will increment the variable
by -3.
Step 6 |
|
That setup one track sensor to modify our step size variable, so now we repeat
the same wiring for the other track sensor (TurnOn sends an incrementBy of +3
and TurnOff sends an incrementBy of -3).
Step 7 |
|
We now have a fully operational step size variable, but we need to do something
with it. Originally I had a loop timer setup to query the step variable, but
whenever I wanted to try a different step size, I needed to update all four
wires coming from the track sensors. To make my life easier, I decided to
route the step value through a multiply component so I could scale the step
size by just changing one wire. So, add a multiply component and wire the step
variable to set the value of input1.
Step 8 |
|
Add a loop timer and set its TickTime to 0.1 seconds. This is the frequency
that the angle will be updated.
Step 9 |
|
Wire the loop timer to set the input2 on the multiply whenever a tick event
happens (meaning every 0.1 seconds).
Step 10 |
|
Now we can wire the multiply component to increment the current angle variable
by the output of the multiply whenever the set event happens. Note that this
is the set event and not the change event. Most of the time the output of the
multiply will not be changing, so we must look for the set event (caused by the
loop timer setting the input2 value). We will also get some extra events when
a track sensor changes our step size, but the extra events just give a one time
boost to the rate of change and can be ignored.
Step 11 |
|
Our track sensors now will constantly update themselves to try and maintain a
lock on the edges of the track. The one last thing we need to do is some
sanity checking so that we don't go outside some reasonable bounds. To do this
we add a rangeTest component and set the minimum and maximum values to some
sane values. I happened to pick a range of [10-75], but I'm sure these values
could be tweaked to improve performance under unexpected conditions (like being
bumped).
Step 12 |
|
Wire our current angle variable to set the input of the rangeTest. Then wire
the rangeTest to set the variable to the rangeTest's maximum value if the
aboveRange event happens. This will prevent the angle from exceeding our
maximum value.
Step 13 |
|
Also wire the rangeTest to set the current angle variable to the rangeTest's
minimum value if the belowRange event happens. This prevents the angle from
dropping below our minimum.
Step 14 |
|
Our track sensor will now do their best to stay right at the edges of the
track. Next we need to wire up the actual steering. Fortunately this part is
much easier. However, for the first step I took a shortcut and used the fact
that a track sensor's ON state is equal to the value 1 and that the OFF state
is equal to 0. You could also set the values based on the turnOn and
turnOff events, it just would require 4 wires instead of two. To use my
shortcut, just wire the left track sensor to set the input1 of a subtract
component to the track sensor's state.
Step 15 |
|
Then wire the right track sensor to set the input2 of the subtract component to
the right track sensor's state.
Step 16 |
|
The output of the subtract will now be -1, 0, or +1 depending on the states of
the track sensors. It will be -1 if the left sensor is off the track (=0) and
the right sensor is on (=1) since (0-1 = -1). This works out great since if
our left sensor is off the track, we want to steer to the right, which would be
a negative steering angle. Of course, -1 isn't enough of a steering angle, so
we need to multiply it by some factor. So wire the subtract to set the input1
of a multiply to the output of the subtract and set the input2 of the multiply
to a fixed value (I used 8 for the beetle).
Step 17 |
|
The final step is to wire the output of the multiply to set the angle of the
steering wheel. You now have a fully functional racing rover. Try it out. If
it doesn't work, you probably missed changing one of the default values for a
wire. Common problems would be setting a variables value instead of setting
the incrementBy property, or having a multiply set a fixed value instead of
passing on its output.
The Wiggle |
If you do some testing, you may find that it doesn't go quite as fast as some
of the other rovers. That's because a design flaw in the physics engine gives
turning rovers a speed boost, so it is beneficial to always be turning. It is
a fairly easy change to add a continuous wiggle to a rover, so that will be our
first enhancement.
|
Step 1 |
|
The first thing to do is to setup an oscillator. I did this using two one shot
timers. Each timer will set the other time when it triggers cause an endless
loop of events. To start, add two timers and set one of them to start with a
TickTime of 0.1 seconds.
Step 2 |
|
Add a wire that will set the TickTime of the second timer to 0.1 seconds when
the first timer's tick event happens.
Step 3 |
|
Then add a wire from the second timer back to the first that sets the first
timer to 0.1 seconds when the second timer's tick event happens.
Step 4 |
|
You now have an oscillator and can start generating steering inputs from it.
However, since we don't want to override the input we already have, we use an
add component to add the wiggle to whatever steering we are already doing.
Have one of the timers set the input1 of the add component to a small positive
steering (I used +3) when the tick event happens.
Step 5 |
|
Set the other timer to also set the input1 of the add to a small negative value
(I used -3) when the tick event happens.
Step 6 |
|
Finally, delete the wire from the multiply to the steering and instead route it
though the new add component. The multiply should set input2 on the add to the
multiply's output and the add should set the steering angle to the add's
output.
Test out your enhanced rover and you should see a significant improvement.
Other Stuff |
| The other enhancement I made to the beetle was to detect a lost track condition (usually plowing into a wall) and to backup and attempt to get back on the track. This enhancement is of questionable merit since the race is probably lost if it ever has to be used. But it is an interesting concept and I'm sure it can get put to good use in many other circumstances. To detect a lost track, I hook both track sensors to an Or component, if the Or triggers a turnOff, then both track sensors are off the track and I set a timer for 0.5 seconds. If I don't get a turnOn in that time (which would pause the timer), I reverse the engine and turn the steering wheel to one side. I also set a second timer that, once expired, sets the engine back to forward and turns the steering wheel to the other side.
You can reach Sord at sord@bigfoot.com
| |
![]() |
![]() |