Jump to content

KFM-Rotation between waypoints


You are about to reply to a thread that has been inactive for 2185 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

I'm making a KFM  object that will move/patrol along waypoints. I'm trying to figure out how to rotate towards the next waypoint before moving forward, and if it even needs to rotate.

here's what I have so far, but it's giving me odd looking rotations. I have my avatar sitting on a cube for this test. He should be facing the direction that it is moving, but some of the movements are backwards, while one is moving the correct direction. What am I doing wrong? Is there a simpler way to determine if it needs to rotate? 

list kfm()
{
    list temp = [];
    vector lastpos = llGetPos();
    integer len = llGetListLength(points);
    integer i;
    for(i = 0; i < len; i++)
    {
        vector nextpos = llList2Vector(points,i);
        float dist = llVecDist(nextpos,lastpos)/3;
        vector kfmvec = nextpos-lastpos;
        if(dist < mintime)dist = mintime;
        rotation rotbet = llRotBetween(<1,0,0>,llVecNorm(nextpos-lastpos));
        float angle = llRot2Angle(rotbet);
        if(angle > 0.1)
        temp += [ZERO_VECTOR,rotbet,1.25];
        temp += [kfmvec,ZERO_ROTATION,dist];
        lastpos = nextpos;
    }
    return temp;
}

 

Link to comment
Share on other sites

Your rotations may get a little wonky if the waypoints are not all at the same elevation, so what you'll want to do is calculate the angles with the Z components of nextpos and lastpost zeroed out.  That may be part of the problem.  

Incidentally, I asked a very similar question (different context) in another forum last week.  You may want to take a look.  >>  http://www.sluniverse.com/php/vb/scripting/134801-measuring-horizontal-angle.html

Edited by Rolig Loon
Link to comment
Share on other sites

I dunno if this will help ya at all , but just incase...

I've been using this for KFM tours for our Burningman events,

mebbe something to try?

to get the waypoints, I rez a box and put this script in it, then move, rotate and click it..

then I copy the text into my waypoints list and then move to the next waypoint etc...

Waypoint finder script

default
{
    state_entry()
    {     
    }
    touch_start(integer total_number)
    {    vector RC =  llGetRegionCorner();
         vector mypos = llGetPos();
         vector RCregPos = llGetRegionCorner() + mypos;         
         vector vRadBase = llRot2Euler( llGetRot()  );
         vRadBase *= RAD_TO_DEG;
         integer Z = (integer)vRadBase.z;       
         llOwnerSay("\n RegionCorner is " + (string)RC + "\nPos is " + (string)mypos );        
         llOwnerSay("\n \n Waypoint:\n"+ (string)RCregPos + ", < 0.0 , 0.0 , " + (string)Z + " >," ); 
    }
}

Then i use this script to do the movement... (  i have another script that handles sitting etc)

for rotations, i just copy the next waypoint's rotation to the current one? ( makes it rotate in place)

i.e.

curr waypoint :................................................. <262243.10000, 262133.10000, 23.65183>, < 0.0 , 0.0 , 0 >,
curr waypoint with next waypoint's rotation : <262245.10000, 262133.10000, 23.65183>, < 0.0 , 0.0 , -90 >,
next waypoint: .................................................<262245.00000, 262125.50000, 23.65183>, < 0.0 , 0.0 , -90 >,

 

Movement Script

float   Speed = 3.1; // ORIGINAL SPEED 3.1
//####################################################################################################
// DON´T CHANGE ANYTHING BELOW
//####################################################################################################
//               DATA FOR THE ROUTE A TO B 
//     POSITION                             ROTATION

