Getting the orientation in degrees of an Oriented Point in Oracle - oracle

In my database I have some Oriented Point type geometries.
For example:
{3001,4326,null,{1,1,1,4,1,0},{32.4302549,37.5066298,0,0.16,-0.92,0}}
If I'm correct, my gps coordinates are
lat: 32.4302549, lon: 37.5066298
and the virtual point determining the orientation is a Point(0.16 -0.92 0)
I would like to get the orientation in degrees or radians using a query.
So far I can extract the orientation point:
SELECT SDO_UTIL.GET_COORDINATE(MY_GEOMETRY_COLUMN, 2) as orientation_vector
FROM GCOL;
But don't know how to get the orientation. I know it can be calculated vie arctan2 function, but don't know the correct oracle syntax.

You need to use ATAN2 to get radians with the correct quadrant.
WITH X AS (
SELECT
SDO_GEOMETRY(3001,4326,NULL,
SDO_ELEM_INFO_ARRAY(1, 1, 1, 4, 1,0),
SDO_ORDINATE_ARRAY(32.4302549, 37.5066298, 0, 0.16, - 0.92,0)) AS G
FROM DUAL
)
SELECT
ATAN2(
SDO_UTIL.GET_COORDINATE(G, 2).SDO_POINT.Y ,
SDO_UTIL.GET_COORDINATE(G, 2).SDO_POINT.X)
FROM X;
To convert to degrees please see SDO_UTIL.CONVERT_UNIT .

Based on #David Lapp's answer, I'm posting a solution which works for me. In my application I need 0 degrees to point upwards. The correct order of parameters to the ATAN2() function is first X, then Y.
I converted the result to degrees and rounded to 2 decimal points.
WITH X AS (
SELECT MY_GEOMETRY_COLUMN as G
from MY_GEOMETRY_TABLE
)
SELECT ROUND(SDO_UTIL.CONVERT_UNIT(
ATAN2(
SDO_UTIL.GET_COORDINATE(G, 2).SDO_POINT.X,
SDO_UTIL.GET_COORDINATE(G, 2).SDO_POINT.Y),
'Radian', 'Degree'),
2) as orientation;

Related

Inverse Camera Intrinsic Matrix for Image Plane at Z = -1

A similar question was asked before, unfortunately I cannot comment Samgaks answer so I open up a new post with this one. Here is the link to the old question:
How to calculate ray in real-world coordinate system from image using projection matrix?
My goal is to map from image coordinates to world coordinates. In fact I am trying to do this with the Camera Intrinsics Parameters of the HoloLens Camera.
Of course this mapping will only give me a ray connecting the Camera Optical Centre and all points, which can lie on that ray. For the mapping from image coordinates to world coordinates we can use the inverse camera matrix which is:
K^-1 = [1/fx 0 -cx/fx; 0 1/fy -cy/fy; 0 0 1]
Pcam = K^-1 * Ppix;
Pcam_x = P_pix_x/fx - cx/fx;
Pcam_y = P_pix_y/fy - cy/fy;
Pcam_z = 1
Orientation of Camera Coordinate System and Image Plane
In this specific case the image plane is probably at Z = -1 (However, I am a bit uncertain about this). The Section Pixel to Application-specified Coordinate System on page HoloLens CameraProjectionTransform describes how to go form pixel coordinates to world coordinates. To what I understand two signs in the K^-1 are flipped s.t. we calculate the coordinates as follows:
Pcam_x = (Ppix_x/fx) - (cx*(-1)/fx) = P_pix_x/fx + cx/fx;
Pcam_y = (Ppix_y/fy) - (cy*(-1)/fy) = P_pix_y/fy + cy/fy;
Pcam_z = -1
Pcam = (Pcam_x, Pcam_y, -1)
CameraOpticalCentre = (0,0,0)
Ray = Pcam - CameraOpticalCentre
I do not understand how to create the Camera Intrinsics for the case of the image plane being at a negative Z-coordinate. And I would like to have a mathematical explanation or intuitive understanding of why we have the sign flip (P_pix_x/fx + cx/fx instead of P_pix_x/fx - cx/fx).
Edit: I read in another post that the thirst column of the camera matrix has to be negated for the case that the camera is facing down the negative z-direction. This would explain the sign flip. However, why do we need to change the sign of the third column. I would like to have a intuitive understanding of this.
Here the link to the post Negation of third column
Thanks a lot in advance,
Lisa
why do we need to change the sign of the third column
To understand why we need to negate the third column of K (i.e. negate the principal points of the intrinsic matrix) let's first understand how to get the pixel coordinates of a 3D point already in the camera coordinates frame. After that, it is easier to understand why -z requires negating things.
let's imagine a Camera c, and one point B in the space (w.r.t. the camera coordinate frame), let's put the camera sensor (i.e. image) at E' as in the image below. Therefore f (in red) will be the focal length and ? (in blue) will be the x coordinate in pixels of B (from the center of the image). To simplify things let's place B at the corner of the field of view (i.e. in the corner of the image)
We need to calculate the coordinates of B projected into the sensor d (which is the same as the 2d image). Because the triangles AEB and AE'B' are similar triangles then ?/f = X/Z therefore ? = X*f/Z. X*f is the first operation of the K matrix is. We can multiply K*B (with B as a column vector) to check.
This will give us coordinates in pixels w.r.t. the center of the image. Let's imagine the image is size 480x480. Therefore B' will look like this in the image below. Keep in mind that in image coordinates, the y-axis increases going down and the x-axis increases going right.
In images, the pixel at coordinates 0,0 is in the top left corner, therefore we need to add half of the width of the image to the point we have. then px = X*f/Z + cx. Where cx is the principal point in the x-axis, usually W/2. px = X*f/Z + cx is exactly as doing K * B / Z. So X*f/Z was -240, if we add cx (W/2 = 480/2 = 240) and therefore X*f/Z + cx = 0, same with the Y. The final pixel coordinates in the image are 0,0 (i.e. top left corner)
Now in the case where we use z as negative, when we divide X and Y by Z, because Z is negative, it will change the sign of X and Y, therefore it will be projected to B'' at the opposite quadrant as in the image below.
Now the second image will instead be:
Because of this, instead of adding the principal point, we need to subtract it. That is the same as negating the last column of K.
So we have 240 - 240 = 0 (where the second 240 is the principal point in x, cx) and the same for Y. The pixel coordinates are 0,0 as in the example when z was positive. If we do not negate the last column we will end up with 480,480 instead of 0,0.
Hope this helped a little bit

