I am doing a C# project on ragdolls based on Thomas Jakobsen's article http://www.gpgstudy.com/gpgiki/GDC%202001%3A%20Advanced%20Character%20Physics
I have converted the logic to 2D and everything seems to be working only I am having problems implementing angle constraints.
This is the code I am using at the moment:
public static void SatisfyAngleConstraint(Particle p1, Particle p, float minAngle, float maxAngle)
{
float a1 = (float)Math.Atan2(p1.m_x.X - p1.getFixPoint().X, p1.m_x.Y - p1.getFixPoint().Y);
float a2 = (float)Math.Atan2(p.m_x.X - p.getFixPoint().X, p.m_x.Y - p.getFixPoint().Y);
float diffAngle = a2 - a1;
Game.currentGame.Window.Title = "a " + diffAngle;
//Vector2 OldPosition = p.m_x;
if (diffAngle > maxAngle)
p.m_x = RotatePoint(p.m_x, p.getFixPoint(), (diffAngle - maxAngle));
else if (diffAngle < minAngle)
p.m_x = RotatePoint(p.m_x, p.getFixPoint(), (diffAngle - minAngle));
//p.m_oldx += p.m_x - OldPosition;
}
Particles p1 and p are the joints and getFixPoint() returns the position of parent joint.
RotatePoint(point, centerPoint, angleRad) returns the position of point rotated around centerPoint by angleRad radians.
This code causes severe jitters and due to the fact that I use Verlet integration - I have tried to compensate for this by adding the transformation to the old position as well and that does seem to solve some of my problems but I still experience severe jitters and random force application which leads me to believe that my math is bad.
I am applying this constraint after my distance constraint because the distance between the joints should be constant when I am rotating around the parent joint.
This is my first stackoverflow question so please tell me if my form is bad.
I found the root of my problem was in the way I calculated angles between vectors
A really nice solution to that problem can be found here:
https://stackoverflow.com/a/21486462/2342801
Using this method to calculate a1 and a2 gets rid of the jitters - The problem with this whole approach is that verlet does linear force application to the conflicted joint but what you want is the force to be transferred by rotation to the parent joint (inverse kinematics)
I would therefore recommend a different approach to 2D rag dolls with angle constraints.
Related
I'm trying to create a .bvh file via kinect.
It means in need to get rotations of each bone of a skeleton. I need the rotations in Euler angles. I already tried many different approaches, but any of them gave me good result. Could anyone give me some advice what am I doing wrong?
Here is (I think) the main part of my code.
foreach (Skeleton skeleton in newSkeleton)
{
if (skeleton.TrackingState != SkeletonTrackingState.Tracked)
continue;
int j = 0;
foreach (BoneOrientation orientation in skeleton.BoneOrientations)
{
Matrix4 matrix = orientation.HierarchicalRotation.Matrix;
double y = Math.Asin(matrix.M13);
double x = Math.Atan2(-matrix.M23, matrix.M33);
double z = Math.Atan2(-matrix.M12, matrix.M11);
rotationMatrix[j, 0] = x * 180 / Math.PI;
rotationMatrix[j, 1] = y * 180 / Math.PI;
rotationMatrix[j, 2] = z * 180 / Math.PI;
j++;
}
}
My euler angles should be stored in the rotationMatrix array for further use (saving into bvh file). Here comes my problem... the rotations calculated this way doesn't make sense (I mean they have nothing to do with the position of me ahead of kinect) and they seems to be random.
Edit:
I would also need to explain some unclear topics about kinect. I tried to Google it, but didn't succeed.
Does kinect skeleton have something like zero pose? I mean any pose where all bone rotations are zero. (e.g. T-pose and so on)
What kind of standards does kinect use? I mean how does kinect store data into rotation matrices? I would like to know if the matrix is like
[X1, Y1, Z1,
X2, Y2, Z2,
X3, Y3, Z3]
or does it use some other order?
About the marices.. Is it possible to calculate Euler angles from the matrix given by kinect in standard way? I mean some of algorithms mentioned in this paper?
http://www.geometrictools.com/Documentation/EulerAngles.pdf
OK, after some more time spend researching, i think i might be able to answer some of mine questions. If is anyone interested...
i havent found any zero pose, but i created my own using some kind of calibration. I saved rotation matrices for my chosen zero pose (let's call these Mz), made these matrices trandposed (MzT) and I multiplied all the next matrices kinect gave me (let's call these Mr).
It means I calculated matrices for further use this way: M = MzT x Mr.
I used the conversion from link in 3. question for Rxyz order and all worked well, it means the rotation matrices given by kinect probably have the order given in the question. This should be answer to the third question as well.
I have two objects in a game, which for this purpose can be considered points on a 2d plane, but I use Vector3s because the game itself is 3d.
I have a game camera which I want to align perpendicularly (also on the plane) to the two objects, so that they are both in view of the camera. Due to the nature of the game, the objects could be in any imaginable configuration of positions, so the directional vector between them could have any direction.
Part1: How do I get the perpendicular angle from the two positional vectors?
I have:
Vector3 object1Position; // x and z are relevant
Vector3 object2Position;
I need:
float cameraEulerAngleY;
Part2: Now, because of the way the game's assets are modelled, I want to only allow the camera to view within a 180 degree 'cone'. So if the camera passes a certain point, it should use the exact opposite position the above math might produce.
An image is attached of what I need, the circles are the objects, the box is the camera.
I hope this post is clear and you guys won't burn me alive for being total rubbish at vector math :P
greetings,
Draknir
You'll need to specify a distance from the object line, and an up vector:
Vector3 center = 0.5 * (object2position + object2position)
Vector3 vec12 = object2position - object1position
Vector3 normal = Cross(vec12, up)
normal.Normalize()
Vector3 offset = distance * normal
Vector3 cameraA = center + offset
Vector3 cameraB = center - offset
< choose which camera position you want >
Instead of using Euler angles, you should probably use something like LookAt() to orient your camera.
Assuming Y is always 0 (you mentioned "X and Z" are your relevant components), then you can use some 2-d math for this:
1.Find any perpendicular vector (there are two). You can get this by calculating the difference between the two vectors, swapping the components, and negating one of them.
Vector3 difference = (object1Position - object2Position);
Vector3 perpendicular = new Vector3(difference.z, 0, -difference.x);
2.Using your separating plane's normal, flip the direction of your new vector if it's pointing opposite of intended.
Vector3 separatingPlaneNormal = ...; // down?
if(Vector3.Dot(separatingPlaneNormal, perpendicular ) < 0)
{
perpendicular = -perpendicular ;
}
// done.
Well, for the first bit, if you have points (x1, y1) and (x2, y2) describing the positions of your objects, just think of it in terms of triangles. The angle you're looking for ought to be described by
arctan((y2-y1)/(x2-x1))+90
I don't completely understand what you want to do with the second part, though.
I've been working on a simple program in C# in which a Ball [X,Y] cordinates are periodical incremented.
I've managed to implement a collision detection method, but I'm trying to determine how to reflect the ball at an angle oposed bouncing it back along the same linear path.
dx = -dx //This bounces the ball back along the same linear path
dy = -dy
Solution
Trigonometry
theta = range between 0<theta<=360 depending on where it bounced
x = cos(theta)*time
y= sin(theta)*time
The whole point of Newtonian physics is that it is not random, it is deterministic. If you throw the same ball against the same wall at the same angle and with the same velocity and the same spin, it goes to the same place every time.
This sort of program is a really great learning opportunity for both programming and physics. What I encourage you to do is to first write a program that simulates very simple bouncing. As you note, when an object is moving straight down and hits a horizontal surface, then you can model the bounce as simply reversing the vertical velocity component. Just get that right; no gravity, no nothing. That's a great start.
Then try adding bouncing off of horizontal walls, the same way.
Then try adding bouncing off of walls that are not aligned with horizontal or vertical directions. That's where you're going to have to learn how vectors and trigonometry work, because you'll have to work out what component of the ball's velocity is changed by striking the wall obliquely.
Then add gravity. Then add friction from the air. Then add the fact that the ball can be spinning. Add elasticity, so that you can model deformation of the ball.
Once you get to that point, if you want to introduce randomness you'll be able to figure out how to do it. For example, you might introduce randomness by saying "well, when the ball strikes the wall and deforms, I'll introduce a random element that changes its deformation by 0-10%". That will then change how the simulation bounces the ball. You can experiment with different kinds of randomness: add random air currents, for instance.
You will have to add in randomness yourself. To rephrase your question: "Deterministically, it bounces off at angle theta. How can I make it bounce back at angle theta + epsilon, where epsilon is some random value?"
To rotate a vector, see this. You will just specify theta.
pseudocode:
RotateVector(vec):
bounce_vec = [-vec.x vec.y]; //deterministic answer is negative x, normal y
bounce_angle = acos(dot(vec,bounce_vec) / (norm(vec)*norm(bounce_vec)));
modified_angle = bounce_angle + random_number();
ca = cos(modified_angle);
sa = sin(modified_angle);
rotation_matrix = [ca -sa; sa ca];
return rotation_matrix * vec;
Line 3 uses the law of cosines to figure out the angle. In line 4, that angle is modified randomly. The rest of the function rotates the original vector by your new angle.
As long as it's a perfect ball with a perfect surface it will not bounce back randomly. Neither vectors nor trigonometry will give you any randomness.
"randomly, though applying to the basic laws of physics" seems like an oxymoron. However...
If you want it to bounce in a random direction, while maintaining its current speed, you might do something like this (pseudocode):
first, bounce back the canonical way (dx = -dx or dy = -dy depending on the collision)
then convert the dx and dy to polar coordinates (theta and r)
jitter theta by a small amount (+ or - a few degrees, according to your taste)
make sure theta isn't heading into a wall that you just bounced off
convert theta and r back to dx and dy
That would be conserving scalar momentum.
I am currently experimenting with some physics toys in XNA using the Farseer Physics library, however my question isn't specific to XNA or Farseer - but to any 2D physics library.
I would like to add "rocket"-like movement (I say rocket-like in the sense that it doesn't have to be a rocket - it could be a plane or a boat on the water or any number of similar situations) for certain objects in my 2D scene. I know how to implement this using a kinematic simulation, but I want to implement it using a dynamic simulation (i.e. applying forces over time). I'm sort of lost on how to implement this.
To simplify things, I don't need the dynamics to rotate the geometry, just to affect the velocity of the body. I'm using a circle geometry that is set to not rotate in Farseer, so I am only concerned with the velocity of the object.
I'm not even sure what the best abstraction should be. Conceptually, I have the direction the body is currently moving (unit vector), a direction I want it to go, and a value representing how fast I want it to change direction, while keeping speed relatively constant (small variations are acceptable).
I could use this abstraction directly, or use something like a "rudder" value which controls how fast the object changes directions (either clockwise or counter clockwise).
What kind of forces should I apply to the body to simulate the movement I'm looking for? Keep in mind that I would also like to be able to adjust the "thrust" of the rocket on the fly.
Edit:
The way I see it, and correct me if I'm wrong, you have two forces (ignoring the main thrust force for now):
1) You have a static "fin" that is always pointed in the same direction as the body. If the body rotates such that the fin is not aligned with the direction of movement, air resistance will apply forces to along the length of the fin, proportional to the angle between the direction of movement and the fin.
2) You have a "rudder", which can rotate freely within a specified range, which is attached some distance from the body's center of mass (in this case we have a circle). Again, when this plane is not parallel to the direction of movement, air resistance causes proportional forces along the length of the rudder.
My question is, differently stated, how do I calculate these proportional forces from air resistance against the fin and rudder?
Edit:
For reference, here is some code I wrote to test the accepted answer:
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
float dc = 0.001f;
float lc = 0.025f;
float angle = MathHelper.ToRadians(45);
Vector2 vel = new Vector2(1, 0);
Vector2 pos = new Vector2(0, 0);
for (int i = 0; i < 200; i++)
{
Vector2 drag = vel * angle * dc;
Vector2 sideForce = angle * lc * vel;
//sideForce = new Vector2(sideForce.Y, -sideForce.X); // rotate 90 degrees CW
sideForce = new Vector2(-sideForce.Y, sideForce.X); // rotate 90 degrees CCW
vel = vel + (-drag) + sideForce;
pos = pos + vel;
if(i % 10 == 0)
System.Console.WriteLine("{0}\t{1}\t{2}", pos.X, pos.Y, vel.Length());
}
}
When you graph the output of this program, you'll see a nice smooth circular curve, which is exactly what I was looking for!
If you already have code to integrate force and mass to acceleration and velocity, then you just need to calculate the individual part of each of the two elements you're talking about.
Keeping it simple, I'd forget about the fin for a moment and just say that anytime the body of your rocket is at an angle to it's velocity, it will generate a linearly increasing side-force and drag. Just play around with the coefficients until it looks and feels how you want.
Drag = angle*drag_coefficient*velocity + base_drag
SideForce = angle*lift_coefficent*velocity
For the rudder, the effect generated is a moment, but unless your game absolutely needs to go into angular dynamics, the simpler thing to do is let the rudder control put in a fixed amount of change to your rocket body angle per time tick in your game.
I suddenly "get" it.
You want to simulate a rocket powered missile flying in air, OK. That's a different problem than the one I have detailed below, and imposes different limits. You need an aerospace geek. Or you could just punt.
To do it "right" (for space):
The simulated body should be provided with a moment of inertia around its center of mass, and must also have a pointing direction and an angular velocity. Then you compute the angular acceleration from the applied impulse and distance from the CoM, and add that to the angular velocity. This allows you to compute the current "pointing" of the craft (if you don't use gyros or paired attitude jets, you also get a (typically very small) linear acceleration).
To generate a turn, you point the craft off the current direction of movement and apply the main drive.
And if you are serious about this you also need to subtract the mass of burned fuel from the total mass and make the appropriate corrections to the moment of inertia at each time increment.
BTW--This may be more trouble than it is worth: maneuvering a rocket in free-fall is tricky (You may recall that the Russians bungled a docking maneuver at the ISS a few years ago; well, that's not because they are stupid.). Unless you tell us your use case we can't really advise you on that.
A little pseudocode to hint at what you're getting into here:
rocket {
float structuralMass;
float fuelMass;
point position;
point velocity;
float heading;
float omega; // Angular velocity
float structuralI; // moment of inertia from craft
float fuelI; // moemnt of inertia from the fuel load
float Mass(){return struturalMass + fuelMass};
float I(){return struturalI + fuelI};
float Thrust(float t);
float AdjustAttitude(float a);
}
The upshot is: maybe you want a "game physics" version.
For reason I won't both to go into here, the most efficient way to run a "real" rocket is generally not to make gradual turns and slow acceleration, but to push hard when ever you want to change direction. In this case you get the angle to thrust by subtracting the desired vector (full vector, not the unit) from the current one. Then you pointing in that direction, and trusting all out until the desired course is reached.
Imagine your in floating in empty space... And you have a big rock in your hand... If you throw the rock, a small impulse will be applied to you in the exact opposite direction you throw the rock. You can model your rocket as something that rapidly converts quantum's of fuel into some amount of force (a vector quantity) that you can add to your direction vector.
I've scored the internet for sources and have found a lot of useful information, but they are math sites trying to tell me how to solve what angle an object has to be at to reach y location. However, I'm trying to run a simulation, and haven't found any solid equations that can be implemented to code to simulate a parabolic curve. Can those with some knowledge of physics help me on this?
While Benny's answer is good, especially in its generality, you can solve your problem exactly rather than using finite integration steps. The equation you want is:
s = u*t + 0.5*a*t^2;
Look here for an explanation of where this comes from.
Here s is the displacement, u is the initial speed, a is the acceleration and t is time. This equation is only 1 dimensional, but can be easily used for your problem. All you need to do is split the motion of your projectile into two components: one parallel to your acceleration and one perpendicular. If we let Sx describe the displacement in the x direction and Sy the displacement in the y direction we get:
Sx = Ux*t + 0.5*Ax*t;
Sy = Uy*t + 0.5*Ay*t;
Now in your particular example Ax is 0 as the only acceleration is due to gravity, which is in the y direction, ie Ay = -g. The minus comes from the fact that gravity will be acting in the opposite direction to the original motion of the object. Ux and Uy come from simple trigonometry:
Ux = U*cos(angle);
Uy = U*sin(angle);
Putting this all together you get two equations describing where the projectile will be at a time t after being launched, relative to its starting position:
Sx = U*cos(angle)*t;
Sy = U*sin(angle)*t - 0.5*g*t^2;
Don't use the equations for position. Instead, use the equations for velocity. Calculate the new velocity each loop of your simulation from the object's old velocity and apply it to your object. You will need to know the elapsed time between each loop of the simulation. Of course, this works for vertical or horizontal velocity.
v_new = v_old + acceleration * delta_time (from wikipedia)
Then apply:
position_new = position_old + v_new * delta_time;
You can use a simple acceleration of -9.8 m/s (don't forget that "down" on the screen is really an increase in the vertical position! So you can use +9.8 for simplicity). Or you could get fancy and add variable acceleration (for example, from wind, if you are also modeling the horizontal motion of the object).
Basically, the acceleration you apply is based on the sum of forces applied to the object (force of gravity, friction, jet propulsion, etc.).
F_final = F1 + F2 + ... + Fn
The following can help you with that.
If you are modeling a force applied to the object, first break the force into it's horizontal and vertical components using:
F_horiz = F * sin( angle )
F_vert = F * cos( angle ) where angle is the angle between the force and the horizontal.
Then calculate the acceleration from the force using:
a = F / mass
(I give all credit for this knowledge to my first programming experience: GORILLA.BAS =) )
Some definitions:
x = x-coordinate (horizontal)
y = y-coordinate (vertical)
Vx = x-velocity
Vy = y-veloctiy
t = time
A = initial angle
V0 = intial velocity
g = acceleration due to gravity
Some equations:
Vx = V0*cos(A)
Vy = V0*sin(A) - g*t
x = V0*cos(A)*t
y = V0*sin(A)*t - (1/2)*g*t^2
Heres a nice library that might help you
http://sites.google.com/site/physics2d/
I haven't looked into it too much to be honest, I came across it in Scott Whitlock's code project article.
http://www.codeproject.com/KB/WPF/SoapBoxCorePinBallDemo.aspx