How to convert Yaw, Pitch, Roll and Acceleration value to cartesian system? - math

I am having readings of Yaw, pitch, Roll, Rotation matrix, Quaternion and Acceleration. These reading are taken with frequency of 20 (per second). They are collected from the mobile device which is moving in 3D space from one position to other position.
I am setting reference plane by multiplying inverse matrix to the start postion. The rest of the readings are taken by considering the first one as a reference one. Now I want to convert these readings to 3D cartesian system.
How to convert it? Can anyone please help?

Ok basically yaw, pitch and roll are the euler angles, with them you got your rotation matrix already.
Quaternions are aquivalent to that, with them you can also calculate the rotation matrix you need.
If you have rotation matrices R_i for every moment i in your l=20secs interval. Than these rotations are relative the the one applied at R_(i-1) you can calculate their rotation relative to the first position. So A_i = R_1*...*R_i but after all you could also just safe the new direction of travel (safes calculations).
So asuming that the direction of travel is d_0 = (1,0,0) at first. You can calculate the next by d_i = R_i*d_(i-1) (always norm d_(i-1) because it might get smaller or bigger due to error). The first position is p and your start speed is v_0 = (0,0,0) and finally the acceleration is a_i. You need to calculate the vectorial speed v_i for every moment:
v_i = v_(i-1) + l*a_i*A_i*d_0 = v_(i-1) + l*a_i*d_i
Now you basically know where you are moving, and what kind of speed you use, so your position p_i at the moment i is given by:
`p_i = p_0 + l * ( v_1 + v_2 + ... + v_i)`
For the units:
a_i = [m/s^2]^3
v_i = [m/s]^3
p_i = [m]^3
Precision
Now some points to the precision of your position calculation (just if you want to know how good it will work). Suppose you have an error e>= ||R_i*v-w|| (where w is the correct vector). in the data you calculate the rotation matrices with. Your error is multipling itself so your error in the i moment is e_i <= e^i.
Then because you apply l and a_i to it, it becomes:
f_i <= l*a_i*e^i
But you are also adding up the error when you add up the speed, so now its g_i <= f_1+...+f_i. And yeah you also add up for the position (both sums over i):
h_i <= g_1+...+g_i = ΣΣ (l*a_i*e^i) = l* ΣΣ (a_i*e^i)
So this is basically the maximum difference from your position p_i to the correct position w (||p_i - w|| <= h_i).
This is still not taking in account that you don't get the correct acceleration from your device (I don't know how they normally do this), because correct would be:
a_i = ||∫a_i(t) dt|| (where a_i(t) is vectorial now)
And you would need to calculate the difference in direction (your rotation matrix) as:
Δd_i = (∫a_i(t) dt)/a_i (again a_i(t) is vectorial)
So apart from the errors you get from the error in your rotations from your device (and from floating point arithmetic), you have an error in your acceleration, I won't calculate that now but you would substitute a_i = a_i + b_i.
So I'm pretty sure it will be far off from the real position. You even have to take in account that you're speed might be non zero when it should be!
But that beeing said, I would really like to know the precision you get after implementing it, that's what always keept me from trying it.

Related

Calculating the angle tilt using only accelerometers

I would like to know how to calculate using the coordinates of the accelerometer of my Android phone the angle between the two segments connecting the accelerometer and the bottom of the tree (B) and the accelerometer and the top of the tree (T) .
The accelerometer takes a value of acceleration on 3 axes every second, so I calculated the average and I have:
For the phone towards B: Ay1 = -9.69m.s^-1 and Az1 = 0.71m.s^-1
For the phone towards T: Ay2 = -9.71m.s^-1 and Az2 = 0.71m.s^-1
I am located at a distance D = 20m from the tree.
I would like at the end to know the value of H. So I would like to know how to calculate the angle and then find the height of the tree.
Thanks for your help
The angles we need are the angles between world-up and device-up. Since the gravity vector is pointing towards world-down, this is simply (assuming, you are pointing with the device y-axis):
cos angle = -a.y / sqrt(a.x^2 + a.y^2 + a.z^2)
The two angles we get from your readings are:
angle1 = 4.19065°
angle2 = 4.18205°
You can already see that the angles are very close as the two acceleration values are also extremely close. Btw, I wonder if you are really pointing with the y-axis because the gravity values suggest that you are holding the phone almost upright in both cases.
Anyway, if we assume that the two angles are correct, we can now calculate the height of the respective triangles assuming a length to target l. Then:
tan (90° - angle) = h / l
Assuming l=20 m, this gives us two height values:
h1 = 272.958 m
h2 = 273.521 m
These are heights above the height of the phone. In theory, one should be positive and the other should be negative. The height of the tree would be the difference of the two heights:
treeH = h2 - h1
treeH = 0.56338 m
As you have seen throughout the example, your readings must be pretty off. Nevertheless, this is how you would calculate the tree height.

