I'm working on a 2D physics engine for a game. I have gravity and masses working, using a simple iterative approach (that I know I'll have to upgrade eventually); I can push the masses around manually and watch them move and it all works as I'd expect.
Right now I'm trying to set up the game world in advance with a satellite in a simple circular orbit around a planet. To do this I need to calculate the initial velocity vector of the satellite given the mass of the planet and the desired distance out; this should be trivial, but I cannot for the life of me get it working right.
Standard physics textbooks tell me that the orbital velocity of an object in circular orbit around a mass M is:
v = sqrt( G * M / r )
However, after applying the appropriate vector the satellite isn't going anything like fast enough and falls in in a sharply elliptical orbit. Random tinkering shows that it's off by about a factor of 3 in one case.
My gravity simulation code is using the traditional:
F = G M m / r^2
G is set to 1 in my universe.
Can someone confirm to me that these equations do still hold in 2D space? I can't see any reason why not, but at this point I really want to know whether the problem is in my code or my assumptions...
Update: My physics engine works as follows:
for each time step of length t:
reset cumulative forces on each object to 0.
for each unique pair of objects:
calculate force between them due to gravity.
accumulate force to the two objects.
for each object:
calculate velocity change dV for this timestep using Ft / m.
v = v + dV.
calculate position change dS using v * t.
s = s + dS.
(Using vectors where appropriate, of course.)
Right now I'm doing one physics tick every frame, which is happening about 500-700 times per second. I'm aware that this will accumulate errors very quickly, but it should at least get me started.
(BTW, I was unable to find an off-the-shelf physics engine that handles orbital mechanics --- most 2D physics engines like Chipmunk and Box2D are more focused on rigid structures instead. Can anyone suggest one I could look at?)
You need to make sure that your delta t iterative time value is small enough. You will definitely have to tinker with the constants in order to get the behaviour you expect. Iterative simulation in your case and most cases is a form of integration where errors build up fast and unpredictably.
Yes, these equations hold in 2D space, because your 2D space is just a 2D representation of a 3D world. (A "real" 2D universe would have different equations, but that's not relevant here.)
A long shot: Are you perhaps using distance to the surface of the planet as r?
If that isn't it, try cutting your time step in half; if that makes a big difference, keep reducing it until the behavior stops changing.
If that makes no difference, try setting the initial velocity to zero, then watching it fall for a few iterations and measuring its acceleration to see if it's GM/r2. If the answer still isn't clear, post the results and we'll try to figure it out.
Related
I am trying to implement rigid bodies dynamics for my simulation. I am trying to simulate a tensegrity as in the paper attached.
The paper I follow is: Dynamic equations of motion for a 3-bar tensegrity based mobile robot
According to this paper and what I have read so far the general process is:
For each bar:
A) define the bar’s pose (q) : for that I need a position vector and an
orientation vector. I have this since it is my initial position.
B) Apply initial velocity: which is 0
C) Find Kinetic Energy
D) Find Potential Energy
E) Find Torque
For the total system:
A) Find Kinetic Energy
B) Find Potential Energy
C) Find Torque
My question is how can I find the new pose (position and orientation) of each bar according to Kinetic Energy, Potential Energy and Torque?
As I understand, I will need the linear acceleration and angular acceleration, and then the linear velocity and angular velocity and finally update pose (position and orientation). I don’t understand how could I do this.
I looked at those books and read some notes, but I didn't understand practically how to do this
Rigid Body Dynamics Algorithms, by Roy Featherstone
Physics for Game Developers, David M.Bourg
Physically Based Modeling, David Baraff
Extra Clarification if possible:
1) Basically the W matrix that requires the angles of φ, θ, would those angles be the angles of the basic reference frame for the whole structure? Not the angles for each bar, because this is not , I assume it is for the whole system?
2) Regarding the Inertia matrix of the mobile reference frame, I understand this must refer for each bar? But since is for the whole system, what should be the matrix of ?
3) How to factorize M(q)
4) In the paper, it is described through in the cables. I would like to try something else, the bars connected together in the center and each one would be possible to move axially only. So I guess I will have to add a force for each bar and affect this?
If you have any information could you please let me know?
The answer to your question is equation 12 in your paper, which gives you the acceleration at time t.
Computing acceleration
If you look carefully at equation 12, every term is previously defined (except maybe the gravitational forces which are -g * mi along the z axis for each node i, thus f gi = [0, 0, -g * mi]). I recommend that you start building/computing each of these terms (taking into account the remarks on changing basis for I).
To differentiate M(q), remember that all of the mi, li, r1i and r2i are constant, thus only the W have a non-zero derivative:
Then just differentiate each term inside the
Only the unknown will remain, which is the acceleration, written in the paper as
You now need to put all the elements that you have computed on the right hand side of the equation, compute the resulting vector, and factorize your M(q), which is the block-diagonal matrix of all the Mi(q), thus this is equivalent to factorizing each Mi(q). Then you will have the acceleration, from which you can integrate velocity, and in turn, position.
Integrating
This is left out of the paper, but isn't too hard. Since you need velocities to compute acceleration, you will have to use a first order integrator like the Semi-Implicit Euler method for example.
Thus the velocity and position should be updated as follows:
I have an input device that gives me 3 angles -- rotation around x,y,z axes.
Now I need to use these angles to rotate the 3D space, without gimbal lock. I thought I could convert to Quaternions, but apparently since I'm getting the data as 3 angles this won't help?
If that's the case, just how can I correctly rotate the space, keeping in mind that my input data simply is x,y,z axes rotation angles, so I can't just "avoid" that. Similarly, moving around the order of axes rotations won't help -- all axes will be used anyway, so shuffling the order around won't accomplish anything. But surely there must be a way to do this?
If it helps, the problem can pretty much be reduced to implementing this function:
void generateVectorsFromAngles(double &lastXRotation,
double &lastYRotation,
double &lastZRotation,
JD::Vector &up,
JD::Vector &viewing) {
JD::Vector yaxis = JD::Vector(0,0,1);
JD::Vector zaxis = JD::Vector(0,1,0);
JD::Vector xaxis = JD::Vector(1,0,0);
up.rotate(xaxis, lastXRotation);
up.rotate(yaxis, lastYRotation);
up.rotate(zaxis, lastZRotation);
viewing.rotate(xaxis, lastXRotation);
viewing.rotate(yaxis, lastYRotation);
viewing.rotate(zaxis, lastZRotation);
}
in a way that avoids gimbal lock.
If your device is giving you absolute X/Y/Z angles (which implies something like actual gimbals), it will have some specific sequence to describe what order the rotations occur in.
Since you say that "the order doesn't matter", this suggests your device is something like (almost certainly?) a 3-axis rate gyro, and you're getting differential angles. In this case, you want to combine your 3 differential angles into a rotation vector, and use this to update an orientation quaternion, as follows:
given differential angles (in radians):
dXrot, dYrot, dZrot
and current orientation quaternion Q such that:
{r=0, ijk=rot(v)} = Q {r=0, ijk=v} Q*
construct an update quaternion:
dQ = {r=1, i=dXrot/2, j=dYrot/2, k=dZrot/2}
and update your orientation:
Q' = normalize( quaternion_multiply(dQ, Q) )
Note that dQ is only a crude approximation of a unit quaternion (which makes the normalize() operation more important than usual). However, if your differential angles are not large, it is actually quite a good approximation. Even if your differential angles are large, this simple approximation makes less nonsense than many other things you could do. If you have problems with large differential angles, you might try adding a quadratic correction to improve your accuracy (as described in the third section).
However, a more likely problem is that any kind of repeated update like this tends to drift, simply from accumulated arithmetic error if nothing else. Also, your physical sensors will have bias -- e.g., your rate gyros will have offsets which, if not corrected for, will cause your orientation estimate Q to precess slowly. If this kind of drift matters to your application, you will need some way to detect/correct it if you want to maintain a stable system.
If you do have a problem with large differential angles, there is a trigonometric formula for computing an exact update quaternion dQ. The assumption is that the total rotation angle should be linearly proportional to the magnitude of the input vector; given this, you can compute an exact update quaternion as follows:
given differential half-angle vector (in radians):
dV = (dXrot, dYrot, dZrot)/2
compute the magnitude of the half-angle vector:
theta = |dV| = 0.5 * sqrt(dXrot^2 + dYrot^2 + dZrot^2)
then the update quaternion, as used above, is:
dQ = {r=cos(theta), ijk=dV*sin(theta)/theta}
= {r=cos(theta), ijk=normalize(dV)*sin(theta)}
Note that directly computing either sin(theta)/theta ornormalize(dV) is is singular near zero, but the limit value of vector ijk near zero is simply ijk = dV = (dXrot,dYrot,dZrot), as in the approximation from the first section. If you do compute your update quaternion this way, the straightforward method is to check for this, and use the approximation for small theta (for which it is an extremely good approximation!).
Finally, another approach is to use a Taylor expansion for cos(theta) and sin(theta)/theta. This is an intermediate approach -- an improved approximation that increases the range of accuracy:
cos(x) ~ 1 - x^2/2 + x^4/24 - x^6/720 ...
sin(x)/x ~ 1 - x^2/6 + x^4/120 - x^6/5040 ...
So, the "quadratic correction" mentioned in the first section is:
dQ = {r=1-theta*theta*(1.0/2), ijk=dV*(1-theta*theta*(1.0/6))}
Q' = normalize( quaternion_multiply(dQ, Q) )
Additional terms will extend the accurate range of the approximation, but if you need more than +/-90 degrees per update, you should probably use the exact trig functions described in the second section. You could also use a Taylor expansion in combination with the exact trigonometric solution -- it may be helpful by allowing you to switch seamlessly between the approximation and the exact formula.
I think that the 'gimbal lock' is not a problem of computations/mathematics but rather a problem of some physical devices.
Given that you can represent any orientation with XYZ rotations, then even at the 'gimbal lock point' there is a XYZ representation for any imaginable orientation change. Your physical gimbal may be not able to rotate this way, but the mathematics still works :).
The only problem here is your input device - if it's gimbal then it can lock, but you didn't give any details on that.
EDIT: OK, so after you added a function I think I see what you need. The function is perfectly correct. But sadly, you just can't get a nice and easy, continuous way of orientation edition using XYZ axis rotations. I haven't seen such solution even in professional 3D packages.
The only thing that comes to my mind is to treat your input like a steering in aeroplane - you just have some initial orientation and you can rotate it around X, Y or Z axis by some amount. Then you store the new orientation and clear your inputs. Rotations in 3DMax/Maya/Blender are done the same way.
If you give us more info about real-world usage you want to achieve we may get some better ideas.
I've had a bit of a sniff around google for a solution but I believe my terminology is wrong, so bear with me here.
I'm working on a simple game where people can build simplistic spaceships and place thrusters willy nilly over the space ship.
Let's call say my space ship's center of mass is V.
The space ship has an arbitrary number of thrusters at arbitrary positions with arbitrary thrust direction vectors with an arbitrary clamp.
I have an input angular velocity vector (angle/axis notation) and world velocity (vector) which i wish the ship to "go" at.
How would I calculate the the ideal thrust for each of the thrusters for the ship to accelerate to the desired velocities?
My current solution works well for uniformly placed thrusters. Essentially what I do is just dot the desired velocity by the thrusters normal for the linear velocity. While for the angular velocity I just cross the angular velocity by the thrusters position and dot the resulting offset velocity by the thrusters normal. Of course if there's any thrusters that do not have a mirror image on the opposite side of the center of mass it'll result in an undesired force.
Like I said, I think it should be a fairly well documented problem but I might just be looking for the wrong terminology.
I think you can break this down into two parts. The first is deciding what your acceleration should be each frame, based on your current and desired velocities. A simple rule for this
acceleration = k * (desired velocity - current velocity)
where k is a constant that determines how "responsive" the system is. In order words, if you're going too slow, speed up (positive acceleration), and if you're going too fast, slow down (negative acceleration).
The second part is a bit harder to visualize; you have to figure out which combination of thrusters gives you the desired accelerations. Let's call c_i the amount that each thruster thrusts. You want to solve a system of coupled equations
sum( c_i * thrust_i ) = mass * linear acceleration
sum( c_i * thrust_i X position_i) = moment of interia * angular acceleration
where X is the cross produxt. My physics might be a bit off, but I think that's right.
That's an equation of 6 equations (in 3D) and N unknowns where N is the number of thusters, but you've got the additional constraint that c_i > 0 (assuming the thrusters can't push backwards).
That's a tricky problem, but you should be able to set it up as a LCP and get an answer using the Projected Gauss Seidel method. You don't need to get the exact answer, just something close, since you'll be solving it again for slightly different values on the next frame.
I hope that helps...
I am quite new to this, and iv'e heard that i need to get my inversed projection matrix and so on to create a ray from a 2D point to a 3D world point, however since im using OpenglES and there are not as many methods as there would be regulary to help me with this. (And i simply don't know how to do it) im using a trigenomeric formula for this insted.
For each time i iterate one step down the negative Z-axis i multiply the Y-position on the screen (-1 to 1) with
(-z / (cot(myAngle / 2))
And the X position likewise but with a koefficent equally to the aspect ratio.
myAngle is the frustum perspective angle.
This works really good for me and i get very accurate values, so what i wonder is: Why should i use the inverse of the projection matrix and multiply it with some stuff instead of using this?
Most of the time you have a matrix lying around for your OpenGl camera. Using an inverse matrix is simple when you already have a camera matrix on hand. It is also (oh so very slightly at computer speeds) faster to do a matrix multiply. And in cases where you are doing a bajillion of these calculations per frame, it can matter.
Here is some good info on getting started on a camera class if you are interested:
Camera Class
And some matrix resources
Depending on what you are working on, I wouldn't worry too much about the 'best way to do it.' You just want to make sure you understand what your code is doing then keep improving it.
I am trying to map a trajectory path between two point. All I know is the two points in question and the distance between them. What I would like to be able to calculate is the velocity and angle necessary to hit the end point.
I would also like to be able to factor in some gravity and wind so that the path/trajectory is a little less 'perfect.' Its for a computer game.
Thanks F.
This entire physical situation can be described using the SUVAT equations of motion, since the acceleration at all times is constant.
The following explanation presumes understanding of basic algebra and vector maths. If you're not familiar with it, I strongly recommend you go read up on it before attempting to write the sort of game you have proposed. It also assumes you're dealing with 2D, though if you're dealing with 3D most of the same applies, since it's all in vector form - you just end up solving a cubic instead of quadratic, for which it may be best to use a numerical solver.
Physics
(Note: vectors represented in bold.)
Basically, you'll want to start by formulating your equation for displacement (in vector form):
r = ut + (at^2)/2
r is the displacement relative to the start position, u is the initial velocity, a is the acceleration (constant at all times). t is of course time.
a is dependent on the forces present in your system. In the general case of gravity and wind:
a = F_w/m - g j
where i is the unit vector in the x direction and j the unit vector in the y direction. g is the acceleration due to gravity (9.81 ms^-2 on Earth). F_w is the force vector due to the wind (this term disappears for no wind) - we're assuming this is constant for the sake of simplicity. m is the mass of the projectile.
Then you can simply substitute the equation for a into the equation for r, and you're left with an equation of three variables (r, u, t). Next, expand your single vector equation for r into two scalar equations (for x and y displacement), and use substitution to eliminate t (maths might get a bit tricky here). You should be left with a single quadratic equation with only r and u as free variables.
Now, you want to solve the equation for r = [target position] - [start position]. If you pick a certain magnitude for the initial velocity u (i.e. speed), then you can write the x and y components of u as U cos(a) and U sin(a) respectively, where U is the initial speed, and a the initial angle. This can be rearranged and with a bit of trignometry, you can finally solve for the angle a, giving you the launch velocity!
Algorithm
Most of the above description should be worked out on paper first. Then, it's simply a matter of writing a function to solve the quadratic formula and apply some inverse trigonometric functions to get the result.
P.S. Sorry for all the maths/physics in this post, but it was unavoidable! The OP seemed to be asking more about the physical rather than computational side of this, anyway, so that's what I've provided. Hopefully this is still useful to both the OP and other people.
The book:
Modern Exterior Ballistics: The Launch and Flight Dynamics of Symmetric Projectiles ISBN-13: 978-0764307201
Is the modern authority on ballistics. For accuracy you'll need the corrections:
http://www.dexadine.com/mccoy.html
If you need something free and less authoritative, Dr. Mann's 1909 classic The bullet's flight from powder to target is available on books.google.com.
-kmarsh
PS Poor ballistics in games is a particular pet peeve of mine, especially the "shoots flat to infinity" ballistic model.
As people have mentioned, while figuring out the angles between the points is relatively easy, determining the way that wind and gravity will affect the shot is more difficult.
Wind and gravity are both accelrating forces, though they act somewhat differently.
Gravity is easier, since it has both a constant direction (down) and magnitude regardless of the object. (Assuming that you're not shooting things with ridiculously high velocities). To calculate how gravity will affect the velocity of your object, just take the time since you last updated the velocity of the object, multiply it by your gravitational factor, and add it to your current velocity vector.
As a simple example, let's think of an object that is moving with a velocity of (3, 4, 7) in the x, y, z directions, with z being parallel with the force of gravity. You decide that your gravity value is -.3 You are ready to calculate the new velocity. When you check, you discover that 10 time units have passed since your last calculation (whatever your time units are...perhaps ticks or something). You take your time units (10), multiply by your gravity (-.3), which gives you -3. You add that to your Z, and your new velocity is (3, 4, 4). That's it. (This has been very simplified, but that should get you started.)
Wind is a bit different, if you want to do it right. If you want to do it a simple and easy way, you can make it like gravity...a constant force in a particular direction. But a more realistic way is to have the force be dependent on your current velocity vector. Put simply: if you're moving exactly with the wind, it shouldn't impart any force onto you. In this case, you simply calculate the magnitude of the force as the difference between its direction and your own.
A simple example of this might be if you were moving at (3, 0, 0), and the wind was moving at (5, 0, 0), and we can give the wind a strength of .5. (You also have to multiply by the time elapsed...for the sake of this example, to keep it simple, we'll leave the time-elapsed factor at 1) You calculate the difference in the vectors and multiply by your time difference (1), and discover that the difference is (2, 0, 0). You then multiply that vector by the wind strength, .5, and you discover that your velocity change is (1, 0, 0). Add that to your previous velocity, and you get (4, 0, 0)...so the wind has sped the object up slightly. If you waited another single time unit, you would have a difference of (1, 0, 0), multiplied by your strength of .5, so your final velocity would then be (4.5, 0, 0). As you can see, the wind provides less force as you become closer to it in velocity.) This is kind of neat, but may be overly complex for game ballistics.
The angle is easy, atan2(pB.x-pA.x,pB.y-pA.y). The velocity vector should be (pB-pA)*speed. And to add gravity/wind (gravity is just wind with a negative y component) add the (scaled) wind vector to your velocity at every simulation tick (you're basically adding it as acceleration).
Just a link, sorry : http://www.gamedev.net/reference/articles/article694.asp.
There is a lot of papers about game physics at gamedev. Have a look.
(BTW : wind only add some velocity to an object. The hard part is gravity.)