Say I have an object next to me at my desk right now, and a java object in the program I am working on. If I were to drop the real object it would accelerate downwards at a speed of 9.81 m/s (ignoring wind resistance), thus the velocity would be 9.81 m/s/s and the overall position would be (-)9.81 m/s/s/s relative to where it started.
Now if I wrote a java program with my java object simulating this I would do it like such
public class HypotheticalObjectClass(){
double position = 0, velocity = 0;
tick(){
velocity += 9.81;
position += velocity;
}
}
This program is accurate as long as I have it calling tick() once a second, but if it's called multiple times a second the position skyrockets because of calculus or whatever... I intend to have this program tick multiple times a second, so how would I correct the calculation given only instantaneous values (such as velocity, position, rotation, etc...) and, if it is not possible, what system do I need to add to make it possible?
Sorry if this question was already addressed on this site, I have no idea how I'd find it, and thank you for your help.
You need to know the time difference between your tick calls, then you can scale acceleration and speed according to it.
public class HypotheticalObjectClass(){
double position = 0, velocity = 0;
public void tick(double dt) {
velocity += 9.81 * dt;
position += velocity * dt;
}
}
If accelaration is in units/s^2 and speed in units/s then dt is the time difference in seconds between function calls. So if you call it once a second, you should call it obj.tick(1.0). However the best idea is to measure time between calls because, as you mentioned, the time difference is not always exactly the same.
Note that this method is quite inaccurate, however it is often good enough. For more information about physics simulation see: http://gafferongames.com/game-physics/integration-basics/
Related
There seems to be a lot of confusing/conflicting advice out there about when you should or should not multiply a quantity by Time.deltaTime. So I was wondering, as it pertains to the Unity physics system, when should you multiply by Time.deltaTime?
I understand that Time.deltaTime is used to make certain actions framerate independent, but there are some situations where it isn't clear whether an action is framerate independent. For instance:
Doing rigidbody.velocity += acceleration*Time.deltaTime; in FixedUpdate. Since FixedUpdate runs at a constant timestep, does this make the multiply by Time.deltaTime unnecessary?
Doing rigidbody.AddForce(force*Time.deltaTime, forceMode);. How do the various ForceModes effect this?
I've seen solutions to individual situations, but it would be nice if there were a simple intuition which could address all of these situations.
The intuition
Multiplying by Time.deltaTime is used to make an instantaneous operation act in a continuous (or "smooth") way.
An instantaneous operation will cause a certain quantity to "jump" to a different value. The following operations are instantaneous:
Rigidbody.[position|velocity|rotation|angularVelocity] += x;
Rigidbody2D.[position|velocity|rotation|angularVelocity] += x;
Rigidbody.Add[Force|Torque](x, ForceMode.[Impulse|VelocityChange]);
Rigidbody2D.Add[Force|Torque](x, ForceMode2D.Impulse);
All the above operations cause a quantity to instantly jump by x, irrespective of the length of the frame.
In contrast, the following operations are continuous:
Rigidbody.Add[Force|Torque](x, ForceMode.[Force|Acceleration]);
Rigidbody2D.Add[Force|Torque](x, ForceMode.Force);
Rigidbody.velocity = x; (continuous from the perspective of Rigidbody.position. i.e. setting the velocity will not make Rigidbody.position suddenly jump to a new value)
All the above operations are applied over the course of the frame (at least conceptually this happens; what the physics system does internally is out of the scope of this answer). To illustrate this, Rigidbody.AddForce(1, ForceMode.Force) will cause a force of 1 newton to be applied to an object for the entire frame; there will be no sudden jumps in position or velocity.
So when do you multiply by Time.deltaTime?
If you are using a continuous operation, you should almost definitely not be multiplying by Time.deltaTime. But if you are using an instantaneous operation, the answer depends on if the operation is being used in a continuous way.
Example 1: Explosion
void Explode() {
rigidbody.velocity += explosionAcceleration;
}
Here you should not be multiplying by Time.deltaTime since Explode() gets called just once. It is not meant to be applied over a series of frames.
Example 2: Moving
void Update() {
rigidbody.position += velocity * Time.deltaTime;
}
Here you do have to multiply by Time.deltaTime because the object is supposed to move continuously over time, and you are also using an instantaneous operation. Note that this could be replaced with a continuous operation, and remove the need for multiplying by Time.deltaTime:
void Update() {
rigidbody.velocity = velocity;
}
Although this isn't entirely equivalent to the original, since it ignores the previous value of rigidbody.velocity.
Example 3: Accelerating
void Update() {
rigidbody.AddForce(acceleration*Time.deltaTime, ForceMode.VelocityChange);
}
Here you should be multiplying by Time.deltaTime because you want the velocity to increase at a consistent rate frame by frame. Note that this is precisely equivalent to:
void Update() {
rigidbody.AddForce(acceleration, ForceMode.Acceleration);
}
This code applies the acceleration over the course of the whole frame. This code is also (in my opinion) cleaner and easier to understand.
What about FixedUpdate?
Being in FixedUpdate does not effect any of the above advice. Yes, you could theoretically get away with never multiplying by Time.deltaTime since the time between frames would always be the same. But then all your units would have to be dependent on the fixed frame rate. So for example if you wanted to move at a rate of 1 m/s with 60 frames per second, you would have to add 1/60=.01666 to the position each frame. And then imagine what happens if you change your fixed timestep. You would have to change a bunch of your constants to accommodate.
Executing code in FixedUpdate does not suddenly make that code framerate independent. You still have to take the same precautions as in Update.
As a side note, you do not need to replace Time.deltaTime with Time.fixedDeltaTime inside FixedUpdate because Unity already does this substitution.
Conclusion
Only multiply by Time.deltaTime if you want an instantaneous operation to act smoothly over a series of frames.
Many times, you can avoid using Time.deltaTime by using continuous operations, which are often more intuitive (see examples 2 and 3). But this of course depends on the context.
A simple way to think about this is to determine:
Are objects' transforms manipulated directly?
When an object is being moved directly via its transform.position and transform.rotation components, manipulation of the transform should occur in Update(), which runs once per drawn frame. The developer should build their game with the expectation that the Update/frame rate varying between zero and the game's maximum frame rate. The way to accomplish this is by factoring in the time between now and previous frame into the movement (step) for each update/frame.
Thus, manipulations to the transform.position and transform.rotation should factor in Time.deltaTime and should occur within Update().
Are objects being manipulated with physics?
In this case, forces and torques should be applied by calling Rigidbody.AddForce() or Rigidbody.AddTorque() in FixedUpdate(). FixedUpdate() can be expected to occur at a fixed/guaranteed rate, which Unity defaults to 50 times per second (this can be adjusted within the Physics settings of your game project).
To complicate things a bit, when AddForce() and AddTorque() are called with ForceMode.Force (default) or ForceMode.Acceleration, the value provided for the force or torque parameters will be interpreted as amounts for one entire second, so these functions will adjust the value (a force/torque or acceleration/angular acceleration) for one fixed time step (i.e., x 0.02s with the default Unity Physics fixed update rate).
In case you are curious about ForceMode.Impulse or ForceMode.VelocityChange, these will interpret the force or torque as the amount to apply within that fixed time step (i.e. the value will not be adjusted with respect to time).
I have a question about Lerp. So I know that lerp helps you to move your object like:
void update(){
transform.position = vector3.lerp(start.position,end.position, (Time.time / 1000));
}
this will get your object to your endposition.
But if you have this code:
void Update(){
transform.position = Vector3.Lerp(transform.position,
destination.position,
speed * 3.0f * Time.deltaTime);
}
How is it possible that your object arrives at your destination, the 3th parameter of lerp has to reaches slowly 1 so your objects arrives at your destination. But "speed" , "3.0" , "Time.deltaTime" will always be the same, so how is it possible that your object arrives at your destination?
So the big question: Is it possible to do the lerp with some variables, which have always the same value and with Time.deltaTime?
Now, because of the different comments etc. I don't know exactly how lerp works, i have to possibilities:
1.) First i thought it works like this:
Vector3.lerp(a,b,c)
The c value has to change every frame to move the object. If the c value is 0.2 your object will moved 20% of the way and if the c value doesn't change the object will always be on 20% of the way. So the get the object moved fluently your c value have to change every frame a little so you c value will go from 0 to 1 and so is your object going from start to destination.
Or is it like this
2.) Because of several comments i thought lerp works like this
Like the comments say, the c value doesn't have to change the value, becaue if you have c = 0.2 you will pass 20% of the way and the next frame, if c is still 0.2 you will pass 20% of the remaining way and so on.
So is it lerp working like 1(you have to change c) or is it working like 2(you don't have to change c)
The distance between your transform position and the destination is an exponential decay. The distance shrinks by (1 - speed) every frame (given that speed is less than 1). Say your game is supposed to run at 60FPS. If for whatever reason the frame rate drops to 30FPS, the deltaTime is gonna be twice as big and you’re supposed to execute the Lerp 2 times. In such case, the distance will shrink by (1 - speed) then (1 - speed) again yielding a result of (1 - speed)^2 shrinkage. From this, you can generalize that the shrink amount of the distance is (1 - speed) ^ (deltaTime / baseDeltaTime) with baseDeltaTime being the deltaTime the game is supposed to run at i.e. 1/60 (for 60FPS).
To put in code:
transform.position = Vector3.Lerp(transform.position, destination.position, 1 - Mathf.Pow(1 - speed * 3.0f, Time.deltaTime * 60));
The object reaches the goal because your start position is the current position, and after lerping, you set the position of the object to the resulting position of Lerp. If you change your starting position to a normal Vector3 it would Lerp to "speed * Time.deltaTime * 3f"
I guess you didn't understand that how lerp works in unity. I will recommend you this Article of Robbert How to Lerp like a pro.
I see this sort of thing far too often:
transform.position = Vector3.Lerp(startPos, endPos, Time.deltaTime);
The person posting it is usually convinced that Vector3.Lerp is
“broken”, but the real problem is that they’re not using it correctly.
Lerp, short for “linear interpolation” does one very simple thing:
given two values, x and y, it returns a value that is t percent
between them. If you expect the output to change, the arguments you
pass in need to reflect that!
In the example above, it doesn’t make sense to just pass in
Time.deltaTime, because that’s only the time that passed during the
most recent frame. If your game is running at a constant 50fps, that’s
always going to be 0.02.
myLocation = Mathf.Lerp(myLocation, myDestination, 0.02)
If you are storing the return of the Lerp function into a variable and then also using that same variable as the minimum value in that same Lerp function, then the min value is getting bigger and bigger everytime the function is called.
So, even though you're not changing T, you're changing the starting value and thus, the stored value gets closer and closer to the max value.
It will accelerate very quickly initially and then slow down the closer it gets to the max value. Also, the max value will either never be reached or take an extremely long time.
(See https://gamedev.stackexchange.com/questions/149103/why-use-time-deltatime-in-lerping-functions)
There are two common ways to use Lerp:
1. Linear blending between a start and an end
progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);
2. Exponential ease toward a target
current = Mathf.Lerp(current, target, sharpnessPerTick);
Note that in this version the current value appears as both the output and an input. It displaces the start variable, so we're always starting from wherever we moved to on the last update. This is what gives this version of Lerp a memory from one frame to the next. From this moving starting point, we then then move a fraction of the distance toward the target dictated by a sharpness parameter.
This parameter isn't quite a "speed" anymore, because we approach the target in a Zeno-like fashion. If sharpnessPerTick were 0.5, then on the first update we'd move halfway to our goal. Then on the next update we'd move half the remaining distance (so a quarter of our initial distance). Then on the next we'd move half again...
This gives an "exponential ease-out" where the movement is fast when far from the target and gradually slows down as it approaches asymptotically (though with infinite-precision numbers it will never reach it in any finite number of updates - for our purposes it gets close enough). It's great for chasing a moving target value, or smoothing a noisy input using an "exponential moving average," usually using a very small sharpnessPerTick parameter like 0.1 or smaller.
I'm trying to figure out how to stop the rotation of a rigidbody using inertia in Unity 3D. This is how I assumed it should be done, but when I ran it, it crashed Unity and I had to kill the process.
while(rigidBody.angularVelocity.magnitude != 0) {
rigidBody.AddTorque(-transform.up * REACTION_WHEEL, ForceMode.Impulse);
}
So how would I go about adding torque to a rigidbody to bring it from any degrees/second to 0?
Note: I wrote this before looking up the different ForceModes, but all of the advice still stands. Your freeze was because you were asking for too much precision (you're subtracting from velocity by the same amount repeatedly, with no consideration for overstepping (.5 -1 is never 0) or direction (your object may not be spinning around Transform.up)), but I think what you really want follows:
The problem you're running into is that torque is to angular velocity like acceleration is to normal velocity - you can set your acceleration to billions, but that won't affect your velocity until some time passes. If you want to stop your object this frame, you really just want to set rigidBody.angularVelocity = Vector3.zero;. If you want to slow down your object over time, then AddTorque is what you're looking for, but you want to do it only once per frame.
If you're looking to make something slow down as if because of friction, then constant torque each frame is the goal, e.g.
float SlowDownPerSecond = 2f;
//...each frame:
if(rigidBody.angularVelocity.maginitude > SlowDownPerSecond * Time.deltaTime){
rigidBody.AddTorque(-rigidBody.angularVelocity.normalized * SlowDownPerSecond, ForceMode.Force);
} else {//less than change per frame
rigidBody.angularVelocity = Vector3.zero;
}
But you might also be less concerned with the velocity being exactly zero than you are with making it slow down smoothly, in which case you can just do
rigidBody.AddTorque(rigidBody.angularVelocity * -.05f, ForceMode.Force);
//or
rigidBody.AddTorque(rigidBody.angularVelocity * -.05f * Time.deltaTime, ForceMode.Impulse);
each frame. Although if this is what you're looking for, I think you can just up the angular Drag of the object either in the editor or at runtime with rigidbody.angularDrag = .1f, or whatever value you find feels right.
I want to make the sphero move a given amount of centimeters ahead but so far i have not managed to get anything to work properly
This is the code i have now:
EditText distanceText = (EditText) findViewById(R.id.distanceText);
int inputMSec = Integer.parseInt(distanceText.getText().toString());
int time = (inputMSec - inputMSec/2);
// The ball is given the RollCommand at half speed.
RollCommand.sendCommand(mRobot, heading,0.5f);
// A handler is created to delay the Stop command.
final Handler handler = new Handler();
handler.postDelayed(new Runnable(){
#Override
public void run() {
// Makes the ball stop
RollCommand.sendStop(mRobot);
}
// The variable 'time' defines how long the ball rolls until it is told to stop.
}, time);
Is there any other command i can send to the ball instead of RollCommand?
Or can anyone find out what to do to the input from the EditText so that the distance turns out correct?
There's no API command that directly provides the ability to drive a given distance. The only way I now how is with an iterative strategy using the locator, which provides position information about the ball.
Here's an overview of the strategy. Let me know if you need more details.
Turn on data streaming and request locator position data. You should now have some callback giving you Sphero position ~20x a sec. The positions are (x, y) coordinates on the floor in centimeters.
Record the starting position of the ball (x0, y0).
At each point in time, compute the distance the ball has traveled so far using the Pythagorean theorem/distance formula.
Use this to figure out how far the ball has left to go. Call this distance D.
Give a roll command where the speed is computed from D.
The big question is: how do you decide what speed to command based on D? I had some success with a strategy something like this: (undoubtedly you can tune it up a lot better).
If the remaining distance D > 100cm, command full speed.
Between D = 10cm and D = 100cm, command power ranging from 30% to 100% (linearly).
If D < 10cm, command zero speed to make Sphero stop.
This worked pretty well. It would drive, slow down, and coast the last few inches to a stop. Problems with this algorithm include:
You have to tune it to prevent overshoot/undershoot.
When you want to command the ball to move only very short distance it doesn't work well, so you might have to tweak it to cover those cases.
Good luck!
I'm working on something similar to an inclinometer. I rotate an image based on the angle calculated in didAccelerate (from UIAccelerometerDelegate) using the passed in UIAcceleration variable. The image is jittery or twitchy. Even when the phone is laying on its back and not moving. There are some inclinometers in the app store that are super smooth. I've tried to smooth it out by checking the last reading and if it is within a range, don't do anything. That stops some of the twitching but then you get into something that looks like stop animation. How can I get a smoother affect?
I would suggest smoothing using a 'critically damped spring'.
Essentially what you do is calculate your target rotation (which is what you have now).
Instead of applying this directly to the image rotation, you attach the image rotation to the target rotation with a spring, or piece of elastic. The spring is damped such that you get no oscillations.
You will need one constant to tune how quickly the system reacts, we'll call this the SpringConstant.
Basically we apply two forces to the rotation, then integrate this over time.
The first force is that applied by the spring, Fs = SpringConstant * DistanceToTarget.
The second is the damping force, Fd = -CurrentVelocity * 2 * sqrt(SpringConstant)
The CurrentVelocity forms part of the state of the system, and can be initialised to zero.
In each step, you multiply the sum of these two forces by the time step.
This gives you the change in the value of the CurrentVelocity.
Multiply this by the time step again and it will give you the displacement.
We add this to the actual rotation of the image.
In c++ code:
float CriticallyDampedSpring( float a_Target,
float a_Current,
float & a_Velocity,
float a_TimeStep )
{
float currentToTarget = a_Target - a_Current;
float springForce = currentToTarget * SPRING_CONSTANT;
float dampingForce = -a_Velocity * 2 * sqrt( SPRING_CONSTANT );
float force = springForce + dampingForce;
a_Velocity += force * a_TimeStep;
float displacement = a_Velocity * a_TimeStep;
return a_Current + displacement;
}
I imagine you have two dimensions of rotation. You just need to use this once for each dimension, and keep track of the velocity of each dimension separately.
In systems I was working with 5 was a good value for the spring constant, but you will have to experiment for your situation. Setting it too high will not get rid of the jerkiness, setting it too low it will react too slowly.
Also, you might be best to make a class that keeps the velocity state rather than have to pass it into the function over and over.
I hope this is helpful :)