Vectors and Scaler in games

How can we use vector and scalar in games? What benefit from that.
Could someone please indicate precisely the difference between a scalar and a vector in games field ? I find no matter how many times I try to understand but I maybe need examples for that.
A scalar is just another word for a number. The distinction is that a scalar is a number that is part of a vector. There is nothing special about a scalar.
A vector is a set of numbers (one or more) that define something, in the most common case you have 2 numbers representing a 2D vector or 3 numbers representing a 3D vector. The abstract notion for a vector is simply an arrow.
Take a piece of graph paper. Select any point on that paper and call it the origin. Its coordinate will be x = 0, y = 0. Now draw a straight line from that point in any direction and any length. To describe that arrow you need to define the vector. Count how far across the page the end of the arrow is from the start (origin) and that is the x component. Then how far up the page and that is the y component.
You have just created a vector that has two numbers (x,y) that completely describe the arrow on the paper. This type of vector always starts at zero. You can also describe the vector by its direction (ie north, east, south...) and length.
In 3D you need 3 numbers to describe any arrow. (x,y,z)
Vectors are very handy. You can use a vector to describe how fast something is moving and in what direction. The vector represents a little arrow that starts where the object is now and ends where the object will be in the next time unit.
Thus an object at coordinate x,y has a vector velocity(0.2,0.3). To calculate the position of the object in the next time unit just add the vector to the coordinate
newXPos = currentXPos + velocityVectorX
newYPos = currentYPos + velocityVectorY
If you want to slow the speed by half you can multiply the vector by 0.5
velocityVectorX = velocityVectorX * 0.5
velocityVectorY = velocityVectorY * 0.5
You do the same to increase the speed.
velocityVectorX = velocityVectorX * 2
velocityVectorY = velocityVectorY * 2
You may have an object in 3D space that has many forces acting on it. There is gravity a vector (arrow) pointing down (G). The force of the air resistance pointing up (R). The current velocity another arrow pointing in the direction it is traveling (V). You can have as many as you like (need) to describe all the forces that push and pull at the object. When you need to calculate the position of the object for the next instance in time (say one second) you just add all the force vectors together to get the total force as a vector and add that to the objects position
Object.x = Object.x + G.x + R.x + V.x;
Object.y = Object.y + G.y + R.y + V.y;
Object.z = Object.z + G.y + R.z + V.z;
If you just want the velocity
V.x = V.x + G.x + R.x;
V.y = V.y + G.y + R.y;
V.z = V.z + G.y + R.z;
That is the new velocity in one second.
There are many things that can be done with a vector. A vector can be used to point away from a surface in 3D, this vector is called a surface normal. The you create a vector from a point on that surface pointing to a light. The cosine of the angle between the two vectors is how much light the surface will reflect.
You can use a vector to represent the three direction in space an object has. Say a box, there is a 3D vector pointing along the width, another along the height and the last along the depth. The length of each vector represents the length of each side. You can make another vector to represent how far the corner of the box is from the origin (any known point) In 3D these 4 vectors are used to represent the object and is called a transformation matrix (just another type of vector made up of vectors)
The list of things vectors can do is endless.
The basics is just like number, you can add, subtract, multiply and divide and vector.
Then there are a host of special functions for vectors, normalize, transform, dot product and cross product to name but a few. For these things people normally use a library that does all this for you. My view is that if you really want to learn about vectors and how they are used write your own vector library at some point until then use a library.
Hope that cleared the mud a little bit for you, it is always difficult to describe something you have used for a long time to someone that is new to it so feel free to ask questions in the comments if you need.

