Robotics

This page is currently under construction (But don't let that stop you contributing)- Tip

The objective of this page is to provide information, techniques and tips on the scripting of autonomous objects (And to give me some practice in formating a wiki page Tip). That is, objects that move on their own.

This tutorial is intended for those with a good general knowledge of LSL and programming.

The term 'robot' will be used on this page to describe such an autonomous object.

Movement

You have a choice of three different principles for movement each with their own advantages and restrictions:

Non-physics based

Physics based non-vehicular

Vehicular

Non-physics based

A non-physical robot can be moved using llSetPos, or llSetPrimitiveParams. Rotation can be achieved using llSetRot, llLookat or llRotLookAt depending on the application. The comments for llSetPos have further information on how to get round some of the limitations for long distance movement.

llSetPos has a 10-meter range limit. There are a few ways to get around this, but the fastest is to use this bit of code:

Anorca Calamari's example didn't appear to work for me (OpenSim, 0.6.4). Here is an example of a non-physical robot which did work. It makes use of RandomVector, from the ScriptLibrary. It is slightly bugged -- robot movement is not terribly smooth, and it tends to stop after an arbitrary amount of time. If anyone could tell me why it stops, I'd be obliged. ~ StormSaber

// This is an example, from StormSaber, of a robot which moves non-physically. It uses a llSetPos to fake smooth movement.
float DELAY = 0.0;
// The script sleeps this amount of time before moving to the next spot in between its current position and its target.
// In practice, theres no need to set this to anything other than 0 as LSL forces the script to sleep 0.2 seconds anyway.
float INCREMENT = 0.1;
// This defines the amount by which the robot should move, in each iteration of the script. Higher is faster.
float TOLERANCE = 0.1;
// When the robot is a certain distance from its target, it will give up and find another one.
// (A metaphor would be that you tend not to measure the distance to your house in centremetres -- after a certain distance, it becomes moot.)
// You can play about for interesting results by finding the relationship between TOLERANCE and INCREMENT.
// In practice, TOLERANCE probably shouldn't be less than INCREMENT.
vector target;
// Contains the current target we are moving towards
integer moving = FALSE;
// Are we moving? When the robot spawns, it should await commands from a user so the answer is 'no'.
// This function does the main work:
object_move_to(vector targetPos) {
if (moving) { // Check if we're actually supposed to be moving...
// We need to find out if we're close enough to the target that we should actually move closer to it.
if (llVecDist(llGetPos(), targetPos) > TOLERANCE) {
//If we still need to get closer, start by getting our current position.
vector position = llGetPos();
// We find where we need to go next by setting our axes one dimension at a time.
// First we find out if our x position is larger than the targets x position.
if (targetPos.x > position.x) {
position.x = position.x + INCREMENT; // If it is, increment (make larger) our x position.
} else if (targetPos.x < position.x) {
position.x = position.x - INCREMENT; // Otherwise, our x position is smaller than the targets. Decrement our x position.
}
// Now do the same for y.
if (targetPos.y > position.y) {
position.y = position.y + INCREMENT;
} else if (targetPos.y < position.y) {
position.y = position.y - INCREMENT;
}
// Finally for z.
if (targetPos.z > position.z) {
position.z = position.z + INCREMENT;
} else if (targetPos.z < position.z) {
position.z = position.z - INCREMENT;
}
// Teleport to our new position, which we've calculated to be only slightly closer to the target
// In this context, slightly closer means closer by INCREMENT in all three axes.
llSetPos(position);
// Sleep for the recommended amount of time, to prevent ourselves going too fast.
llSleep(DELAY);
// Recursively call this function. We'll look, ending when we're close enough.
object_move_to(targetPos);
} else {
//Oop, we've arrived. Time to choose another target...
llWhisper(0, "... eep..");
chooseTarget();
}
}
}
// FROM RandomVector on the lslwiki.net ScriptLibrary page
// Chooses a random number between min and max.
float randBetween(float min, float max) {
return llFrand(max - min) + min;
}
// FROM RandomVector on the lslwiki.net ScriptLibrary page
vector randVector() { //HERE we use the randBetween we have up on top to
//make a random number from 100 to 500 - on the Z axis. Fun for a trampoline :)
return <randBetween(10, 20),randBetween(10, 20),randBetween(20, 30)>;
}
// Chooses a random position, informs everyone we're moving to it, then moves to it.
chooseTarget() {
target = randVector();
llShout(0, "Moving to " + (string) target);
object_move_to(target);
}
// The script starts here. It informs the user the robot is online, then enters the 'not_moving' state.
default {
state_entry() {
llOwnerSay("Robot Online");
state not_moving;
}
}
// In the moving state, we choose a target then move to it.
state moving {
state_entry() {
moving = TRUE;
chooseTarget();
}
// When touched in the moving state, make a chirp and then enter the 'not moving' state.
touch_start(integer _i) {
llOwnerSay("Eep!");
state not_moving;
}
}
// In the not moving state, we wait to be touched by a user.
state not_moving {
state_entry() {
moving = FALSE;
}
// When touched, we should chirp, then enter the moving state.
touch_start(integer _i) {
llOwnerSay("Eeeep!");
state moving;
}
}

I have never used non-physics based movement, so I shall leave it to others to add additional information to this section - Tip

Physics, Non-Vehicle Based

Example
This example shows a simple ground based, hopping motion. It was created for a small, mass < 5, robot. The robot moves towards its target, the nearest avatar, by turning towards its target and then jumping forward. If it is too near its target, it jumps back. After a few seconds near an Avatar, it leaves that one and moves towards another. Note: You can also use llMoveToTarget for physics based vehicles.

Flying

To make a non-vehicle, physics based robot float in the air or water or to fly, you need to set the bouyancy to 1.0 to cancel the effect of gravity. Because of the effect of energy loss, robot's using this technique cannot have a mass greater than 90 units. Use the llGetMass function to find the mass. If the model is just over 90 units in mass, try hollowing some of the prims.

Example
This example is taken from a small, mass < 10, flying robot. It is based on the Create a flying pet example. The code requires brain script to tell it, via link messages, a waypoint, a speed and a target distance (How near to get to the waypoint). This script then moves the robot using llSetForce and llApplyImpulse to the waypoint. It sends a link message when it has reached the waypoint.

The example has simple collision detection. If it collides with an object or the ground it moves back, to the left and up.

Vehicle Based

Example
This is an example of a simple vehicle based 'engine'. It does nothing except move and change direction as directed by the contents of the link messages it receives. Creating functional modules like this has a number of advantages, including being able to take an 'engine' such as this and drop it into a robot with different behaviours.

This example was originally in a Star Wars droid with a single behaviour of moving from waypoint to waypoint My first vehicle - Tip. It then spent some time in a small follower style pet. The last incarnation was in a large (20 m) ship capable of navigating across void sims.

Sensors

A sensor sweep detecting all around an object has a sweep of PI not 2 * PI as may be expected.

llSensor does not detect objects in adjacent sims. llSensorRepeat has limitations when detecting objects in adjancent sims

Location

Gimbal Mounts

Putting a sensor in its own prim has a number of advantages:

For ground based robots a problem can occur when a robot is travelling over uneven ground. If the sensor is in the root prim of the robot, it could end up pointing into the air or ground. With the sensor in a separate prim, its rotation can be altered to keep the sensor pointing in the correct direction. This is a common technique in RL robotics.

Mounting the sensor as far forward as possible has advatages for collision detection.

The sensor can be scripted to rotate slightly in the direction the robot is turning.

Sensor Arc

As noted, an arc of PI is required to detect object/avatars in a sphere around a robot, not TWO_PI. In practice, if a complete sphere is what is required, it doesnt matter whethere PI or TWO_PI are used. But it must be taken into account if less than a complete sphere is required.

If an animal is being simulated, then the animals field of view is, in part, determined by whether it is hunting or hunted. Hunters tend to have their eyes looking forward to give them good depth perception but with a narrower field of view. The hunted have their eyes either side of their head giving them a wide field of view, so they can see hunters behind them. Think of the difference between the eye position of a cat compared with a rabbit. Take this into account when deciding on the sensor arc.

Collision Avoidance

The objective of collision avoidance is to detect a potential obstacle and then take action to avoid a collision.

Sensor Range and Repeat Rate

It is worth doing a few rough calculations when deciding on the arc, rate and range parameters of your sensor sweep.

Example How far ahead does a robot moving at 10 meters a second have to look to have enough time to spot potential obstacles?Assumptions, a one second sensor sweep, ignore the limitations of sensors with regards over 16 objects and only centres being detected.

In one second, the robot travels 10 meters, therefore in the next second it will collide with any object within the 10 meters ahead. A one second sensor with a 10 meter range will pick up any hazzards.

If the robot is 10 meters long (I like big robots - Tip) then the front of the robot could be five meters ahead of where the sensor range is measured from. So a 15 meter sensor range is needed.

If the object that it is most likely to be encountered is a similar sized robot, then the target's front edge is five meters ahead of the point that will be detected. Therefore a 20 meter sensor range is needed.

If the object is another robot, it may be moving straight at the orginal robot at 10 meters per second. Sensor range needed is now 30 meters.

If the robot is vehicle based, the VEHICLE_LINEAR_MOTOR_TIMESCALE and other vehicle related parameters will cause a delay before the robot actually changes direction or speed. If this delay is around a second, then another 10 meters needs to be added to the sensor range.

Therefore, for a robot moving at 10 meters a second, a sensor range of 40 meters may be required. Obviously increasing the sensor repeat rate will reduce the sensor range required.

Thinking ahead

Not all the moving objects detected in a sensor sweep are a hazard, it depends on the direction they are moving in. Whether or not an object is on a collision course can be determined as follows:

Calculate the current distance between the robot and the detected object using llVecDist

Faking Collision Avoidance

Collision avoidance is tricky. In a controlled environment (hint Void sims) good results can be achieved. In the real world (err... you know what I mean), it is not easy to detect all potential hazards or decide how to avoid them. A simple but effective alternative is to fake it with a invisible bumper.

Getting Stuck

It's a one in a million chance, but very very occasionally a robot may get stuck. Trapped between two prims or unable to navigate around an obsticle, the robot constantly collides with the blocking object.

In many cases, dependant on relative speeds, the robot can inter-penetrate I know there is a better word, when I'm awake I'll remember - Tip the obstacle. In this case, physics wil be turned off.

For the creator this is another interesting problem, but for everyone else this is a Bad Thing. Constant collisions between objects is irritating especially if the noise is not suppressed. It is also a major drain on simulator resources, and may result in the Lindens tapping on your door.

First problem that has to be solved is, how does the robot know it is stuck, A number of techniques can be used in combination depending on the scenario:

Has it taken too long to reach its destination? When a new movement target is selected, estimate the time it shoud take to reach the target. If after this time, plus a bit, the robot has not reached its destination, take action. This method can catch the situations where the robot isnt stuck, but is unable to manouver out of a 'trap' and ends up moving in a loop.

Check the robots speed. If it is not moving, and it should be, it could be stuck.

Has physics been turned off?

Constantly colliding with the same object can also be a good sign that the robot is stuck, unless the object is below the robot in which case it could be the floor.

Like many aspects of behaviours, there is no one 'Flag' that can read to determine if a robot is stuck. Its case of experimenting, finding out what in practice causes your robot to become trapped and then figuring out how to detect it. Try having the 'is it stuck' functionality as a single script which sends out a link message when it thinks the robot is stuck.

The action you take depends on whether you want the robot to continue onto its destination or not. If not, select a new destination, preferable in the opposite direction to the obsticle.

If the robot still needs to get to its original destination, the action depends on how sophisticated your behaviours are. A simple trick is to turn the robot phantom for a while and let in move through the blocking object. Use the Collision event to determine when the robot has reached the other side.

Behaviours

External References

CW Reynolds page on steering behaviours. Craig Reynolds created the flocking algorithm. This is a must read. The java applets are great, but there is more information in the actual paper itself.

AI planning in the FEAR game. Top of the right hand column are some presentations describing some of the high level strategies used to develop an AI capable of planning ahead to achieve its goal.