Estimated position of vector after time, angle and speed - math

How to calculate 3D vector position after some time of movement at given angle and speed?
I have these variables available: current position, horizontal angle, vertical angle and speed.
I want to calculate position in the future.
Speed is defined as:
float distMade = this->Position().GetDistanceTo(lastPosition);
float speed = (distMade / timeFromLastCheck) * 1000; // result per sec
// checking every 100ms
Vertical angle coordinate system:
Facing 100% down -PI/2 (-1.57)
Facing 100% up PI/2 (1.57)
Horizontal angle:
Radian system, facing north = PI/2
Facing west = PI
Position 3d vector: x, y, z where z is height level.

It looks like you are trying to predict a future position based on current position and previous position, and know the duration between them.
In this case, it seems like you don't need the angular directions at all. Just keep your "speed" as a vector.
speed = (position() - lastPosition) / (time-last_time);
future_position = position()+(future_time-time)*speed;
If your vector objects don't have operators overloaded, look for some that do or perform the calculation on each x,y,z component independently.
This is, of course, does not take into account any acceleration, just predicts based on current velocity. You could also smooth it out by averaging over the last 5-10 speeds to get a slightly less jittery prediction. If you want to account for acceleration, then you'll have to track last_speed in the same fashion you are tracking last_position currently, and acceleration is just speed-last_speed. And you'd likely want to do an average over that as well.