Point look at Point

So I have one point in 3D space, and I have location and rotation of the Camera in 3D space.
So basically there is Vector3 on the object.
Camera Vector3 and Quaternion.
I need to get how to look at that point.
I want to tell user how to move to that point.
Should user direct camera left or right or behind?
One way to do this is to calculate the direction the camera is currently facing as a yaw angle (like a compass heading), and calculate the direction it needs to face in order to be looking at the point.
Subtract one from the other and adjust the result so that it is in the range of -180 to 180 degrees (or -pi to pi radians) and then tell the user to turn left or right based on the sign. If the absolute value is more than 120 degrees (or some configurable value) then tell them it is behind them.
To find the camera's current heading, transform the vector (0, 0, 1) by the quaternion to get the forward vector, then calculate the heading using atan2(forward.z, forward.x).
To calculate the heading required to look at the point, subtract the current camera position from the point to get a desired forward vector and then pass to atan:
Vector3 desired_forward = point - camera_pos;
float desired_heading = atan2(desired_forward.z, desired_forward.x);
Then find the rotation needed:
float rotation_needed = desired_heading - heading;
if(rotation_needed > Math.PI)
rotation_needed -= 2 * Math.PI;
if(rotation_needed < -Math.PI)
rotation_needed += 2 * Math.PI;
Now tell the user to rotate left or right based on the sign of the rotation needed.
If you want to do it for look up/down, you can calculate a pitch angle by first calculating the length of the forward vector in the XZ plane and then using atan2 again:
float xzLength = sqrt(forward.x * forward.x + forward.z * forward.z);
float pitch_angle = atan2(forward.y, xzLength);
Do the same for the desired forward vector and subtract the current from the desired. Check the sign to tell the user whether to look up or down.
There's a few likely complications. For example, depending on whether the camera quaternion specifies the transform from world space to camera space or vice versa, you might need to negate the calculated camera heading.

GLKit quaternion code not agreeing with matrix code?

I must be misunderstanding something about GLKit's handling of quaternions and rotation matrices. In the following snippet, I would expect matrices a and b to end up with identical contents (subject to floating point errors)...
GLKQuaternion q = GLKQuaternionMakeWithAngleAndAxis(M_PI / 2, 1, 1, 1);
GLKMatrix3 a = GLKMatrix3MakeWithQuaternion(q);
GLKMatrix3 b = GLKMatrix3MakeRotation(M_PI / 2, 1, 1, 1);
However, they don't agree. Not even close. In column major order, the arrays contain...
a.m[0]=0.000000 b.m[0]=0.333333
a.m[1]=1.000000 b.m[1]=0.910684
a.m[2]=0.000000 b.m[2]=-0.244017
a.m[3]=0.000000 b.m[3]=-0.244017
a.m[4]=0.000000 b.m[4]=0.333333
a.m[5]=1.000000 b.m[5]=0.910684
a.m[6]=1.000000 b.m[6]=0.910684
a.m[7]=0.000000 b.m[7]=-0.244017
a.m[8]=0.000000 b.m[8]=0.333333
I thought that both GLKQuaternionMakeWithAngleAndAxis and GLKMatrix3MakeRotation each took radians, x, y, z in order to represent a rotation of the specified radians around the specified axis. And I thought that GLKMatrix3MakeWithQuaternion was intended to convert from the quaternion representation to the matrix representation.
So, why don't those agree? Do I need to normalize the axis before the quaternion creation? This does, in fact, seem to fix the problem but I don't believe it is documented that way.
From GLKQuaternion.h
/*
Assumes the axis is already normalized.
*/
static inline GLKQuaternion GLKQuaternionMakeWithAngleAndAxis(float radians, float x, float y, float z);
So yes, you do need to normalize the axis before creating the quaternion.