Calculating Normals across a sphere with a wave-like vertex shader

I've been trying to get the correct normals for a sphere I'm messing with using a vertex shader. The algorithm can be boiled down simply to
vert.xyz += max(0, sin(time + 0.004*vert.x))*10*normal.xyz
This causes a wave to roll across the sphere.
In order to make my normals correct, I need to transform them as well. I can take the tangent vector at a given x,y,z, get a perpendicular vector (0, -vert.z, vert.y), and then cross the tangent with the perp vector.
I've been having some issue with the math though, and it's become a personal vendetta at this point. I've solved for the derivative hundreds of times but I keep getting it incorrect. How can I get the tangent?
Breaking down the above line, I can make a math function
f(x,y,z) = max(0, sin(time + 0.004*x))*10*Norm(x,y,z) + (x,y,z)
where Norm(..) is Normalize((x,y,z) - CenterOfSphere)
After applying f(x,y,z), unchanged normals
What is the correct f '(x,y,z)?
I've accounted for the weirdness caused by the max in f(...), so that's not the issue.
Edit: The most successful algorithm I have right now is as follows:
Tangent vector.x = 0.004*10*cos(0.004*vert.x + time)*norm.x + 10*sin(0.004*vert.x + time) + 1
Tangent vector.y = 10*sin(0.004*vert.x + time) + 1
Tangent vector.z = 10*sin(0.004*vert.x + time) + 1
2nd Tangent vector.x = 0
2nd Tangent vector.y = -norm.z
2nd Tangent vector.z = norm.y
Normalize both, and perform Cross(Tangent2, Tangent1). Normalize again, and done (it should be Cross(Tangent1, Tangent2), but this seems to have better results... more hints of an issue in my math!).
This yields this
Get tangent/normal by derivate of function can sometimes fail if your surface points are nonlinearly distributed and or some math singularity is present or if you make a math mistake (which is the case in 99.99%). Anyway you can always use the geometric approach:
1. you can get the tangents easy by
U(x,y,z)=f(x+d,y,z)-f(x,y,z);
V(x,y,z)=f(x,y+d,z)-f(x,y,z);
where d is some small enough step
and f(x,y,z) is you current surface point computation
not sure why you use 3 input variables I would use just 2
but therefore if the shifted point is the same as unshifted
use this instead =f(x,y,z+d)-f(x,y,z);
at the end do not forget to normalize U,V size to unit vector
2. next step
if bullet 1 leads to correct normals
then you can simply solve the U,V algebraically
so rewrite U(x,y,z)=f(x+d,y,z)-f(x,y,z); to full equation
by substituting f(x,y,z) with the surface point equation
and simplify
[notes]
sometimes well selected d can simplify normalization to multipliyng by a constant
you should add normals visualization for example like this:
to actually see what is really happening (for debug purposses)

Scale vector along plane

I'm trying to apply friction to a 3D collision. The information I have is:
The velocity of the collision
The surface normal of the collider
An arbitrary friction coefficient (0 - 1 inclusive)
What I would like to do is multiply the portion of the velocity that is parallel to the plane by the friction coefficient, while leaving the portion parallel to the normal intact.
How can I go about performing this operation?
I was thinking perhaps this will involve the use of the dot-product, but then I started reading about matrices, then vector projection, and now I'm pretty lost.
I was able to solve the problem by doing the following:
Get a tangent vector for the normal
Use the normal and the tangent vector to get a rotation matrix for the surface
Use the inverse of the rotation matrix to transform the velocity vector
Scale the x and z components of the transformed vector by the friction coefficient
Use the rotation matrix to transform the velocity back again
I doubt this is the most efficient way of doing it, but it seems to have worked.
If you can do vector addition, scalar multiplication (i.e. multiplying a vector by a number) and the dot product, then this is all you need:
Vin = (V•Vnormal)Vnormal
Vpar = V - Vin
Vpar = kVpar (where k is the coefficient, and "=" means assignment)
Vin = -Vin
V = Vin + Vpar

