Adjust camera co-ordinates to represent change in azimuth, elevation and roll values - qt

I'm currently working with libQGLViewer, and I'm receiving a stream of data from my sensor, holding azimuth, elevation and roll values, 3 euler angles.
The problem can be considered as the camera representing an aeroplane, and the changes in azimuth, elevation and roll the plane moving.
I need a general set of transformation matrices to transform the camera point and the up vector to represent this, but I'm unsure how to calculate them since the axis to rotate about changes after each rotation ( I think? ).
Either that, or just someway to pass the azimuth, elevation, roll values to the camera and have some function do it for me? I understand that cameraPosition.setOrientation(Quaterion something) might work, but I couldn't really understand it. Any ideas?

For example you could just take the three matrices for rotation about the coordinate axes, plug in your angles respectively, and multiply these three matrices together to get the final roation matrix (but use the correct multiplication order).
You can also just compute a quaternion from the euler angles. Look here for ideas. Just keep in mind that you always have to use the correct order of the euler angles (whatever your three values mean), perhaps with some experimentation (those different euler conventions always make me crazy).
EDIT: In response to your comment: This is accounted by the order of rotations. The matrices applied like v' = XYZv correspond to roation about z, unchanged y and then unchanged x, which is equal to x, y' and then z''. So you have to keep an eye on the axes (what your words like azimuth mean) and the order in which you rotate about these axes.

Related

Understanding Angular velocities and their application