Collision detection for rotated rectangles with coordinate math

I am aware that there are other solutions to this problem, but I am learning and for that purpose would like to understand why my algorithm doesn't work
Here is how my solution works:
It gets the coordinates for the 4 vertices of each rectangle, translates them so they are relative to 0, 0 rather than the rectangles' origins, and rotates them respectively using these formulas:
rotatedX = unrotatedX * cos( radiansOfCounterClockwiseRotation ) -
unrotatedY * sin( radians );
and
rotatedY = unrotatedX * sin( radians ) + y * cos( radians );
and translates them so they are relative to their rectangles' origins
Then it calculates x and y values of the axis to compare separation on by subtracting the upper left, and lower right vertices' coordinates from those of the upper right vertice, for a total of 4 axis (1 for each pair of parallel edges of the 2 rectangles)
Then it calculates an x value for each of the rotated vertices, which lies on the axis, using this formula:
x = -( -( axis.x / axis.y ) * vertice.x - vertice.y ) /
( axis[i].y / axis[i].x + axis[i].x / axis[i].y );
which is derived from getting the point of intersection between the axis line and the line perpendicular to the axis that passes through the vertice
It compares these values for each axis and checks whether:
maxXValueForRect0 >= minXValueForRect1 AND minXValueForRect0 <= maxXValueForRect1;
if that is true for every axis, then there is a collision
However, during debugging I discovered that the min x values area always lower than the max x values, regardless of positions and sizes of the rectangles
Can anyone tell me what is wrong here?
This works perfectly and I made an intensely minor error in my code itself that caused both groups of vertices to be translated relative to the first rectangle after their rotation. So the logic presented here is solid and will work provided you don't make a silly mistake like I did :D

Spatial Rotation in Gmod Expression2

I'm using expression2 to program behavior in Garry's mod. Expression2 (archive link)
Okay so, to set the precedent. In Gmod I have a block and I am at a complete loss of how to get it to rotate around the 3 up, down and right vectors (Which are local. ie; if I pitch it 45 degrees the forward vector is 0.707, 0.707, 0). Essentially, From the 3 vectors I'd like to be able to get local Pitch/Roll/Yaw. By Local Pitch Roll Yaw I mean that they are completely independent of one another allowing true 3d rotation. So for example; if I place my craft so its nose is parallel to the floor the X,Y,Z would be 0,0,0. If I turn it parallel to the floor (World and Local Yaw) 90 degrees it's now 0, 0, 90. If I then pitch it (World Roll, Local Pitch) it 180 degrees it's now 180, 0, 90. I've already explored quaternions however I don't believe I should post my code here as I think I was re-inventing the wheel.
I know I didn't explain that well but I believe the problem is pretty generic. Any help anyone could offer is greatly appreciated.
Oh, I'd like to avoid gimblelock too.
Essentially calculating the rotation around each of the crafts up/forward/right vectors using the up/forward/right vectors.
To simply the question a generic implementation rather than one specific to Gmod is absolutely fine.
I'm not sure what the application you are looking forward to implementing, however, in this sort of situation, I would usually suggest applying angular force. Would that be sufficient for your needs in this regard?
Well if that is all that you need, then i have managed to perfect the angular force equation to having entities point at a given position.
EntityVector = Entity:massCenter()
Leverage = sqrt( ( Entity:inertia():length()^2 ) / 3 )
LookPos = EntityVector - Target:pos()
A = ang(
toDeg( atanr( LookPos:z() , sqrt( LookPos:x()^2 + LookPos:y()^2) ) ) ,
toDeg( atanr( -LookPos:y(), -LookPos:x() ) ) ,
0 )
EntityAngle = ( ( Entity:angles() - angnorm(A) ) * 5 + Entity:angVel() ) * 5
Entity:applyAngForce( -EntityAngle * Leverage )
This set of equations has helped me through countless projects

Resources