Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Autopilot plane

Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
01-14-2007 14:36
Has anyone written script for a 'plane' style vehicle entirely piloted by a script? I'm trying to write scripts for a bird-type creature that should be able to fly around on its own (as well as landing, swooping down to eat seeds, etc), and even with the simplification of setting buoyancy to 1.0 so I don't have to be moving to generate lift, I still don't think it's simple to get them going where I want them to, while still looking realistic.

Has anyone got experience with this, or better, scripts to share?
grumble Loudon
A Little bit a lion
Join date: 30 Nov 2005
Posts: 612
01-14-2007 23:55
The AutoBahn system creates a vechical without using the vehicle system.
http://www.lslwiki.com/lslwiki/wakka.php?wakka=Autobahn

Here is the current vehicle script.
The rotation does not work yet, but it shows the basic concept.
CODE

// Automatic car script, By grumble Loudon
//From Simple car script V1.0
//
//V0.4 (not done)

integer m_DesiredSpeed = 0; // forward/ reverse
integer m_WheelPos = 0; // Right / left

//*********************************************************************************
integer m_Lane = 1;
integer m_Segment = 0;

integer m_Scanning = FALSE;
key m_DetectedKey; //

integer m_RoadValid; //We have an item.

string m_DetectedRoadName;

//list m_DetectedList; //it's data

integer m_UseRotation; //true to use prim rotation
//vector m_DetOffset; //true to use prim rotation
vector m_TargetPos;
rotation m_TargetRot;
key m_TargetKey;

vector m_RotVect;

//
vector m_VelLast;
rotation m_RotLast;


//-------------------------------------------------------------------
// NoteCard configuration

string m_strNotecard = "Config";
integer m_lineCounter = 0;
key m_dataRequestID = "";

vector m_SitTargetPos = <0,0,0>; //Overridden by notecard
rotation m_SitTargetRot = ZERO_ROTATION; //

//*********************************************************************************
UseCommand(string msg)
{ //message from either chat or notecard
integer msgLen = llStringLength(msg);
if (msgLen >= 3) //we need at least one command char and one data char
{
if (llGetSubString(msg,0,0) != ";")
{ //comment
integer nFind = llSubStringIndex(msg,"=");
if ((nFind >= 1 ) && ((msgLen - nFind) > 1))
{ //commands must be at least 1 chars
string command = llGetSubString(msg,0,nFind - 1);

string strData = llGetSubString(msg, nFind + 1, msgLen - 1);
if (command == "SitTargetPos"){
m_SitTargetPos = (vector)strData;
llSitTarget(m_SitTargetPos, m_SitTargetRot);
}else if (command == "SitTargetRot"){
m_SitTargetRot = (rotation)strData;
llSitTarget(m_SitTargetPos, m_SitTargetRot);
};// command
};//find
}; //comment
};// len <4



}//Use message
//*********************************************************************************
UpdateStatus(){
string msg;


msg = "Wheel = " + (string) m_WheelPos;
msg += "\nSpeed = " + (string) m_DesiredSpeed;
msg += "\nEnergy = " + (string) llGetEnergy();
if (m_RoadValid == FALSE){
msg += "\nRoad not valid. Scaning = " + (string)m_Scanning;

}else{
msg += "\n" + m_DetectedRoadName + " Target Pos = " + (string)m_TargetPos;
if (m_UseRotation){
msg += "\n Rotation = " + (string)m_TargetRot;
}else{
msg += "\n Auto Rotation = ";
};
msg += "\n Test tourqe = " + (string)m_RotVect;
};

llMessageLinked(LINK_ALL_CHILDREN, 1, msg, NULL_KEY);
//llSetText(msg,<1,1,1>,1);
}

//*********************************************************************************
UseRoadName(string ObjectName){

//
//llOwnerSay(ObjectName);

m_RoadValid = FALSE;
list Prams = llParseStringKeepNulls(ObjectName,[";"],[]);
integer listLenght = llGetListLength(Prams);
if (listLenght >= 7 ){
//0 PublicRoad
//1 version
//2 Lane
//3 speed
m_DetectedRoadName = llList2String(Prams,4); //4 Name
m_TargetPos = (vector)llList2String(Prams,5); //5 target

string RotStr = llList2String(Prams,6); //6 rotation
if (llStringLength(RotStr) > 2){
m_TargetRot = (rotation)RotStr;
m_UseRotation = TRUE;
}else{
m_UseRotation = FALSE;
};
string keyStr = llList2String(Prams,7);//7 next key
if (llStringLength(keyStr) > 10){
m_TargetKey = (key)keyStr;
m_RoadValid = TRUE;
};

UpdateStatus();
};//list count >= 7

}//Use name

