Ruthven Ravenhurst Posted May 13, 2018 Share Posted May 13, 2018 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 More sharing options...
Rolig Loon Posted May 13, 2018 Share Posted May 13, 2018 (edited) 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 May 13, 2018 by Rolig Loon Link to comment Share on other sites More sharing options...
Ruthven Ravenhurst Posted May 13, 2018 Author Share Posted May 13, 2018 They're all the same elevation. I'll take a look at the link you provided and see if that helps Link to comment Share on other sites More sharing options...
Xiija Posted May 13, 2018 Share Posted May 13, 2018 (edited) 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 May 13, 2018 by Xiija 1 Link to comment Share on other sites More sharing options...
Rolig Loon Posted May 13, 2018 Share Posted May 13, 2018 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 More sharing options...
Innula Zenovka Posted May 13, 2018 Share Posted May 13, 2018 (edited) 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 May 13, 2018 by Innula Zenovka 1 Link to comment Share on other sites More sharing options...
Ruthven Ravenhurst Posted May 13, 2018 Author Share Posted May 13, 2018 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 More sharing options...
Rolig Loon Posted May 13, 2018 Share Posted May 13, 2018 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 More sharing options...
Ruthven Ravenhurst Posted May 13, 2018 Author Share Posted May 13, 2018 (edited) 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 May 13, 2018 by Ruthven Willenov 2 Link to comment Share on other sites More sharing options...
Recommended Posts
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