# Problem regarding rotational conversion

## Recommended Posts

Hello LSL scripting forum. I recently ran into a math issue that for some reason, I can not figure out for the life of me, but perhaps it is a very simple one.

First, let me explain what I am looking to create:
The plan is to make an object which moves as a vehicle, and turns via llRotLookAt(), and checks what is infront of itself via llCastray(). To simplify the model, I wanted to treat the direction the vehicle is facing as an angle around the world Z axis, aka a simple top-down view. Thus, I am using llAxisAngle2Rot() to cast a ray in a certain direction, as well as to rotate the object in a certain rotation. I should also mention, for the purpose of llRotLookat() to work at all, the object is rotated so the local Z axis points forward now, and positive X points down (as per the criteria of llRotLookat()'s orientation).

The problem begins when i want to make the object turn away a certain angle from obstacles to try and navigate around them. At some point, I need to know the current angle of the object around its Z axis and properly modify it. But try as I might, the math I try only produces garbage at worst, and random results at best. For the purpose of easier troubleshooting, I created a tiny script to experiment in. I rotated a prim 90° around it's Y axis - like the "vehicle" I am creating, and dropped in this short script:

```default
{
touch_start(integer total_number)
{
vector vec  = <0, 0, 1> * llGetRot();
float angle = llAtan2(vec.x, vec.y) * RAD_TO_DEG;
llOwnerSay((string)angle);
vector pos = llGetPos() + (<2, 0, 0> * llAxisAngle2Rot(<0, 0, 1>, angle * DEG_TO_RAD));

llRezObject("target", pos, ZERO_VECTOR, ZERO_ROTATION, 0);
}
}```

This is as close as I have gotten to a working script. It works for some facings, but not for others, putting it on a seemingly random offset of either 45, 90, or 180 degrees to where the prim's local Z axis is pointing.

I know I must be making some mistake as far as either the obtaining or setting of the angle goes, but I can not for the life of me figure out what.

Anyone willing to offer some insight is welcome, my web research so far hasn't yielded anything useful. FYI, the object target is just a small object used as marker in relation to where the original prim's local Z axis should be pointing at.

The goal is to correctly rez the object at the correct angle of the prim`s world Z axis, regardless of all axis' orientations. Aka treat the prim as if it only had a top-down 2D existance, nothing else.

##### Share on other sites

That's a error in the llGetRot, I have found that to, seems at the compass point it is right till it goes over the 90 degree point then has the results from 180 degrees away, I think this is the gimbal affect, I am not sure what your trying to do, but llGetCameraRot() does not have these errors, also I don't like the line

vector pos = llGetPos() + (<2, 0, 0> * llAxisAngle2Rot(<0, 0, 1>, angle * DEG_TO_RAD));

I would put

vector pos = llGetPos() + <2, 0, 0> * llAxisAngle2Rot(<0, 0, 1>, angle * DEG_TO_RAD);

but I have always done it that way, what your doing is not multiplying the llGetPos with the rotation, whereas I would but that's just me, with me it is trial and error, I have always managed to fix it, but I did once go though something similar to you with garbage at certain points.

##### Share on other sites

That can be a tricky problem.  You might try either of Void Singer's snippets in the wiki at http://wiki.secondlife.com/wiki/LlRotLookAt and http://wiki.secondlife.com/wiki/LlLookAt . She's using a slerp routine that makes for a nice smooth rotation and avoids most of the side issues that you are probably experiencing.  I've used both very successfully in similar situations.

##### Share on other sites

well, the actual llRotLookAt() isn't the problem at all though, I'm afraid.

The problem is turning a 3D rotation into the z-axis rotation angle, and turning this angle back into a rotation, for various functions I use (lookats, raycasting etc).

The math does seem to have considerable issues with the gimbal system, so I'm hoping for input on how to do the math the right way.

##### Share on other sites

I am a bit confused about what you're trying to do, not least because I think you're confusing llRotLookAt -- which points the x axis in the direction you want -- with llLookAt.

If you simply want to turn the object 90 degrees on its own z axis (the equivalent to rotating it with the edit tools and the ruler in local mode) this is all you need:

`rotation z90;default{    state_entry()    {        z90=llEuler2Rot(<0.0,0.0,90.0>*DEG_TO_RAD);    }    touch_start(integer total_number)    {        llRotLookAt(z90*llGetRot(),0.2,0.2);    }}`

If you want to turn it 90 degrees on the vertical relative to the sim (equivalent to having the ruler in world mode) then you want

`rotation z90;default{    state_entry()    {        z90=llEuler2Rot(<0.0,0.0,90.0>*DEG_TO_RAD);    }    touch_start(integer total_number)    {        llRotLookAt(llGetRot()*z90,0.2,0.2);    }}`

I realise this probably isn't exactly what you're looking for, but it should point you in the right direction, as it were.

ETA

I've just read what was posted while I was writing this, and I'm even more confused.

You see an obstacle directly in front of you.. you want to avoid it.  Thinking of what I would do I was driving a car, I'd want to turn left, or turn right.

How far left or right I'd want to turn would depend on how large the obstacle was and how far away it was (and how fast I was going), which I don't think we know from your calculations yet.

##### Share on other sites

ah, let me try and break it down a bit more then.

What I'm trying to do is a vehicle which turns via llRotLookAt(current angle + turning angle). and it casts a ray along the angle it is currently facing. however, i want it to be treated as if it were moving on the XY plane exclusively to simplify the movement. aka to not cast a ray upward when it travels uphill for instance.

for this, i need the current angle around the world z axis - so i can use llAxisAngle2Rot(<0, 0, 1> * angle);  to do an llCastRay infront of where the object is traveling.

The entire rest of the code is standing and seems to do as it should. The mathematical issues that remain is:

• How can I turn any random x/y/z rotation into JUST the Z axis angle?
• How can I SET this angle reliably? There seem to be a lot of flips going on when reaching certain angles

##### Share on other sites

Not that it makes any difference, but as a side note..... you are getting the angle with llAtan2 and converting it from radians to degrees and then immediately back again.  I assume that's because you want to know what that angle is during testing, but in the long run you probably don't want to do that.  Also, note that llAtan2 behaves almost like arctan(angle), except that it is constrained not to hit a singularity at 0 and 90 degrees, so you shouldn't hit any division by zero problems there.  The arithmetic sign of the result tells you what quadrant you are in.

##### Share on other sites

I'm probably missing the point, but what's wrong with this:

`llCastRay(llGetPos(),llGetPos()+<10.0,0.0.0.0>*llGetRot,[some options]);`

That's effectively me driving with a spotlight focussed straight ahead of me, in the direction my car is going, whether I'm on a level surface, or going up or downhill.   Isn't that what you want?

Then if I see something caught in my spotlight, I turn 90 degrees to avoid it, on my car's local z axis (otherwise, if I'm on a slope, I'm going to be trying to bury one end or the other of the car in the ground), so I use

`rotation z90;default{    state_entry()    {        z90=llEuler2Rot(<0.0,0.0,90.0>*DEG_TO_RAD);    }    touch_start(integer total_number)    {        llRotLookAt(z90*llGetRot(),0.2,0.2);    }}`

There seems to be a problem that's obvious to everyone but me.

##### Share on other sites

Well, the above solution seems simple, but it also rotates the ray around the X and Y axes. The issue with that is that I don't want to say, cast a ray uphill into the sky when I travel uphill, neither do I want to llRotLookat() above or below the height I am currently at. That is why I wanted to simplify the entire process into the X/Y plane, so I could model the current facing of my "vehicle" as a simple float, being the world Z rotation.

It has several reasons, one is simplicity, the other is the ability to simply rotate the object by modifying one variable, or being able to say, cast two rays instead of one, one slightly off to the left, one off to the right, to get a better idea of where the obstacle is at and react in a more granular way.

edit:

There is another important factor. Due to me using llRotLookAt(), the vehicle's Z axis is pointing forward, and positive X is pointing down, aka the vehicle is rotated +90° on the Y axis. This would make raycasting based on the object's rotation tricky, because imho they would just be cast into the ground that way? Unless I am seriously getting my math wrong. These last days of trying to figure it out haven't been kind on my brain at times.

##### Share on other sites

I don't know where you get the idea from the llRotLookAt tries to point the Z axis forward, I really don't.   I think you are confusing it with llLookAt.

But I can assure you, that if you rez a cube, colour face 2 (the forward facing X face) red, and then drop in

`rotation z90;default{    state_entry()    {        z90=llEuler2Rot(<0.0,0.0,90.0>*DEG_TO_RAD);    }    touch_start(integer total_number)    {        llRotLookAt(llGetRot()*z90,0.2,0.2);    }}`

and touch it, you will see what I mean.

Now, I may be mistaken but I think what you're trying to do is something like this:

If I have correctly understood you, you want to cast the ray in the direction my red arrow is going, up the slope. To do that, you use

`llCastRay(llGetPos(),llGetPos()+<10.0,0.0.0.0>*llGetRot,[some options]);`

You started by talking about rezzing things to get an idea what's happening.   The second picture shows what happened when I put

`rotation z90;default{    state_entry()    {        z90=llEuler2Rot(<0.0,0.0,90.0>*DEG_TO_RAD);    }    touch_start(integer total_number)    {       llRezAtRoot(llGetInventoryName(INVENTORY_OBJECT,0),llGetPos()+<2.0,0.0,0.0>*llGetRot(),ZERO_VECTOR,llGetRot(),0);    }}`

into my white cube and touched it.   Then I rotated it a bit around its local Z axis (indicated by the blue pole) and rezzed another cube from it:

It might be clearer from another angle:

ETA -- corrected the formula below.. sorry.. copy-pasted the wrong thing

And, as I said above, if you want to rotate the cube by script, around the blue pole, you use

` llRotLookAt(z90*llGetRot(),0.2,0.2);`

Or am I misunderstanding what you want to do?

##### Share on other sites

First of all llRotLookAt points the X-axis forward and llLookAt points the Z-axis forward,
it is confusing but you are not right here.

Next I think you should consider llAxes2Rot() which can be used to convert any vector (any direction) to a rotation confined to the XY plane:

`rotation Vec2RotHor( vector V ){    V = llVecNorm( V );    vector UP = < 0.0, 0.0, 1.0 >;    vector LEFT = llVecNorm(UP%V);    V = llVecNorm(LEFT%UP); // you want V confined to the horizontal plane    return llAxes2Rot(V, LEFT, UP);}`

This routine is taken from the Visual Illustration found with llAxes2Rot

I have a feeling you want to reduce the problem to two dimensions because you feel safe with the plane geometry and sin, cos and tan.
It is my experience though that doing this is not a way to simplify matters, on the contrary.
Trigonometry is not very useful in space.
I find the rotational functions build into LSL much more powerful

##### Share on other sites

hmm I will have to think on this some more again, thanks for the answers so far. maybe I was indeed overthinking some of the things here, and I will take another look into the scripting and see if I can't actually work it in the simple ways you have suggested.

thanks again for the help by the way, the pictures especially have helped me quite a bit, along with the examples. My initial idea for reducing the interaction to the XY plane was that i only would be dealing with one value i could throw into various self-made functions, but i do tend to sometimes overthink simple solutions and make a complex construct instead.

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.