I'd like to build a game to learn cocos2d. Lunar lander is the first exercise coming in my mind. Any pointer/source code/tutorial of the physics calculations required will be appreciated. Thanks!
You'll need stuff like this:
Newton's laws of motion in 2D.
Ability to change effect of gravity. 9.8 m/s^2 is the right acceleration on earth, but you should be able to change this to the appropriate value for Mars, moon, Jupiter, etc.
Ability to turn thrusters off and on to counteract the effect of gravity. Not a very interesting game if you don't, because every one ends in a crash.
Way to relate duration of thruster fire with fuel consumption. If you don't manage fuel well you crash.
Initial conditions (e.g., height above surface, initial velocity, initial fuel, etc.)
You'll start with initial conditions and loop over a number of time steps. At the end of each step you'll check the position and velocity. If the y-position above the surface is zero or negative you'll have landed. If the velocity is greater than a critical y-value you'll have a crash; less than the critical value means a safe, soft landing.
You'll solve Newton's equations of motion numerically. In your case it's four coupled, first order ordinary differential equations: rate of change of velocity in x- and y-directions and rate of change of position in x- and y-directions. If you have the thrusters in place you'll add another equation for conservation of mass for the fuel.
You can eliminate two equations if you assume that there are no x-components: the lunar lander moves perpendicular to the surface, the thruster force only has a non-zero component in the vertical direction. If that's true, you're down to three equations.
You'll do time stepping, so it'll be good to read up integration techniques like explicit Euler or implicit 5th order Runge-Kutta.
A challenging problem - not trivial. Good luck.
The math you need for a lunar lander game is pretty straightforward. Newton's Laws of Motion are all you really need - just pick up a basic physics textbook. You should be set after the first chapter. There are only two force inputs in the system - gravity and thrust from the engines. Just calculate the vertical & horizontal components of the motion, and animate your spaceship accordingly.
The physics are very simple: http://csep10.phys.utk.edu/astr161/lect/history/newtongrav.html
I assume you won't be worrying about drag or wind, so depending on your angles of inclination (user input), you'll be implementing:
Sourced from: http://en.wikipedia.org/wiki/Trajectory. You can even probably get away with simplifying it. If you don't want to be super-accurate, you can just do something like F=ma where is is whatever you decide the gravitational acceleration to be (9.8 m/s² on Earth).
If your game is in 2D, You don't need much math, you need physics, Specifically basic Newtonian motion. Probably intro college or late high school. The math is some grade school algebra with early high school calculus.
If you look at up-down motion, then your ship is essentially an object that is exposed to a force of gravity (the constant depends on your "moon") negated by the force emitted by its engines. You can use that to determine acceleration and from there velocity. Using the velocity, you can do your collision-outcome. The left-and-right motion is easier, since if your moon has no atmosphere, you are merely applying a constant force.
If you want something more realistic, you can modify the gravity constant based on distance from the surface, and can add an atmospheric friction force (though it wouldn't really be our moon).
If your game is in 3D, and your ship has side thrusters in addition to bottom thrusters, then you would not only have motion in location but also rotation. That has to do with rigid body physics. AFAIK that involves college level calculus.
This may be overkill, but I recommend looking at Numerical Recipes -- read the chapter on ordinary differential equations. You don't even need to study the entire chapter; just the first couple of sections.
In two dimensions, on every time tick you want to add the ship's rotational thrust to its rotational velocity, add its rotational velocity to its current heading, compute a thrust vector by multiplying the sine and cosine of its heading by its main thruster output, add that vector and a gravity vector (a straight downward vector of some magnitude) to its current velocity, and add its current velocity to its position. If the timer ticks are small enough, that's pretty much all you have to do, other than check to see if the craft is in contact with the ground. Experiment with the magnitude of your thrust and gravity values until you have a playable game.
Related
I have a big spherical Gameobject which moves forward in 3D with constant velocity. I have other spherical objects that other big object needs to attract to itself. I am using Newton's law of universal gravitation formula to attract other objects, but as expected, other objects are doing a slingshot movement much like the space shuttles doing when needed with other planets' orbits to accelerate.
I actually want a magnetic effect that without taking the masses into account, all other objects will be catched by the big object. How can I do that? Do I need a different formula? Or do I need to change the movement behavior of the objects altogether?
If I got it right you expect to have something like this: https://www.youtube.com/watch?v=33EpYi3uTnQ
You can do a spherical raycast or have an sphere collider as trigger to detected the objects that are inside of your magnetic field.
Once you know those objects you can calculate the distance from each of them to the magnetic ball.
You can make an inverse interpolation to know how much strength/"magnetism" is getting into that object.
Then you can apply some force on the attracted object towards the magnetic ball's center.
Something like this algorithm:
var objectsInsideField = ListOfObjects;
foreach (o in objectsInsideField) {
var distance = (o.position - center.position).magnitude;
var strength = distance / fieldRadius; // fieldRadius == spherical radius
o.AddForce(dir: o.position - center.position, strength: strength)
}
Of course, you need to do some adjustments and probably add some multipliers to make the force to be meaning.
The final result should be: for each sequential frame, if the object is inside the magnetic field it moves towards the center a bit. The next frame it should be even close to the center so the strength is even bigger.. and so and so.
First of all, since the big objects is moving with constant velocity, a coordinate frame with axes parallel to the axes of the original coordinate system will be moving uniformly with constant velocity, so this new moving coordinate system is also inertial and you can write all your equations of motion in it, calculate everything with respect to it, and at the end you add the uniform movement to the results. The benefit is that the big object is stationary in this coordinate system, so simpler physics applies.
The slingshot effect occurs most likely because your objects are treated as mass-points, rather than bigger 3D entities (like spheres), for which the centers of mass never get too close enough. Hence maybe some sort of collision detection may eliminate this problem, especially if you decrease significantly or kill completely the elastic collision resolution.
All of what I am saying is a bit speculative as I have no access to details.
Im simulating a swing door with generator using Simscape/Simulink. I imagine there is only one input for system which is the force at the knob needed to open the door, so all revolute joints have their torque actuation set to automatically computed. However, im getting an error saying:
"In the dynamically coupled component containing Revolute Joint 'SDL/SwingMotion', there are more joint primitive degrees of freedom with automatically computed force or torque (4) than with motion from inputs (0). In general, the equations of motion do not have a unique solution. Solve this problem by increasing the number of joint primitives with motion from inputs or reducing the number of joint primitives with automatically computed force or torque. Resolve this issue in order to simulate the model."
The animation works fine if i set the torque actuation of all 4 revolute joints to none, but the torque produced by the force wont be transfered this way and the generator shaft wont have any torque. However, I am able to measure the output RPM (angular velocity of generator shaft). I dont quite understand the error. Why do the revolute block treats the degree of motion of other revolute blocks as its own? How do i resolve this?
Block Diagram can be seen here.
The Assembly looks like this:
Any help is much appreciated!
For a revolute joint there are three options:
Let the revolute joint just act as a hinge, no torque can be exerted from base to follower and vice versa
Provide torque and calculate motion from the torque. This is called forward dynamics, motion is determined from torque.
Provide motion and calculate torque from the motion. This is called inverse dynamics, torque is determined from motion.
So you have to select either one of the option. If you select torque automatically computed, then you need to provide the motion which it has to follow. If you don't need to follow a provided motion, than no torque is needed.
If you set torque computed to 'none', then there is no torque that can be exerted from the base to the follower and vice versa, that is the idea of a Degree of Freedom.
It seems as if you want the Base and the Follower to be somewhat rigidly connected and follow the same motion. Than you can consider using the Rigid Transform block, which is just a rigid link in which you can define a translation or rotation offset.
EDIT
What you were effectively doing was combining forward and inverse dynamics. You put a force on the doorknob, let Simulink calculate the motion (up till now forward dynamics) then you desire the torque on the GenShaft from the motion it is doing, which is inverse dynamics. That does not work.
A better way to check the torque on the GenShaft is to, for instance, desire a certain door hinge angular velocity, put a proportional controller on it, and check the required torque. Notice that with no friction modeled in the hinge the required torque will go to zero.
So if you set all torque computed to 'none' except for the GenShaft, set this to provided by input. Then put a proportional controller on the angular velocity of the door hinge. You can then check the torque needed.
Updated model
I have a record session for my application. When user started a record session I start collecting data from device's CMMotionManager object and store them on CoreData to process and present later. The data I'm collecting includes gps data, accelerometer data and gyro data. The frequency of data is 10Hz.
Currently I'm struggling to calculate the lean angle of device with motion data. It is possible to calculate which side of device is land by using gravity data but I want to calculate right or left angle between user and ground regardless of travel direction.
This problem requires some linear algebra knowledge to solve. For example for calculation on some point I must calculate the equation of a 3D line on a calculated plane. I am working on this one for a day and it's getting more complex. I'm not good at math at all. Some math examples related to the problem is appreciated too.
It depends on what you want to do with the collected data and what ways the user will go with that recording iPhone in her/his pocket. The reason is that Euler angles are no safe and especially no unique way to express a rotation. Consider a situation where the user puts the phone upright into his jeans' back pocket and then turns left around 90°. Because CMAttitude is related to a device lying flat on the table, you have two subsequent rotations for (pitch=x, roll=y, yaw=z) according to this picture:
pitch +90° for getting the phone upright => (90, 0, 0)
roll +90° for turning left => (90, 90, 0)
But you can get the same position by:
yaw +90° for turning the phone left (0, 0, 90)
pitch -90° for making the phone upright (-90, 0, 90)
You see two different representations (90, 90, 0) and (-90, 0, 90) for getting to the same rotation and there are more of them. So you press Start button, do some fancy rotations to put the phone into the pocket and you are in trouble because you can't rely on Euler Angles when doing more complex motions (s. gimbal lock for more headaches on this ;-)
Now the good news: you are right linear algebra will do the job. What you can do is force your users to put the phone in always the same position e.g. fixed upright in the right back pocket and calculate the angle(s) relative to the ground by building the dot product of gravity vector from CMDeviceMotion g = (x, y, z) and the postion vector p which is the -Y axis (0, -1, 0) in upright position:
g • x = x*0 + y*(-1) + z*0 = -y = ||g||*1*cos (alpha)
=> alpha = arccos (-y/9.81) as total angle. Note that gravitational acceleration g is constantly about 9.81
To get the left-right lean angle and forward-back angle we use the tangens:
alphaLR = arctan (x/y)
alphaFB = arctan (z/y)
[UPDATE:]
If you can't rely on having the phone at a predefined postion like (0, -1, 0) in the equations above, you can only calculate the total angle but not the specific ones alphaLR and alphaFB. The reason is that you only have one axis of the new coordinate system where you need two of them. The new Y axis y' will then be defined as average gravity vector but you don't know your new X axis because every vector perpedicular to y' will be valid.
So you have to provide further information like let the users walk a longer distance into one direction without deviating and use GPS and magnetometer data to get the 2nd axis z'. Sounds pretty error prone in practise.
The total angle is no problem as we can replace (0, -1, 0) with the average gravity vector (pX, pY, pZ):
g•p = xpX + ypY + zpZ = ||g||||p||*cos(alpha) = ||g||^2*cos(alpha)
alpha = arccos ((xpX + ypY + z*pZ) / 9.81^2)
Two more things to bear in mind:
Different persons wear different trowsers with different pockets. So the gravity vector will be different even for the same person wearing other clothes and you might need some kind of normalisation
CMMotionManager does not work in the background i.e. the users must not push the standby button
If I understand your question, I think you are interested in getting the attitude of your device. You can do this using the attitude property of the CMDeviceMotion object that you get from the deviceMotion property of the CMMotionManager object.
There are two different angles that you might be interested in the CMAttitude class: roll and pitch. If you imagine your device as an airplane with the propeller at the top (where the headphone jack is), pitch is the angle the plane/device would make with the ground if the plane were in a climb or dive. Meanwhile, roll is the angle that the "wings" would make with the ground if the plane were to be banking or in mid barrel roll.
(BTW, there is a third angle called yaw that I think is not relevant for your question.)
The angles will be given in radians, but it's easy enough to convert them to degrees if that's what you want (by multiplying by 180 and then dividing by pi).
Assuming I understand what you want, the good news is that you may not need to understand any linear algebra to capture and use these angles. (If I'm missing something, please clarify and I'd be happy to help further.)
UPDATE (based on comments):
The attitude values in the CMAttitude object are relative to the ground (i.e., the default reference frame has the Z-axis as vertical, that is pointing in the opposite direction as gravity), so you don't have to worry about cancelling out gravity. So, for example, if you lie your device on a flat table top, and then roll it up onto its side, the roll property of the CMAttitude object will change from 0 to plus or minus 90 degrees (+- .5pi radians), depending on which side you roll it onto. Meanwhile, if you start it lying flat and then gradually stand it up on its end, the same will happen to the pitch property.
While you can use the pitch, roll, and yaw angles directly if you want, you can also set a different reference frame (e.g., a different direction for "up"). To do this, just capture the attitude in that orientation during a "calibration" step and then use CMAttitude's multiplyByInverseOfAttitude: method to transform your attitude data to the new reference frame.
Even though your question only mentioned capturing the "lean angle" (with the ground), you will probably want to capture at least 2 of the 3 attitude angles (e.g., pitch and either roll or yaw, depending on what they are doing), potentially all three, if the device is going to be in a person's pocket. (The device could rotate in the pocket in various ways if the pocket is baggy, for example.) For the most part, though, I think you will probably be able to rely on just two of the three (unless you see radical shifts in yaw throughout the course of a recording session). So for example, in my jeans pocket, the phone is usually nearly vertical. Thus, for me, pitch would vary a whole bunch as I, say, walk, sit or run. Roll would vary whenever I change the direction I'm facing. Meanwhile, yaw would not vary much at all (unless I do kart-wheels, which I can't!). So yaw can probably be ignored for me.
To summarize the main point: to use these attitude angles, you don't need to do any linear algebra, nor worry about gravity (although you may want to use this for other purposes, of course).
UPDATE 2 (based on Kay's new post):
Kay just replied and showed how to use gravity and linear algebra to make sure your angles are unique. (And, btw, I think you should give the bounty to that post, fwiw.)
Depending on what you want to do, you may want to use this math. You would want to use the linear algebra and gravity if you need a standardized way of "talking about" and/or comparing attitudes over the course of your recording session. If you just want to visualize them, you can probably still get away with not using the increased complexity. (For example, visualizing (pitch=90, roll=0, yaw=0) should be the same as visualizing (pitch=0, roll=90, yaw=90).) In my approach above, while you could have multiple ways of referring to the "same" attitude, none of them is actually wrong, per se. They will still give you the angles relative to the ground.
But the fact that the gyroscope can switch from one valid description of an attitude to another means that what I wrote above about getting away with only 2 of the 3 components needs to be corrected: because of this, you will need to capture all three components, no matter what. Sorry.
I have a ball that you blow on with air. I want the ball to be blown more if it is close to the blower and blown less if it is farther away from the blower. I am using box2d and I am using the impulse function."body->ApplyLinearImpulse(force, body->GetPosition())". I can't seem to find a formula or a way to accomplish this. If I want the ball to blow to a total distance of 300 pixels right, how could I accomplish this? Please help.
If you want to calculate the distance before simulation you have to take a look at box2d sources. When simulating the velocity of the body is modified according to gravity, extra applied forces, linear damping, angular damping and possibly something more. Also velocity relies on velocity iterations.
But I think if you want a really smooth motion (like from a blow) you'd better use applyForce function instead of impulse. But be sure you are applying the force each simulation step.
EDIT:
Also you can simulate the air resistance as:
Fa = -k*V*V. I've simulated movement in the pipe this way. Worked great.
So each step you can make something like this:
BlowForce = k1 / distance; // k1 - coefficient
Resistance = -k2 * V * V; //k2 - another coefficient
TotalForce = BlowForce + Resistance;
body->ApplyForce(TotalForce);
I am not a box 2d expert but what i would do is create a small box which is actually invisible and let the ball hit the box...if the blower is blowing more i would give more speed to the box in opposite direction. As far as 300 pixel length is concerned you have to adjust the forces and velocity such that the ball goes
300/<your_rendering_window_to_physics_world_ratio>
in physical world.
Force = mass * acceleration, so take the mass you set your body to, calculate the acceleration you want (remember to divide 300px by PTM_RATIO) and then multiply the two together.
Is it possible to determine the speed at which someone is shaking their iPhone? This would be the time they start moving to the ending point where they are now going back to the origin. Basically it is one swipe that I'd like to measure the speed of. This discussion comments on initial speed: http://discussions.apple.com/message.jspa?messageID=8297689#8297689. It seems that the important component of distance is lacking in the iPhone to get a good measure of speed.
Sure, it sounds like all you'd need to do would be to numerically integrate the acceleration twice to get the distance traveled. For instance, look at
Calculate the position of an accelerating body after a certain time
Note that you'll have to subtract gravity from the measured acceleration to get the kinetic acceleration, which is what you should integrate. As for how to do that, re: GoatRider's comment: I might try storing the last measured acceleration whose magnitude was equal to gravity (I think that's 1 in iPhone units?). Then for each acceleration measurement you make whose magnitude is greater than 1, subtract the last known acceleration of gravity - this will need to be a vector subtraction - and use that as the kinetic acceleration. Of course, this assumes that the user keeps the phone in the same orientation throughout the swipe, which I think would be approximately true.
Unfortunately, there's no technique you can use to distinguish between gravitational acceleration and kinetic acceleration in general - that is, a determined user could always find a way to fool whatever algorithm you might come up with. (Trivia: that's called the equivalence principle, and it's the foundation of Einstein's theory of general relativity)
You'll have to do the calculations yourself. Each acceleration event you receive will tell you the relative G-forces registering on the accelerometer and the time at which the event was recorded. You'll have to sample over several events and interpolate. Here's more info on the acceleration event itself:
UIAcceleration Class Reference