I recently had to convert euler rotation rates to vectorial angular velocity.
From what I understand, in a local referential, we can express the vectorial angular velocity by:
R = [rollRate, pitchRate, yawRate] (which is the correct order relative to the referential I want to use).
I also know that we can convert angular velocities to rotations (quaternion) for a given time-step via:
alpha = |R| * ts
nR = R / |R| * sin(alpha) <-- normalize and multiply each element by sin(alpha)
Q = [nRx i, nRy j, nRz k, cos(alpha)]
When I test this for each axis individually, I find results that I totally expect (i.e. 90°pitch/time-unit for 1 time unit => 90° pitch angle).
When I use two axes for my rotation rates however, I don't fully understand the results:
For example, if I use rollRate = 0, pitchRate = 90, yawRate = 90, apply the rotation for a given time-step and convert the resulting quaternion back to euler, I obtain the following results:
(ts = 0.1) Roll: 0.712676, Pitch: 8.96267, Yaw: 9.07438
(ts = 0.5) Roll: 21.058, Pitch: 39.3148, Yaw: 54.9771
(ts = 1.0) Roll: 76.2033, Pitch: 34.2386, Yaw: 137.111
I Understand that a "smooth" continuous rotation might change the roll component mid way.
What I don't understand however is after a full unit of time with a 90°/time-unit pitchRate combined with a 90°/time-unit yawRate I end up with these pitch and yaw angles and why I still have roll (I would have expected them to end up at [0°, 90°, 90°].
I am pretty confident on both my axis + angle to quaternion and on my quaternion to euler formulas as I've tested these extensively (both via unit-testing and via field testing), I'm not sure however about the euler rotation rate to angular-velocity "conversion".
My first bet would be that I do not understand how euler rotation-rates axes interacts on themselves, my second would be that this "conversion" between euler rotation-rates and angular velocity vector is incorrect.
Euler angles are not good way of representing arbitrary angular movement. Its just a simplification used for graphics,games and robotics. They got some pretty hard restrictions like your rotations consist of only N perpendicular axises in ND space. That is not how rotation works in real world. On top of this spherical representation of reper endpoint it creates a lot of singularities (you know when you cross poles ...).
The rotation movement is analogy for translation:
position speed acceleration
pos = Integral(vel) = Integral(Integral(acc))
ang = Integral(omg) = Integral(Integral(eps))
That in some update timer can be rewritten to this:
vel+=acc*dt; pos+=vel*dt;
omg+=eps*dt; ang+=omg*dt;
where dt is elapsed time (Timer interval).
The problem with rotation is that you can not superimpose it like translation. As each rotation has its own axis (and it does not need to be axis aligned, nor centered) and each rotation affect the axis orientation of all others too so the order of them matters a lot. On top of all this there is also gyroscopic moment creating 3th rotation from any two that has not parallel axis. Put all of this together and suddenly you see Euler angles does not match the real geometrics/physics of rotation. They can describe orientation and fake its rotation up to a degree but do not expect to make real sense once used for physic simulation.
The real simulation would require list of rotations described by the axis (not just direction but also origin), angular speed (and its change) and in each simulation step the recomputing of the axis as it will change (unless only single rotation is present).
This can be done by using coumulative homogenous transform matrices along with incremental rotations.
Sadly the majority of programmers prefers Euler angles and Quaternions simply by not knowing that there are better and simpler options and once they do they stick to Euler angles anyway as matrix math seem to be more complicated to them... That is why most nowadays games have gimbal locks, major rotation errors and glitches, unrealistic physics.
Do not get me wrong they still have their use (liek for example restrict free look for camera etc ... but they missused for stuff they are the worse option to use for.

Calculate forward and up vectors from euler position and rotation?

I have an object in 3D space where all I have is a euler position and rotation. How can I calculate forward and up vectors from the information I have?
I know that I can calculate the forward vector in this way:
Vector3 forward = (target.getPosition() - object.getPosition()).normalize();
.. where target is any point along the axis which the object is looking. Using the information I have, how can I pick an arbitrary point in this way to normalize?
I'm not sure how to go about solving the "up" vector at all.
First create a transform matrix from your euler angles (with the same method as you are using while rendering). Then extract the axises vectors for forward and up from it directly. For example my view matrices uses Z axis for forward/backward and X axis for left/right so I would just use those two. You will find the location of the vectors here:
Understanding 4x4 homogenous transform matrices

3d rotation around the origin

I know there are plenty of questions about 3d rotation that have been answered here but all of them seem to deal with rotational matrices and quaternions in OpenGL (and I don't really care if I get gimbal lock). I need to get 3d coordinates EX:(x,y,z) of a point that always must be the same distance, I'll call it "d" for now, from the origin. The only information I have as input is the deltax and deltay of the mouse across the screen. So far here is what I have tried:
First:
thetaxz+=(omousex-mouseX)/( width );
thetaxy+=(omousey-mouseY)/( height);
(thetaxy is the angle in radians on the x,y axis and thetaxz on the x,z axis)
(I limit both angles so that if they are less than or equal to 0 they equal 2*PI)
Second:
pointX=cos(thetaxz)*d;
pointY=sin(thetaxy)*d;
(pointX is the point's x coordinate and pointY is the y)
Third:
if(thetaxz)<PI){
pointZ=sqrt(sq(d)-sq(eyeX/d)-sq(eyeY/d));
}else{
pointZ=-sqrt(abs(sq(d)-sq(eyeX/d)-sq(eyeY/d)));
}
(sq() is a function that squares and abs() is an absolute value function)
(pointZ should be the point's z coordinate and it is except at crossing between the positive z hemisphere and negative z hemisphere. As it approaches the edge the point gets stretched further than the distance that it is always supposed to be at in the x and y and seemingly randomly around 0.1-0.2 radians of thetaxz the z coordinate becomes NAN or undefined)
I have thought about this for awhile, and truthfully I'm having difficulty warping my head around the concept of quaternions and rotational matrices however if you can show me how to use them to generate actual coordinates I would be glad to learn. I would still prefer it if I could just use some trigonometry in a few axis. Thank you in advance for any help and if you need more information please just ask.
Hint/last minute idea: I think it may have something to do with the z position affecting the x and y positions back but I am not sure.
EDIT: I drew a diagram:
If you truly want any success in this, you're going to have to bite the bullet and learn about rotation matrices and / or quaternion rotations. There may be other ways to do what you want, but rotation matrices and quaternion rotations are used simply because they are widely understood and among the simplest means of expressing and applying rotations to vectors. Any other representation somebody can come up with will probably be a more complex reformulation of one or both of these. In fact it can be shown rotation is a linear transformation and so can be expressed as a matrix. Quaternion rotations are just a simplified means of rotating vectors in 3D, and therefore have equivalent matrix representations.
That said, it sounds like you're interested in grabbing an object in your scene with a mouse click and rotating in a natural sort of way. If that's the case, you should look at the ArcBall method (there are numerous examples you may want to look over). This still requires you know something of quaternions. You will also find that an at least minimal comprehension of the basic aspects of linear algebra will be helpful.
Update: Based on your diagram and the comments it contains, it looks like all you are really trying to do is to convert Spherical Coordinates to Cartesian Coordinates. As long as we agree on the the notation, that's easy. Let θ be the angle you're calling XY, that is, the angle between the X axis rotated about the Z axis; this is called the azimuth angle and will be in the range [0, 2π) radians or [0°, 360°). Let Φ be an angle between the XY plane and your vector; this is called the elevation angle and will be in the range [-π/2, +π/2] or [-90°, +90°] and it corresponds to the angle you're calling the XZ angle (rotation in the XZ plane about the Y axis). There are other conventions, so make sure you're consistent. Anyway, the conversion is simply:
x = d∙cos(Φ)∙cos(θ)
y = d∙cos(Φ)∙sin(θ)
z = d∙sin(Φ)

3d Parabolic Trajectory

I'm trying to figure out some calculations using arcs in 3d space but am a bit lost. Lets say that I want to animate an arc in 3d space to connect 2 x,y,z coordinates (both coordinates have a z value of 0, and are just points on a plane). I'm controlling the arc by sending it a starting x,y,z position, a rotation, a velocity, and a gravity value. If I know both the x,y,z coordinates that need to be connected, is there a way to calculate what the necessary rotation, velocity, and gravity values to connect it from the starting x,y,z coordinate to the ending one?
Thanks.
EDIT: Thanks tom10. To clarify, I'm making "arcs" by creating a parabola with particles. I'm trying to figure out how to ( by starting a parabola formed by a series particles with an beginning x,y,z,velocity,rotation,and gravity) determine where it will in end(the last x,y,z coordinates). So if it if these are the two coordinates that need to be connected:
x1=240;
y1=140;
z1=0;
x2=300;
y2=200;
z2=0;
how can the rotation, velocity, and gravity of this parabola be calculated using only these variables start the formation of the parabola:
x1=240;
y1=140;
z1=0;
rotation;
velocity;
gravity;
I am trying to keep the angle a constant value.
This link describes the ballistic trajectory to "hit a target at range x and altitude y when fired from (0,0) and with initial velocity v the required angle(s) of launch θ", which is what you want, right? To get your variables into the right form, set the rotation angle (in the x-y plane) so you're pointing in the right direction, that is atan(y/x), and from then on out, to match the usual terminology for 2D problem, rewrite your z to y, and the horizontal distance to the target (which is sqrt(xx + yy)) as x, and then you can directly use the formula in link.
Do the same as you'd do in 2D. You just have to convert your figures to an affine space by rotating the axis, so one of them becomes zero; then solve and undo the rotation.

Polygon math

Given a list of points that form a simple 2d polygon oriented in 3d space and a normal for that polygon, what is a good way to determine which points are specific 'corner' points?
For example, which point is at the lower left, or the lower right, or the top most point? The polygon may be oriented in any 3d orientation, so I'm pretty sure I need to do something with the normal, but I'm having trouble getting the math right.
Thanks!
You would need more information in order to make that decision. A set of (co-planar) points and a normal is not enough to give you a concept of "lower left" or "top right" or any such relative identification.
Viewing the polygon from the direction of the normal (so that it appears as a simple 2D shape) is a good start, but that shape could be rotated to any arbitrary angle.
Is there some other information in the 3D world that you can use to obtain a coordinate-system reference?
What are you trying to accomplish by knowing the extreme corners of the shape?
Are you looking for a bounding box?
I'm not sure the normal has anything to do with what you are asking.
To get a Bounding box, keep 4 variables: MinX, MaxX, MinY, MaxY
Then loop through all of your points, checking the X values against MaxX and MinX, and your Y values against MaxY and MinY, updating them as needed.
When looping is complete, your box is defined as MinX,MinY as the upper left, MinX, MaxY as upper right, and so on...
Response to your comment:
If you want your box after a projection, what you need is to get the "transformed" points. Then apply bounding box loop as stated above.
Transformed usually implies 2D screen coordinates after a projection(scene render) but it could also mean the 2D points on any plane that you projected on to.
A possible algorithm would be
Find the normal, which you can do by using the cross product of vectors connecting two pairs of different corners
Create a transformation matrix to rotate the polygon so that it is planer in XY space (i.e. normal alligned along the Z axis)
Calculate the coordinates of the bounding box or whatever other definition of corners you are using (as the polygon is now aligned in 2D space this is a considerably simpler problem)
Apply the inverse of the transformation matrix used in step 2 to transform these coordinates back to 3D space.
I believe that your question requires some additional information - namely the coordinate system with respect to which any point could be considered "topmost", or "leftmost".
Don't forget that whilst the normal tells you which way the polygon is facing, it doesn't on its own tell you which way is "up". It's possible to rotate (or "roll") around the normal vector and still be facing in the same direction.
This is why most 3D rendering systems have a camera which contains not only a "view" vector, but also "up" and "right" vectors. Changes to the latter two achieve the effect of the camera "rolling" around the view vector.
Project it onto a plane and get the bounding box.
I have a silly idea, but at the risk of gaining a negative a point, I'll give it a try:
Get the minimum/maximum value from
each three-dimensional axis of each
point on your 2d polygon. A single pass with a loop/iterator over the list of values for every point will suffice, simply replacing the minimum and maximum values as you go. The end result is a list that has the "lowest" X, Y, Z coordinates and "highest" X, Y, Z coordinates.
Iterate through this list of min/max
values to create each point
("corner") of a "bounding box"
around the object. The result
should be a box that always contains
the object regardless of axis
examined or orientation (no point on
the polygon will ever exceed the
maximum or minimums you collect).
Then get the distance of each "2d
polygon" point to each corner
location on the "bounding box"; the
shorter the distance between points,
the "closer" it is to that "corner".
Far from optimal, certainly crummy, but certainly quick. You could probably post-capture this during the object's rotation, by simply looking for the min/max of each rotated x/y/z value, and retaining a list of those values ahead of time.
If you can assume that there is some constraints regarding the shapes, then you might be able to get away with knowing less information. For example, if your shape was the composition of a small square with a long thin triangle on one side (i.e. a simple symmetrical geometry), then you could compare the distance from each list point to the "center of mass." The largest distance would identify the tip of the cone, the second largest would be the two points farthest from the tip of the cone, etc... If there was some order to the list, like points are entered in counter clockwise order (about the normal), you could identify all the points. This sounds like a bit of computation, so it might be reasonable to try to include some extra info with your shapes, like the "center of mass" and a reference point that is located "up" above the COM (but not along the normal). This will give you an "up" vector that you can cross with the normal to define some body coordinates, for example. Also, the normal can be defined by an ordering of the point list. If you can't assume anything about the shapes (or even if the shapes were symmetrical, for example), then you will need more data. It depends on your constraints.
If you know that the polygon in 3D is "flat" you can use the normal to transform all 3D-points of the vertices to a 2D-representation (of the points with respect to the plan in which the polygon is located) - but this still leaves you with defining the origin of this coordinate-system (but this don't really matter for your problem) and with the orientation of at least one of the axes (if you want orthogonal axes you can still rotate them around your choosen origin) - and this is where the trouble starts.
I would recommend using the Y-axis of your 3D-coordinate system, project this on your plane and use the resulting direction as "up" - but then you are in trouble in case your plan is orthogonal to the Y-axis (now you might want to use the projected Z-Axis as "up").
The math is rather simple (you can use the inner product (a.k.a. scalar product) for projection to your plane and some matrix stuff to convert to the 2D-coordinate system - you can get all of it by googling for raytracer algorithms for polygons.

Resources