list    Waypoints  = [
<262234.10000, 262122.80000, 23.65183>, < 0.0 , 0.0 , 90 >,
<262234.10000, 262133.10000, 23.65183>, < 0.0 , 0.0 , 0 >,
<262243.10000, 262133.10000, 23.65183>, < 0.0 , 0.0 , 0 >,
<262245.20000, 262133.10000, 23.65183>, < 0.0 , 0.0 , -90 >,
<262245.00000, 262125.50000, 23.65183>, < 0.0 , 0.0 , -90 >,
<262244.40000, 262123.80000, 23.65183>, < 0.0 , 0.0 , -135 >,
<262242.70000, 262123.10000, 23.65183>, < 0.0 , 0.0 , 180 >,
<262234.10000, 262122.80000, 23.65183>, < 0.0 , 0.0 , 180 >,
<262234.10000, 262122.80000, 23.65183>, < 0.0 , 0.0 , 90 >

]; //  End
//####################################################################################################
// DON´T CHANGE ANYTHING BELOW
//####################################################################################################

integer ListLength;
integer Start;
list    Current_route;  
float   Seconds;

calculate_tour()
{
    ListLength = llGetListLength(Waypoints);
    integer Step;
    float dist;
    vector v_now = llGetRegionCorner() + llGetPos();
    float f_temp = 600;
    for(Step = 0; Step < ListLength-1; Step = Step+2)
    {
        if(llVecDist(v_now, (vector)llList2String(Waypoints,Step)) < f_temp)
        {
            f_temp = llVecDist(v_now, (vector)llList2String(Waypoints,Step));
            Start = Step;
        }
    }
    
    if(llList2String(Waypoints,Start+1) == llList2String(Waypoints,Start+3)) Start = Start+2;
    
    for(Step = 0; Step < llGetListLength(Waypoints)-1; Step = Step+2)
    {
        
        integer Calc = Start + Step;
        if(Calc > ListLength-2) Calc = Calc - ListLength;

        vector v1a;//Position
        vector v1b = (vector)llList2String(Waypoints,Calc);
        vector v2a;//Rotation
        vector v2b = (vector)llList2String(Waypoints,Calc + 1);
        
        if(Step == 0)
        {
            v1a = llGetRegionCorner() + llGetPos();
            v2a = llRot2Euler( llGetRot())* RAD_TO_DEG;
        }
        else
        {
            integer ido = Calc;
            if(ido < 0) ido = ido + ListLength;
            v1a = (vector)llList2String(Waypoints,ido-2);
            v2a = (vector)llList2String(Waypoints,ido-1);
                
        }
    
        float distance = llVecDist(v1b, v1a);
        float seconds = distance / Speed;
        if(seconds < 0.45) seconds = 0.45;
        Seconds = Seconds + seconds;
        vector diff_p = v1b - v1a;
        vector diff_r = v2b - v2a;
        Current_route += [diff_p, llEuler2Rot(diff_r* DEG_TO_RAD), seconds];
    }
    Begin();
}
Begin()
{  llSay(0,"\nTour is Departing! \nPlease toggle your AO if sim crossings make you stand\n");
   llLoopSound("3573c7a5-5555-65a8-8c1a-63bd1e445a7a",0.1);
   llSleep( 5 );
   Start_driving();
   // llSetTimerEvent(0.02);
}

Start_driving() 
{
    llMessageLinked(LINK_SET , 100, "fwd", NULL_KEY);
    llSetKeyframedMotion(Current_route,[KFM_MODE,KFM_FORWARD]);
    llSleep(Seconds + 2.0);
    llSay(0,"\nTour resumes in 2 minutes");
    llMessageLinked(LINK_SET , 100, "stopped", NULL_KEY);
    llSetTimerEvent(0.0);
    llSleep(BREAK);
   // llSay(0,"Tour is Departing! \nPlease toggle your AO if sim crossings make you stand");
   
   llResetScript();  // ************* reset this for tour LOOP **************
}

