This page is currently under construction (But don't let that stop you contributing)- Tip
| Functions | Events | Notes |
| llSetPos, llSetPrimitiveParams | For non physical movement | |
| llTarget, llTargetRemove | at_target, not_at_target | In order to know whether or not the robot has reached a specific location |
| llRotTarget, llRotTargetRemove | at_rot_target, not_at_rot_target | In order to know whether or not the robot is facing in a specific direction |
| collision, collision_start, collision_end | In order to know when the robot has hit something | |
| llLookAt, llRotLookAt , llSetRot | To make a robot face a specific direction. Not recomended for vehicle based robots. | |
| llSetForce, llSetForceAndTorque, llApplyImpulse, llMoveToTarget, llStopMoveToTarget | For non-vehicle, physics based movement | |
| llSetBuoyancy | In order to make small physics based robots hover. Not recomended for vehicle based robots. | |
| llSensor, llSensorRepeat | sensor, no_sensor | In order to detect what is around the the robot |
You have a choice of three different principles for movement each with their own advantages and restrictions:
or so that you dont use energy
warpPos( vector destpos ) { //R&D by Keknehv Psaltery, 05/25/2006 //with a little pokeing by Strife, and a bit more //some more munging by Talarus Luan //Final cleanup by Keknehv Psaltery // Compute the number of jumps necessary integer jumps = (integer)(llVecDist(destpos, llGetPos()) / 10.0) + 1; // Try and avoid stack/heap collisions if (jumps > 100 ) jumps = 100; // 1km should be plenty list rules = [ PRIM_POSITION, destpos ]; //The start for the rules list integer count = 1; while ( ( count = count << 1 ) < jumps) rules = (rules=[]) + rules + rules; //should tighten memory use. llSetPrimitiveParams( rules + llList2List( rules, (count - jumps) << 1, count) ); }
Here is an example of a non physical robot by AnorcaCalamari
//Written by Anorca Calamari on the TG //This robot moves non-physically. //It only turns phantom so that you can walk through it. It does not need to be phantom to go through walls. //It randomly chooses targets within 50 meters excluding the owner. //If noone is within 50 meters or only the owner is within 50 meters it increases the range. It continues //increasing till it finds a target and moves there,at which point it resets to 50. integer range=50; default { touch_start(integer total_number) { if(llDetectedKey(0) == llGetOwner()) { llSetStatus(STATUS_PHANTOM,TRUE); llOwnerSay("ROBOT ON"); state on; } } } state on { state_entry() { llSensorRepeat("","",AGENT,range,PI,2.5); } sensor(integer num_detected) { integer target = (integer)llFrand((float)num_detected); if(llDetectedKey(target) == llGetOwner()) { integer target = (integer)llFrand((float)num_detected); } if(num_detected == 0 | num_detected == 1 && llDetectedKey(0) == llGetOwner()) { integer range=range+10; } while(llGetPos() != llDetectedPos(target) + <0,0,2> && llDetectedKey(target) != llGetOwner()) { llSetPos(llDetectedPos(target) + <0,0,2>); } if(llGetPos() == llDetectedPos(target) + <0,0,2>) { range=50; } } touch_start(integer total_number) { if(llDetectedKey(0) == llGetOwner()) { llOwnerSay("ROBOT OFF"); llResetScript(); } } }
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.
integer current_food_level = 0; integer maximum_food_level = 2; key current_target; float max_food_range = 4; float min_food_range = 2; vector kick_up = <0,0,1.5>; float forward_kick = 3; default { state_entry() { llOwnerSay("Script reset:moving to searching state"); llSetStatus(STATUS_PHYSICS,TRUE); llSetStatus(STATUS_ROTATE_X, FALSE); llSetStatus(STATUS_ROTATE_Y, FALSE); state searching; } } state searching { state_entry() { llSensorRepeat("","",AGENT,50, 2 * PI, 3); } sensor(integer total) { if(total == 0) { current_target = llDetectedKey(0); } else { current_target = llDetectedKey(1); } state moving; } state_exit() { llSensorRemove(); } } state moving { //This state moves the robot towards or away from the selected Agent. state_entry() { llSensorRepeat("",current_target,AGENT,50, 2 * PI, 3); llSetTimerEvent(30); } no_sensor() { state searching; } state_exit() { llSensorRemove(); llSetStatus(STATUS_PHANTOM,FALSE); } timer() { //If the target hant been reached after 30 seconds, the robot may be stuck behind something //So go phantom to get throught it. llSetStatus(STATUS_PHANTOM,TRUE); } sensor(integer total) { if(llVecDist(llGetPos(),llDetectedPos(0)) > max_food_range) { // llWhisper(0,"too far"); llApplyImpulse((kick_up + <0,0,llFrand(1)>) * llGetMass(), FALSE); llApplyImpulse(-llVecNorm(llGetPos() - llDetectedPos(0)) * forward_kick * llGetMass(), FALSE); } else if(llVecDist(llGetPos(),llDetectedPos(0)) < min_food_range) { //move away from food llApplyImpulse((kick_up + <0,0,llFrand(1)>) * llGetMass() , FALSE); llApplyImpulse(0.5 * llVecNorm(llGetPos() - llDetectedPos(0)) * forward_kick * llGetMass(), FALSE); } else { //Just right, start feeding state feeding; } } } state feeding { state_entry() { llSensorRepeat("",current_target,AGENT,20, 2 * PI, 3); } no_sensor() { // llWhisper(0,"target lost, searching"); state searching; } state_exit() { llSensorRemove(); } sensor(integer total) { // llWhisper(0,"pong"); if(llVecDist(llGetPos(),llDetectedPos(0)) > max_food_range) { // llWhisper(0,"too far"); state moving; } else if(llVecDist(llGetPos(),llDetectedPos(0)) < min_food_range) { //move away from food state moving; } current_food_level = current_food_level + 1; // llWhisper(0,"yum"); if(current_food_level > maximum_food_level) { current_food_level = 0; // llWhisper(0,"bored"); state searching; } } }
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.
float heartbeat = 0.5; float z_force = 0.4; //Go back, left and up if it collides with the land or an object vector collision_force = <-0.25,0.25,0.75>; vector target_position; integer target; //Start of code from wiki vector AXIS_UP = <0,0,1>; vector AXIS_LEFT = <0,1,0>; vector AXIS_FWD = <1,0,0>; // getRotToPointAxisAt() // Gets the rotation to point the specified axis at the specified position. // @param axis The axis to point. Easiest to just use an AXIS_* constant. // @param target The target, in region-local coordinates, to point the axis at. // @return The rotation necessary to point axis at target. // Created by Ope Rand, modifyed by Christopher Omega rotation rotation getRotToPointAxisAt(vector axis, vector target) { return llGetRot() * llRotBetween(axis * llGetRot(), target - llGetPos()); } //End of code from wiki all_stop() { llSetForceAndTorque(<0.0,0.0,0.0>, <0.0,0.0,0.0>, TRUE); llApplyImpulse(-llGetVel() * llGetMass(), FALSE); llApplyRotationalImpulse(-llGetTorque() * llGetMass(), FALSE); } default { state_entry() { llSetBuoyancy(1); llSetStatus(STATUS_PHYSICS,TRUE); llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y, FALSE); llSetTimerEvent(heartbeat); //llVolumeDetect(TRUE); //llSetStatus(STATUS_PHANTOM,TRUE); all_stop(); } link_message(integer sender_num,integer num, string data,key id) { if(num == 150) { list data = llParseStringKeepNulls( data, ["-=-"], [] ); string Cmd = llList2String( data, 0 ); if( Cmd == "MOVE" ) { target_position = (vector)llList2String( data, 1 ); float speed = (float)llList2String( data, 2 ); float range = (float)llList2String( data, 3 ); llTargetRemove(target); target = llTarget(target_position,range); llSetForce(<speed,0,0> * llGetMass(),TRUE); } if(Cmd == "STOP" ) { //Received a stop message llTargetRemove(target); all_stop(); } } } not_at_target() { llRotLookAt(getRotToPointAxisAt(AXIS_FWD , target_position), 1, 0.5); vector currentpos = llGetPos(); if(currentpos.z > target_position.z + 0.5) { //little push downwards llApplyImpulse(<0,0,-z_force> * llGetMass(),FALSE); } else { if(currentpos.z < target_position.z - 0.5) { //little upwards llApplyImpulse(<0,0,z_force> * llGetMass(),FALSE); } } } at_target(integer target_id,vector t_pos,vector o_pos) { all_stop(); llTargetRemove(target); llMessageLinked(LINK_SET,150,"ATPOS",""); } timer() { //Apply some friction llApplyImpulse(-llGetVel() * llGetMass() * 0.6,FALSE); }//end timer collision_start(integer num_detected) { //Hit something? //go abit higher llApplyImpulse((collision_force) * llGetMass(),TRUE); } land_collision_start(vector num_detected) { //Hit something? //go abit higher llApplyImpulse((collision_force) * llGetMass(),TRUE); } on_rez(integer param) { llTargetRemove(target); all_stop(); } } state turn_to_target { state_entry() { llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y, FALSE); llRotLookAt(getRotToPointAxisAt(AXIS_FWD , target_position), 0.1, 0.5); llSetTimerEvent(1); } timer() { state default; } link_message(integer sender_num,integer num, string data,key id) { if(num == 150) { list data = llParseStringKeepNulls( data, ["-=-"], [] ); string Cmd = llList2String( data, 0 ); if( Cmd == "MOVE" ) { target_position = (vector)llList2String( data, 1 ); float speed = (float)llList2String( data, 2 ); float range = (float)llList2String( data, 3 ); llTargetRemove(target); target = llTarget(target_position,range); llSetForce(<speed,0,0> * llGetMass(),TRUE); } } } }
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.
float speed_multi = 3; float turn_multi = 1; set_motor(vector speed,vector turn) { // llOwnerSay("speed = " + (string)(speed * speed_multi * llGetMass()) + " turn = " +(string)turn); llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, speed * speed_multi); llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, turn* turn_multi); } default { state_entry() { integer chosen_type = VEHICLE_TYPE_CAR; llSetVehicleType(chosen_type); llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_DECAY_TIMESCALE, 10.0); llSetVehicleFloatParam(VEHICLE_ANGULAR_MOTOR_TIMESCALE, 0.1); llSetVehicleFloatParam(VEHICLE_LINEAR_MOTOR_TIMESCALE, 0.1); llRemoveVehicleFlags(-1); llSetVehicleFlags(VEHICLE_FLAG_NO_DEFLECTION_UP | VEHICLE_FLAG_LIMIT_MOTOR_UP); llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, ZERO_VECTOR); llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, ZERO_VECTOR); } on_rez(integer param) { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, ZERO_VECTOR); llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, ZERO_VECTOR); } link_message(integer sender,integer num,string data,key id) { list Arguments = llParseStringKeepNulls( data, ["-=-"], [] ); string Command = llList2String( Arguments, 0 ); if( Command == "FWD" ) { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION, <1,0,0>* speed_multi); } if( Command == "STRT" ) { llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION,ZERO_VECTOR); } if( Command == "ROT_LFT" ) { llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,PI>); } if( Command == "ROT_RGT" ) { llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,PI>); } if( Command == "LFT" ) { llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,PI_BY_TWO>); } if( Command == "RGT" ) { llSetVehicleVectorParam(VEHICLE_ANGULAR_MOTOR_DIRECTION, <0,0,-PI_BY_TWO>); } if( Command == "STP" ) { llSetVehicleVectorParam(VEHICLE_LINEAR_MOTOR_DIRECTION,ZERO_VECTOR); } } }
There are a couple of 'gotcha's' with sensors.
The objective of collision avoidance is to detect a potential obstacle and then take action to avoid a collision.
Assumptions, a one second sensor sweep, ignore the limitations of sensors with regards over 16 objects and only centres being detected.
Page Information
|
Wiki Information |
Recent PBwiki Blog Posts |