in that case your speed is cartesian speed
so:
get point positions in cartesian space in different time
P0=(x0,y0,z0); - last position [units]
P1=(x1,y1,z1); - actual position [units]
dt=0.1; - time difference between obtaining P0,P1
compute new position in time pasted from obtaining P1
P(t)=P1+(P1-P0)*t/dt
expand:
x=x1+(x1-x0)*t/dt
y=y1+(y1-y0)*t/dt
z=z1+(z1-z0)*t/dt
if you need angh,angv,dist (and origin of your coordinate system is (0,0,0)
then you use this or modify it to your coordinate system:
dist = |P|=sqrt(x*x+y*y+z*z)
angv=asin(z/dist)
angh=atan2(y,x)
this is for: Z axis = UP, Y axis = North, X axis = East
if origin is not (0,0,0) then just substract it from P before conversion

If your horizontal angle is azimuthal angle, and vertical angle is elevation,
then
X = X0 + V * t * Cos(Azimuth) * Cos(Elevation)
Y = Y0 + V * t * Sin(Azimuth) * Cos(Elevation)
Z = Z0 + V * t * Sin(Elevation)

Related

Maintain distance for orbital ellipse

I'm making a 4x game with solar systems in the Unity game engine. I have planets which I'd like to orbit around their stars in an elliptical fashion. The planets for various reasons are not parented to the stars. The game is in 3D space with a top down view, so the orbits are on the x and z planes with a y of zero.
Following on from various posts e.g. this, this and this I've put together the following code in a co-routine:
while (true)
{
yield return new WaitForFixedUpdate();
x = orbitStar.position.x + ((dist + xMod) * Mathf.Sin(a));
z = orbitStar.position.z + (dist * Mathf.Cos(a));
orbitLines.position = new Vector3(x, 0, z);
a += aPlus * Time.fixedDeltaTime;
}
orbitStar is the star the planets are orbiting, dist is the distance to the star, orbitLines is the object to be orbited (actually a trail renderer, later to also be the planet but in turn based time not real time) and xMod is the variable that controls how elliptical the path is. a and aPlus are arbitrary variables that control the angular velocity.
This forms a nice ellipse based on xMod. The problem is the trail renderer does not bisect the planet as xMod is increased, the trail moves further away from the planet, here the trail is the turquoise color curve:
Being somewhat inept at maths I've tried juggling round the variables and throwing 'magic' numbers at the function with inconsistent results e.g:
z = orbitStar.position.z + ((dist - xMod) * Mathf.Cos(a));
and
z = orbitStar.position.z + (dist * Mathf.Cos(a)) + someOtherVariable;
How can I correct for the distance xMod is moving the trail by, so that the trail moves through the planet?
It all depend where the planet is. If I understand properly, you are trying to create an ellipse around a center point, and then try to figure out the parameter of this ellipse so a certain planet is on its path. You need to take this planet's coordinate into account.
The ellipse equation is
x = a * cos(t)
z = b * sin(t)
In your case,
a = dist + modX
b = dist
Basically, when z = 0, the planet must be is at a distance 'a' on the x axis to be on the ellipse. In the same way, if the planet is at x = 0, it must be at a distance 'b' to be on the ellipse.
So the question is: where is your planet? if the planet is fixed, there is an infinite number of solutions for a and b, to make different eclipses go through it. You could choose a ratio between a and b that you like and solve the equation above to find the value of 'a':
x = a * cos(t)
z = a*ratio * sin(t)
--> You know x, y, and ratio. t remains variable. solve for a
If, on the other hand, you want to choose the ellipse path and then place the planet on it, just choose a and b and find the planet x and z by computing
x = a * cos(t)
z = b * sin(t)
And choose and arbitrary 't', which represents where the planet is around the eclipse
This link might help you visualize what variables 'a' and 'b' do

How to calculate the angles of the projection in 3d for an object to step at given point?

I need to calculate the angles to through the ball in that direction for a given speed and the point where it should land after thrown.
The horizontal angle is easy(We know both start and step points).How to calculate the vertical angle of projection.There is gravy applying on object.
Time of travel will be usual as bowling time(time between ball release and occurring step) as per video.
Is there a way directly in unity3d?
Watch this video for 8 seconds for clear understating of this question.
According to the Wikipedia page Trajectory of a projectile, the "Angle of reach" (The angle you want to know) is calculated as follows:
θ = 1/2 * arcsin(gd/v²)
In this formula, g is the gravitational constant 9.81, d is the distance you want the projectile to travel, and v is the velocity at which the object is thrown.
Code to calculate this could look something like this:
float ThrowAngle(Vector3 destination, float velocity)
{
const float g = 9.81f;
float distance = Vector3.Distance(transform.position, destination);
//assuming you want degrees, otherwise just drop the Rad2Deg.
return Mathf.Rad2Deg * (0.5f * Asin((g*distance)/Mathf.Pow(velocity, 2f)));
}
This will give you the angle assuming no air resistance etc. exist in your game.
If your destination and your "throwing point" are not at the same height, you may want to set both to y=0 first, otherwise, errors may occur.
EDIT:
Considering that your launch point is higher up than the destination, this formula from the same page should work:
θ = arctan(v² (+/-) √(v^4-g(gx² + 2yv²))/gx)
Here, x is the range, or distance, and y is the altitude (relative to the launch point).
Code:
float ThrowAngle(Vector3 start, Vector3 destination, float v)
{
const float g = 9.81f;
float xzd = Mathf.Sqrt(Mathf.Pow(destination.x - start.x, 2) + Mathf.Pow(destination.z - start.z, 2));
float yd = destination.y - start.y;
//assuming you want degrees, otherwise just drop the Rad2Deg. Split into two lines for better readability.
float sqrt = (Mathf.Pow(v,4) - g * (g*Mathf.Pow(xzd,2) + 2*yd*Mathf.Pow(v,2))/g*xzd);
//you could also implement a solution which uses both values in some way, but I left that out for simplicity.
return Mathf.Atan(Mathf.Pow(v, 2) + sqrt);
}

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

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.

How can I calculate the distance between two points in Cartesian space while respecting Asteroids style wrap around?

I have two points (x1, y1) and (x2,y2) which represent the location of two entities in my space. I calculate the Euclidian distance between them using Pythagoras' theorem and everything is wonderful. However, if my space becomes finite, I want to define a new shortest distance between the points that "wraps around" the seams of the map. For example, if I have point A as (10, 10) and point B as (90,10), and my map is 100 units wide, I'd like to calculate the distance between A and B as 20 (out the right edge of the map and back into the left edge), instead of 80, which is the normal Euclidian distance.
I think my issue is that I'm using a coordinate system that isn't quite right for what I'm trying to do, and that really my flat square map is more of a seamless doughnut shape. Any suggestions for how to implement a system of this nature and convert back and forth from Cartesian coordinates would be appreciated too!
Toroidal plane? Okay, I'll bite.
var raw_dx = Math.abs(x2 - x1);
var raw_dy = Math.abs(y2 - y1);
var dx = (raw_dx < (xmax / 2)) ? raw_dx : xmax - raw_dx;
var dy = (raw_dy < (ymax / 2)) ? raw_dy : ymax - raw_dy;
var l2dist = Math.sqrt((dx * dx) + (dy * dy));
There's a correspondence here between the rollover behavior of your x and y coordinates and the rollover behavior of signed integers represented using the base's complement representation in the method of complements.
If your coordinate bounds map exactly to the bounds of a binary integer type supported by your language, you can take advantage of the two's complement representation used by nearly all current machines by simply performing the subtraction directly, ignoring overflow and reinterpreting the result as a signed value of the same size as the original coordinate. In the general case, you're not going to be that lucky, so the above dance with abs, compare and subtract is required.

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