Triangle mathematics for game development

I'm trying to make a triangle (isosceles triangle) to move around the screen and at the same time slightly rotate it when a user presses a directional key (like right or left).
I would like the nose (top point) of the triangle to lead the triangle at all times. (Like that old asteroids game).
My problem is with the maths behind this. At every X time interval, I want the triangle to move in "some direction", I need help finding this direction (x and y increments/decrements).
I can find the center point (Centroid) of the triangle, and I have the top most x an y points, so I have a line vector to work with, but not a clue as to "how" to work with it.
I think it has something to do with the old Sin and Cos methods and the amount (angle) that the triangle has been rotated, but I'm a bit rusty on that stuff.
Any help is greatly appreciated.
The arctangent (inverse tangent) of vy/vx, where vx and vy are the components of your (centroid->tip) vector, gives you the angle the vector is facing.
The classical arctangent gives you an angle normalized to -90° < r < +90° degrees, however, so you have to add or subtract 90 degrees from the result depending on the sign of the result and the sign of vx.
Luckily, your standard library should proive an atan2() function that takes vx and vy seperately as parameters, and returns you an angle between 0° and 360°, or -180° and +180° degrees. It will also deal with the special case where vx=0, which would result in a division by zero if you were not careful.
See http://www.arctangent.net/atan.html or just search for "arctangent".
Edit: I've used degrees in my post for clarity, but Java and many other languages/libraries work in radians where 180° = π.
You can also just add vx and vy to the triangle's points to make it move in the "forward" direction, but make sure that the vector is normalized (vx² + vy² = 1), else the speed will depend on your triangle's size.
#Mark:
I've tried writing a primer on vectors, coordinates, points and angles in this answer box twice, but changed my mind on both occasions because it would take too long and I'm sure there are many tutorials out there explaining stuff better than I ever can.
Your centroid and "tip" coordinates are not vectors; that is to say, there is nothing to be gained from thinking of them as vectors.
The vector you want, vForward = pTip - pCentroid, can be calculated by subtracting the coordinates of the "tip" corner from the centroid point. The atan2() of this vector, i.e. atan2(tipY-centY, tipX-centX), gives you the angle your triangle is "facing".
As for what it's relative to, it doesn't matter. Your library will probably use the convention that the increasing X axis (---> the right/east direction on presumably all the 2D graphs you've seen) is 0° or 0π. The increasing Y (top, north) direction will correspond to 90° or (1/2)π.
It seems to me that you need to store the rotation angle of the triangle and possibly it's current speed.
x' = x + speed * cos(angle)
y' = y + speed * sin(angle)
Note that angle is in radians, not degrees!
Radians = Degrees * RadiansInACircle / DegreesInACircle
RadiansInACircle = 2 * Pi
DegressInACircle = 360
For the locations of the vertices, each is located at a certain distance and angle from the center. Add the current rotation angle before doing this calculation. It's the same math as for figuring the movement.
Here's some more:
Vectors represent displacement. Displacement, translation, movement or whatever you want to call it, is meaningless without a starting point, that's why I referred to the "forward" vector above as "from the centroid," and that's why the "centroid vector," the vector with the x/y components of the centroid point doesn't make sense. Those components give you the displacement of the centroid point from the origin. In other words, pOrigin + vCentroid = pCentroid. If you start from the 0 point, then add a vector representing the centroid point's displacement, you get the centroid point.
Note that:
vector + vector = vector
(addition of two displacements gives you a third, different displacement)
point + vector = point
(moving/displacing a point gives you another point)
point + point = ???
(adding two points doesn't make sense; however:)
point - point = vector
(the difference of two points is the displacement between them)
Now, these displacements can be thought of in (at least) two different ways. The one you're already familiar with is the rectangular (x, y) system, where the two components of a vector represent the displacement in the x and y directions, respectively. However, you can also use polar coordinates, (r, Θ). Here, Θ represents the direction of the displacement (in angles relative to an arbitary zero angle) and r, the distance.
Take the (1, 1) vector, for example. It represents a movement one unit to the right and one unit upwards in the coordinate system we're all used to seeing. The polar equivalent of this vector would be (1.414, 45°); the same movement, but represented as a "displacement of 1.414 units in the 45°-angle direction. (Again, using a convenient polar coordinate system where the East direction is 0° and angles increase counter-clockwise.)
The relationship between polar and rectangular coordinates are:
Θ = atan2(y, x)
r = sqrt(x²+y²) (now do you see where the right triangle comes in?)
and conversely,
x = r * cos(Θ)
y = r * sin(Θ)
Now, since a line segment drawn from your triangle's centroid to the "tip" corner would represent the direction your triangle is "facing," if we were to obtain a vector parallel to that line (e.g. vForward = pTip - pCentroid), that vector's Θ-coordinate would correspond to the angle that your triangle is facing.
Take the (1, 1) vector again. If this was vForward, then that would have meant that your "tip" point's x and y coordinates were both 1 more than those of your centroid. Let's say the centroid is on (10, 10). That puts the "tip" corner over at (11, 11). (Remember, pTip = pCentroid + vForward by adding "+ pCentroid" to both sides of the previous equation.) Now in which direction is this triangle facing? 45°, right? That's the Θ-coordinate of our (1, 1) vector!
keep the centroid at the origin. use the vector from the centroid to the nose as the direction vector. http://en.wikipedia.org/wiki/Coordinate_rotation#Two_dimensions will rotate this vector. construct the other two points from this vector. translate the three points to where they are on the screen and draw.
double v; // velocity
double theta; // direction of travel (angle)
double dt; // time elapsed
// To compute increments
double dx = v*dt*cos(theta);
double dy = v*dt*sin(theta);
// To compute position of the top of the triangle
double size; // distance between centroid and top
double top_x = x + size*cos(theta);
double top_y = y + size*sin(theta);
I can see that I need to apply the common 2d rotation formulas to my triangle to get my result, Im just having a little bit of trouble with the relationships between the different components here.
aib, stated that:
The arctangent (inverse tangent) of
vy/vx, where vx and vy are the
components of your (centroid->tip)
vector, gives you the angle the vector
is facing.
Is vx and vy the x and y coords of the centriod or the tip? I think Im getting confused as to the terminology of a "vector" here. I was under the impression that a Vector was just a point in 2d (in this case) space that represented direction.
So in this case, how is the vector of the centroid->tip calculated? Is it just the centriod?
meyahoocomlorenpechtel stated:
It seems to me that you need to store
the rotation angle of the triangle and
possibly it's current speed.
What is the rotation angle relative to? The origin of the triangle, or the game window itself? Also, for future rotations, is the angle the angle from the last rotation or the original position of the triangle?
Thanks all for the help so far, I really appreciate it!
you will want the topmost vertex to be the centroid in order to achieve the desired effect.
First, I would start with the centroid rather than calculate it. You know the position of the centroid and the angle of rotation of the triangle, I would use this to calculate the locations of the verticies. (I apologize in advance for any syntax errors, I have just started to dabble in Java.)
//starting point
double tip_x = 10;
double tip_y = 10;
should be
double center_x = 10;
double center_y = 10;
//triangle details
int width = 6; //base
int height = 9;
should be an array of 3 angle, distance pairs.
angle = rotation_angle + vertex[1].angle;
dist = vertex[1].distance;
p1_x = center_x + math.cos(angle) * dist;
p1_y = center_y - math.sin(angle) * dist;
// and the same for the other two points
Note that I am subtracting the Y distance. You're being tripped up by the fact that screen space is inverted. In our minds Y increases as you go up--but screen coordinates don't work that way.
The math is a lot simpler if you track things as position and rotation angle rather than deriving the rotation angle.
Also, in your final piece of code you're modifying the location by the rotation angle. The result will be that your ship turns by the rotation angle every update cycle. I think the objective is something like Asteroids, not a cat chasing it's tail!

Resources