//*********************************************************************************
default
{
state_entry()
{
llMessageLinked(LINK_ALL_CHILDREN, 0, "stop", NULL_KEY);
llCollisionSound("", 0.0);
llSetSitText("Drive");

llSitTarget(<0.0,-0.0,-0.1>, ZERO_ROTATION);
llStopSound();

llSetTimerEvent(0.0);


// llSitTarget(<0.1, 0.35, 0.6>, <0,-0.2,0,1>); //buggy
llSetCameraEyeOffset(<-5.0, 0.0, 2.5>);
llSetCameraAtOffset(<0.0, 0.0, 1.0>);

// remove all flags
llRemoveVehicleFlags(-1);

llSetStatus(STATUS_PHYSICS, FALSE);
llSetStatus(STATUS_PHANTOM, TRUE);
llSetBuoyancy(1); //floats

llSetForceAndTorque(<0,0,0>,<0,0,0>,TRUE);

//Kick off notecard reader
m_dataRequestID = llGetNotecardLine(m_strNotecard, m_lineCounter);

}
//****************************************************************************
on_rez(integer startPram){
llResetScript();
}
//****************************************************************************
dataserver(key queryid, string data)
{
//Check to make sure this is the request we are making.
//Remember that when data comes back from the dataserver,
//it goes to *all* scripts in your prim.
//So you have to make sure this is the data you want, and
//not data coming from some other script.

if(m_dataRequestID == queryid)
{
if(data != EOF){
UseCommand(data); //feed the notecard to the message processor
m_lineCounter++;
m_dataRequestID = llGetNotecardLine(m_strNotecard, m_lineCounter);
}
}
}//dataserver
//****************************************************************************
changed(integer change)
{
if (change & CHANGED_LINK)
{
key agent = llAvatarOnSitTarget();
if (agent)
{
if (agent != llGetOwner())
{
llSay(0, "You aren't the owner");
llUnSit(agent);
llPushObject(agent, <0,0,100>, ZERO_VECTOR, FALSE);
}
else
{
// You sit and are owner so get controls
llSetStatus(STATUS_PHANTOM, FALSE);
llSetStatus(STATUS_PHYSICS, TRUE);
llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, TRUE);
llSetForceAndTorque(<0,0,0>,<0,0,0>,TRUE);
llRequestPermissions(agent,PERMISSION_TAKE_CONTROLS);

//timer is turned on after premissions are ok
}
}
else
{
// You stand so car stops
// llMessageLinked(LINK_ALL_CHILDREN, 0, "stop", NULL_KEY);
llSetForceAndTorque(<0,0,0>,<0,0,0>,TRUE);
llSetStatus(STATUS_PHYSICS, FALSE);
llSetStatus(STATUS_ROTATE_X | STATUS_ROTATE_Y | STATUS_ROTATE_Z, FALSE);
llSetStatus(STATUS_PHANTOM, TRUE);
llReleaseControls();
// llStopSound();
llSetTimerEvent(0.0);
llSensorRemove();
}
}else if (change & CHANGED_INVENTORY)
{
llResetScript(); //re read notecard
}; //if


}//changed
//****************************************************************************
run_time_permissions(integer perm)
{
if (perm)
{
// Take these controls and lets go
llTakeControls(CONTROL_FWD | CONTROL_BACK | CONTROL_RIGHT | CONTROL_LEFT | CONTROL_ROT_RIGHT | CONTROL_ROT_LEFT | CONTROL_UP | CONTROL_DOWN, TRUE, FALSE);

m_DesiredSpeed=0;
m_WheelPos = 0; // Right / left
UpdateStatus();
m_RoadValid = FALSE;
m_Scanning = TRUE;
// llLoopSound("car idle",0.3);
llSetTimerEvent(0.5);
llSensorRepeat("",NULL_KEY,PASSIVE|ACTIVE,12,PI,2.3);

}
}
//

