Related
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.
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've been looking at Kevin Beason's path tracer "smallpt" (http://www.kevinbeason.com/smallpt/) and have a question regarding the mirror reflection calculation (line 62).
My understanding of the rendering equation (http://en.wikipedia.org/wiki/Rendering_equation) is that to calculate the outgoing radiance for a differential area, you integrate the incoming radiance over each differential solid angle in a hemisphere above the differential area, weighted by the BRDF and a cosine factor, with the purpose of the cosine factor being to reduce the contribution to the differential irradiance landing on the area for incoming light at more grazing angles (as light at these angles will be spread across a larger area, meaning that the differential area in question will receive less of this light).
But in the smallpt code this cosine factor is not part of the calculation for mirror reflection on line 62. (It is also omitted from the diffuse calculation, but I believe that to be because the diffuse ray is chosen with cosine-weighted importance sampling, meaning that an explicit multiplication by the cosine factor is not needed).
My question is why doesn't the mirror reflection calculation require the cosine factor? If the incoming radiance is the same, but the angle of incidence becomes more grazing, then won't the irradiance landing on the differential area be decreased, regardless of whether diffuse or mirror reflection is being considered?
This is a question that I have raised recently: Why the BRDF of specular reflection is infinite in the reflection direction?
For perfect specular reflection, BRDF is infinite in the reflection direction. So we can't integrate for rendering equation.
But we can make reflected radiance equal the incident according to energy conservation.
The diffuse light paths are, as you suspect, chosen such that the cosine term is balanced out by picking rays proportionally more often in the direction where the cosine would have been higher (i.e. closer to the direction of the surface normal) a good explanation can be found here. This makes the simple division by the number of samples enough to accurately model diffuse reflection.
In the rendering equation, which is the basis for path tracing, there is a term for the reflected light:
Here
represents the BRDF of the material. For a perfect reflector this BRDF would be zero in every direction except for in the reflecting direction. It then makes little sense to sample any other direction than the reflected ray path. Even so, the dot product at the end would not be omitted.
But in the smallpt code this cosine factor is not part of the
calculation for mirror reflection on line 62.
By the definitions stated above, my conclusion is that it should be part of it, since this would make it needless to specify special cases for one material or another.
That's a very good question. I don't understand it fully, but let me attempt to give an answer.
In the diffuse calculation, the cosine factor is included via the sampling. Out of the possible halfsphere of incidence rays, it is more likely a priori that one came directly from above than directly from the horizon.
In the mirror calculation, the cosine factor is included via the sampling. Out of the possible single direction that an incidence ray could have come from, it is more likely a priori - you see where I'm going.
If you sampled coarse reflection via a cone of incoming rays (as for a matte surface) you would again need to account for cosine weighting. However, for the trivial case of a single possible incidence direction, sampling reduces to if true.
From formal perspective cosine factor in the integral cancels out with cosine in denominator of specular BRDF (f_r = delta(omega_i, omega_o)/dot(omega_i, n)).
In different literature, the ideal mirror BRDF is defined by
a specular albedo
dirac deltas (infinite in direction of perfect reflectance, zero everywhere else) and
and 1/cos(theta_i) canceling out the cosine term in the rendering equation.
See e.g.: http://resources.mpi-inf.mpg.de/departments/d4/teaching/ws200708/cg/slides/CG07-Brdf+Texture.pdf, Slide 12
For an intuition of the third point, consider that the differential footprint of the surface covered by a viewing ray from direction omega_r is the same as the footprint of the surface covered by the incident ray from direction omega_i. Thus, all incident radiance is reflected towards omgea_r, independent of the angle of incidence.
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 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.)