Circular Motion

Started by
3 comments, last by apatriarca 14 years, 1 month ago
Hi everyone, that's the issue: I just want to make my entity (wich I normally move with the basic m_vPosition + m_vDirection * m_vSpeed) to move in a circular motion! I've read for about a day physical explanation of this motion, but I cannot find what I look for: How can I reproduce this in C#? I just figured out how to get the radius: I assume I just need to create a vector vCenter, calculate the difference between my position and the center obtaining a vector which lenght is the radius of the circumference! wheather I shall use the direction of my entity and rotate that as it would be the v vector shown in the picture above: i don't know! as for the centripetal force, to calculate it i need the acceleration, to calculate acceleration i need velocity, to calculate velocity I need an angle wich I don't know to get and don't even now if I could just throw in a float angle with a user-determined value... In other terms: I'm in desperate need of assistance here!
Advertisement
A few clarifying Q's...

Are we talking scripted motion or is it supposed to be physics based ie. caused by forces? Is this going to happen inside some physics / graphics / game engine or are you planning to write this bý hand?

cheers,
Mike
It's for a game that I'm developing with some friends! We are using C#, XNA and a private Engine!

Does that make things more clear?
Based on the figure, this is how you could achieve what you want:

1)Since you want your rigid body to rotate along a circle with constant speed, we do for each frame:
vehicle.angular_velocity = constant;//you define it to the value desiredacceleration = cross_product( vehicle.angular_velocity, vehicle.linear_velocity );

2)We can therefore compute the force to be applied to the vehicle. It is:
vehicle.force_accumulator = vehicle.mass * acceleration;vehicle.position += vehicle.linear_velocity * dt;vehicle.linear_velocity += vehicle.force_accumulator * ( dt / vehicle.mass );/*yes, we could have done:vehicle.linear_velocity += acceleration * dtbut I am quite use to compute variations of linear_momentum and compute velocities from it*/

3)The rate of variation of the orientation is:
dR = skew_symmetric_matrix( vehicle.angular_velocity ) * vehicle.orientationMatrix3 const skew_symmetric_matrix( Vector3 const & vec ){   return Matrix3(      0, -vec.z, vec.y,      vec.z, 0, -vec.x,      -vec.y, vec.x, 0   );}vehicle.orientation += dR * dt;orthonormalize( vehicle.orientation );


This won't give you a perfect circular motion( due to the re-orthonormalization of vehicle.orientation, and some other subtle things ). The faster you'll rotate the vehicle, the greater the error will be: so the faster you rotate the vehicle, the smaller the timestep.
As you've probably understood, vehicle.orientation is a 3x3 matrix. You could use an angle, but actually, I never use things like Vector2, or Matrix22 data structure, since, Vector3 and Matrix33, are sufficient for every type of problem in an euclidian space. Here, the vehicle.orientation will have vehicle.orientation(0,2)=vehicle.orientation(2,0)=
vehicle.orientation(1,2)=vehicle.orientation(2,1)=0

and vehicle.orientation(2,2)=1 ( after of course re-orthonormalization )

and all other vector3 variables will have their third component equal to zero, except the angular velocity who will verify the following property:
vehicle.angular_velocity(0)=vehicle.angular_velocity(1)=0
and vehicle.angular_velocity(2) != 0 will evaluate to true.

P.S: yes, this is C++ code...The C# implementation is left as an exercise for the reader.
edit
the equations I used are:

angular_velocity(t)=constant_vector_3//Vector3(0,0,constant_float)
acceleration(t)=skew_symmetric_matrix(angular_velocity(t))*velocity(t)
d(position(t))/dt = linear_velocity(t)
d(linear_velocity(t))/dt=acceleration(t)
d(orientation(t))/dt = skew_symmetric_matrix(angular_velocity(t))*orientation(t)

And I used the Integration Method of Euler, the simplest one, to compute position(t+dt), linear_velocity(t+dt) and orientation(t+dt). But you can use any other method(generally I use the fourth order Runge-Kutta method, RK4 pour les intimes.

[Edited by - johnstanp on March 10, 2010 12:10:25 PM]
A circumference in 2D is defined by the parametric equation
P(θ) = C + R*(cosθ, sinθ).
The angle θ is the angle between the line with direction (cosθ, sinθ) and the x-axis. r = R*(cosθ, sinθ) is the vector you have calculated in your code.

By basic calculus, the velocity of your object is the derivative of the position P(θ(t)) with respect to time t. It is quite easy to get the following formula:
v(t) = d/dt P(θ(t)) = d/dt (C + R*(cos(θ(t)), sin(θ(t)))) = R*(d/dt θ(t))*(-sin(θ(t)), cos(θ(t))).
ω(t) = (d/dt θ(t)) is the angular velocity.

There are two important considerations:
1. The vector r and the velocity v are perpendicular:
dot(r, v) = R*R*ω*(-cosθsinθ + sinθcosθ) = 0
2. The velocity can be calculated without any cross product. Indeed, if r = (rx, ry) the velocity is v = (-ω*ry, ω*rx)

The acceleration is
a(t) = d/dt v(t) = d/dt (R*ω(t)*(-sin(θ(t)), cos(θ(t)))) = R*(d/dt ω(t))*(-sin(θ(t)), cos(θ(t))) + R*ω(t)*(-cos(θ(t)), -sin(θ(t))).
(d/dt ω(t)) is the angular acceleration and, if the angular velocity is constant, it is zero and the acceleration is parallel to r and with opposite direction. So, if r = (rx, ry), a = (-ω*rx, -ω*ry).

In code it is something like (pseudocode):
Vector2 radius = position - center;Vector2 velocity(- angular_velocity * radius.y, angular_velocity * radius.x);Vector2 acceleration = - angular_velocity * radius;Vector2 force = mass * acceleration;

You can then use the integration method you prefer.

Note that you probably have to 'renormalize' the radius to be sure the object is on the circumference and it is probably better to simply do a rotation around the point.

This topic is closed to new replies.

Advertisement