//****************************************************************************
no_sensor(){
//m_Detected = 0;
}
sensor(integer num_detected){
//m_Detected = num_detected;

vector MyPos = llGetPos();

integer i;
float d;
vector p;
float MinDistance = 96; //find nearest
integer UseIndex = -1;
for (i=0; i < num_detected ; ++i){
string name = llDetectedName(i);
if (llGetSubString(name,0,9) == "PublicRoad"){

p = llDetectedPos(i);
d = llVecDist(p,MyPos);
//get distance

if (d < MinDistance){
key IdxKey = llDetectedKey(UseIndex);
// integer lane = 0;//(integer)llGetObjectDesc(IdxKey);
// if (lane == m_Lane){
UseIndex = i;
MinDistance = d;
// };
};
};//name
};//for
if (UseIndex != -1) {
key IdxKey = llDetectedKey(UseIndex);
if (m_DetectedKey != IdxKey){
m_DetectedKey = IdxKey;
string nextName = llDetectedName(UseIndex);
UseRoadName(nextName);
if (m_RoadValid) {
// llOwnerSay(nextName);
llSensorRemove();
m_Scanning = FALSE;
};
};
}else{
//m_Detected = 0; //might as well be zero
};

// vector m_TargetPos;
// rotation m_TargetRot;
} //sensor
//****************************************************************************
control(key id, integer level, integer edge)
{

if(level & CONTROL_FWD)
{
// Set cruising speed faster
if(m_DesiredSpeed < 10) //limit forward speed
{
m_DesiredSpeed +=1;
UpdateStatus();
}
}
if(level & CONTROL_BACK)
{
// Set cruising speed slower
if(m_DesiredSpeed > 0) //limit reverse speed
{
m_DesiredSpeed -=1;
UpdateStatus();
}
}
if((level & CONTROL_FWD) && (level & CONTROL_BACK))
{
// Forwards and Backwards <-- Brakes or stops
// llMessageLinked(LINK_ALL_CHILDREN, 0, "brake", NULL_KEY);
m_DesiredSpeed=0;
UpdateStatus();
}
if(level & (CONTROL_RIGHT|CONTROL_ROT_RIGHT))
{
m_WheelPos += 1; // Turn right
UpdateStatus();
}
if(level & (CONTROL_LEFT|CONTROL_ROT_LEFT))
{
m_WheelPos -= 1 ; // Turn left
UpdateStatus();
}
if(level & CONTROL_UP)
{
// add features for when you press up
}
if(level & CONTROL_DOWN)
{
// Added feature for when you press down
}

}
//****************************************************************************
timer()
{

//where are we
vector MyPos = llGetPos(); //current sim position
vector curVel = llGetVel(); //how fast are we moving
rotation CurRot = llGetRot(); // current rotation
vector RotVel = llGetOmega();//rotational velocity in radians/second
float MyMass = llGetMass();



vector Force = <0.0,0.0,0.0>; //output
vector Torque = <0.0,0.0,0.0>;

if (m_RoadValid == TRUE) {


//Adjust for vechical size and base prim rotation
//
//To do!!!

//movement

vector v2Next = m_TargetPos - MyPos; //point at target
if (llVecMag(v2Next) > 1.0){ //below 1m then dampen to stop
v2Next = llVecNorm(v2Next); //normilze directon
};

Force = v2Next * m_DesiredSpeed;

Force -= curVel; // remove current speed

//Force.z += -0.98; //make gravity again, but in local direction.

Force *= MyMass;
Force *= .5; // Time constant of velocity loop

//Rotation
rotation TargetRot;
if (m_UseRotation) {
TargetRot = m_TargetRot;
}else{
//use vector twards target pos
//Z up
TargetRot = ZERO_ROTATION;
//To Do!!!

};

//compare to current
rotation newRot = CurRot * TargetRot; // compute global rotation
//llSetRot(new_rot); // orient the object accordingly

vector RotVect = llRot2Euler(newRot) ; //convert to angle in radians

m_RotVect = RotVect; //test

//RotVect = RotVect * 5.0; //speed

Torque = -RotVect; //oposite direction of where we are

// Torque.x = 0.0;
// Torque.y = 0.0;
// Torque.z = PI; //one rotation per second test


Torque -= RotVel; //remove current speed

// Torque *= MyMass;
// Torque = Torque * .9; //dampen rotational speed


//-----------------
//next road prim ?
if ((m_DesiredSpeed > 2 ) && (llVecMag(v2Next) < 2.0)){
//get next
string nextName = llKey2Name(m_TargetKey);
// llOwnerSay(nextName);
UseRoadName(nextName);
};

}else{ //road valid
Force = -curVel; // remove current speed
//Force.z += -0.98; //make gravity again, but in local direction.
Force *= MyMass;
Force *= .7; //dampen
}; //road detected

llApplyImpulse(Force,FALSE) ;
llApplyRotationalImpulse(Torque, FALSE);


//display
if (m_WheelPos != 0){
m_WheelPos =0;
// UpdateStatus();
};
UpdateStatus();

} //timer
}//state
Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
01-15-2007 12:14
Any particular reason you decided not to make them vehicles?
Senuka Harbinger
A-Life, one bit at a time
Join date: 24 Oct 2005
Posts: 491
01-15-2007 12:41
From: Arachnid Baxter
Any particular reason you decided not to make them vehicles?



It's very hard to make an AI that can control a true Vehicle in SL. I've got one such AI on the back burner. The biggest pit-falls are knowing when to start and stop turning. Accelleration is difficult as well, but I have a routine which works fairly well for the linear movement. I haven't experimented with 3d movement (planes), but I'd imagine that the height element would need to be based along similar logic gates as the turning routine.


In general it's much easier to work with a llMoveToTarget() "vehicle" for set waypoints than it is to have a true vehicle going from point A to point B.
_____________________
My SLExchange shop

Typos are forgiven; desecrating the english language with reckless abandon and necrophilic acts is not.


The function is working perfectly fine. It's just not working the way you wanted it to work.
Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
01-15-2007 12:50
Unfortunately, I'm building 'birds' (or something a lot like them, anyway), and a direct move-to-point style motion would look rather unrealistic. Though I may simply have to start from there and try and improve it later. :/
Simstick Boram
Registered User
Join date: 3 Dec 2006
Posts: 87
01-15-2007 14:07
LSL wiki under pets?

http://www.google.com/search?hl=en&lr=&safe=off&domains=http%3A%2F%2Flslwiki.com&q=+pet&btnG=Search&sitesearch=http%3A%2F%2Flslwiki.com
Arachnid Baxter
Registered User
Join date: 8 Jan 2007
Posts: 44
01-15-2007 14:29
Perfect! Thanks!