float BREAK = 120;  // number of minutes to pause at DMV IN SECONDS
integer flip = 1;
default
{
     on_rez(integer honk)
    {  llResetScript();
    }
    state_entry() 
    {
        llMessageLinked(LINK_SET , 100, "stopped", NULL_KEY);
        llSetLinkPrimitiveParamsFast( LINK_ROOT,        [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX,
                    PRIM_LINK_TARGET, LINK_ALL_CHILDREN, PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_NONE]);
        llSleep(1); 
        llSetKeyframedMotion([],[KFM_COMMAND,KFM_CMD_STOP]);
        calculate_tour();
       
    }            
    link_message(integer s_link, integer s_chan, string s_msg, key id) 
    {
        if(s_chan == 200)
        {
            if(s_msg == "start") 
            {  Start_driving();
               //llSetTimerEvent(0.02);
            }
        }
    }
      timer()     
    {  
    }
}

 

Edited by Xiija
  • Like 1
Link to comment
Share on other sites

44 minutes ago, Xiija said:

to get the waypoints, I rez a box and put this script in it, then move, rotate and click it..

then I copy the text into my waypoints list and then move to the next waypoint etc...

That's a truly good point, Xiija.  If I'm laying out a path that follows more than a small set of waypoints, I almost always do something like that.  It's less frustrating than doing all the math and probably making mistakes at it. It takes almost no time to simply move a dummy object manually from one waypoint to the next, adjust the rotation, click, record the position and rotation, and move on.

Link to comment
Share on other sites

According to the wiki, "each keyframe is interpreted relative to the previous transform of the object".  

At the moment, unless I misunderstand the initial formula (always a strong possibility) you don't take into account the object's rotation at each step on the itinerary.

I would calculate that at run time,  using 

 rotation r =  llRotBetween(<1,0,0>,llVecNorm(<vTarget.x - vPos.x,vTarget.y - vPos.y,0>)); 

 though I'm not sure why that should make a difference

 

 

Edited by Innula Zenovka
  • Like 1
Link to comment
Share on other sites

I have the way points. I need it to figure out at each way point to figure out if it needs to rotate to point towards the next one, and how much. If it needs to, it will stay in position, rotate, then move to the next way point. If it doesn't need to rotate (if the angle is small enough) it will just move on to the next way point without pausing to rotate

Link to comment
Share on other sites

So, if I understand correctly, you want to rotate the object before it moves to the next waypoint rather than letting KFM rotate it en route?  That's fine. You can still do it empirically, the way that Xiija suggested, instead of doing all the analytical heavy lifting of calculating the angles. Use a version of her script, move a scripted dummy object manually from waypoint to waypoint, and record the rotation at each one.  The KFM rotation will always be the difference between the new rotation and the previous one. If you want to rotate the object before it moves, just do that in its own step in the KFM sequence, and then move.

Link to comment
Share on other sites

ahha, i figured it out i think. can't say i understand it, but it looks like it's working the way i wanted.

list kfm()
{
    list temp = [];
    vector lastpos = llGetPos();
    rotation lastrot = llGetRot();
    integer len = llGetListLength(points);
    integer i;
    for(i = 0; i < len; i++)
    {
        vector nextpos = llList2Vector(points,i);
        float time = llVecDist(nextpos,lastpos)/3;
        vector kfmvec = nextpos-lastpos;
        if(time < mintime)time = mintime;
        rotation rotbet = llRotBetween(<1,0,0>,llVecNorm(<lastpos.x-nextpos.x,lastpos.y-nextpos.y,0>));
        float rottime = llRot2Angle(rotbet)*4;//calculates the angle * 4 to determine how long the rotation should take
        if(rottime < mintime)rottime = mintime;
        temp += [ZERO_VECTOR,rotbet/lastrot,rottime];//subtracts the new rotation from the last rot to determine how much to rotate on this from
        temp += [kfmvec,ZERO_ROTATION,time];
        lastpos = nextpos;
        lastrot = rotbet;//last rot becomes rotation calculated above
    }
    return temp;

 

Edited by Ruthven Willenov
  • Like 2
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 2185 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...