Jump to content

trigonometry: find perpendicular to arbitrary axis defined by rotation


Judy Hynes
 Share

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

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

Recommended Posts

I'm stuck on a problem trying to do some trig and I just can't get it.  Hopefully someone here can help me work through it.

The problem: I want to figure out the angle of displacement to a target discovered in a sensor call.  I run the sensor, find the target's position, and now I want to know its angle from the center line (the local x-axis) used by sensor.  Actually, I want to know two angles: the angle from center in both the horizontal and vertical planes.

I figured out the vertical angle correctly I think.  I can find how much the target is vertically angled up (or down) from the center line based making a vertical right triangle.  I can do this easily because I can find the opposite side of the triangle by just examining the height (z-axis coordinate) of the target relative to the sensor's position.  But I'm stuck trying to do the same in the horizontal plane, since the local x-axis is based on the orientation of the prim containing the script and not necessarily aligned with any of the region axes.  It's probably clearer to take a look at my sample code at this point.

float SENSOR_ARC_DEGREES = 20.0;
float SENSOR_RANGE = 30.0;

float find_vertical_angle_from_center(vector my_pos, vector target_pos)
{
	// right triangle has hypotenuse that is distance between the two points
	float hyp = llVecDist(my_pos, target_pos);
	
	// right triangle has opposite side that is vertical (z-axis) distance between the two points
	float opp = llFabs(my_pos.z-target_pos.z);
	
	// Angle x:    sin(x) = opp/hyp;    x = arcsin(opp/hyp);
	return llAsin(opp/hyp);
}

float find_horizontal_angle_from_center(vector my_pos, vector target_pos, rotation my_rot)
{
	// translate the target position into the xy-plane
	vector target_xy_plane_pos = <target_pos.x, target_pos.y, my_pos.z>;
	
	// right triangle has hypotenuse that is distance between the two points in xy-plane
	float hyp = llVecDist(my_pos, target_xy_plane_pos);
	
	// STUCK HERE
	// How do I get the opposite side, which forms a perpendicular to local x-axis used in sensor call?
	// I guess I will need the rotation, but I don't know how to calculate where the perpendicular is. 
}

default
{
    on_rez(integer p)
	{
		llSensor("", NULL_KEY, AGENT, SENSOR_RANGE, SENSOR_ARC_DEGREES*DEG_TO_RAD);
	}
	
	sensor(integer num_detected)
	{
		rotation my_rot = llGetRot();
		vector my_pos = llGetPos();
		vector target_pos = llDetectedPos(0);
		
		float angle_vert = find_vertical_angle_from_center(my_pos, target_pos)*RAD_TO_DEG;
		float angle_horiz = find_horizontal_angle_from_center(my_pos, target_pos, my_rot)*RAD_TO_DEG;
		
		llSay(0, "Vertical angle (degrees): "+(string)angle_vert);
		llSay(0, "Horizontal angle (degrees): "+(string)angle_horiz);
	}
}

So you can see I'd like to do the same right triangle math for horizontal plane that I did for vertical, but I don't know how to find the opposite side as I did in the vertical calculation.  Can anyone give me any pointers? 

NOTE: I'm only interested in the magnitude of the angle (I don't care if it's up/down or left/right) so that's why I used absolute value in the vertical calculation.

 

Link to comment
Share on other sites

1 hour ago, Judy Hynes said:

I'm only interested in the magnitude of the angle

So, I only skimmed your post, but in SL, there are only 2 functions you need for 99% of all "how do I find this angle" problems.

The 3 dimensional case is actually very simple. If you have 2 vectors, A and B, the angle between them can be found by

llRot2Angle(llRotBetween(A,B));

easy as that. This will always give a positive angle though. (you can find the "direction" of the angle by playing with the cross product)

 

For angles on a 2d plane, things actually get a bit more annoying, but the function you want to learn to understand is llAtan2(y,x); Assuming you have two 2-dimensional vectors, on the x,y plane the angle between them should be:

// angle a to b on the x-y plane
llAtan2(b.y,b.x)-llAtan2(a.y,a.x);

you could do similarly with the x-z plane.

  • Like 2
Link to comment
Share on other sites

Ah great that's what I needed.  I'll have to play with the llAtan2 to understand how it works.  I decided to start with just the "whole angle" not broken into horizontal and vertical components.  As an example to anyone who wants to play around with it, here is my test script.  Put it in a prim, enter mouselook, press left mouse button with some other av nearby to try it out.

float SENSOR_ARC_DEGREES = 180.0;
float SENSOR_RANGE = 90.0;

default
{
    attach(key id)
    {
        if(id != NULL_KEY)
        {
            llRequestPermissions(llGetOwner(), PERMISSION_TRACK_CAMERA|PERMISSION_TAKE_CONTROLS);
        }
    }

    run_time_permissions(integer perm)
    {
        if(!(perm & PERMISSION_TRACK_CAMERA))
        {
            llOwnerSay("Failed to get camera permissions");
        }
        else if(perm & PERMISSION_TAKE_CONTROLS)
        {
            llTakeControls(CONTROL_ML_LBUTTON, TRUE, TRUE);
        }
        else
        {
            llOwnerSay("Failed to get control permissions");
        }
    }
    
    control(key agt, integer hld, integer chg)
    {
        if(hld&chg)
        {
            llSensor("", NULL_KEY, AGENT, SENSOR_RANGE, SENSOR_ARC_DEGREES*DEG_TO_RAD);
        }
    }
    
    sensor(integer num_detected)
    {
        rotation my_rot = llGetRot();
        vector my_pos = llGetPos();
        vector sensor_center_line = <SENSOR_RANGE, 0.0, 0.0>*my_rot;
        
        integer i=0;
        for(; i<num_detected; ++i)
        {
            vector target_pos = llDetectedPos(i);
            vector target_line = target_pos - my_pos;
            
            float angle = llRot2Angle(llRotBetween(sensor_center_line, target_line));
            
            llSay(0, "Angle to target "+llDetectedName(i)+" is "+(string)angle+" ("+(string)(angle*RAD_TO_DEG)+" degrees)");
        }
    }
}

 

  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 949 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...