Calculating a mass resistance to acceleration - c++

Im not sure if this is the right place for this question, but I need to calculate the velocity of a large amplitude pendulum, with my current code it results in a sinusoidal graph.
The problem is that the period of the pendulum becomes smaller if I increase the mass, which shouldn't happen in a real pendulum because the period is independent of mass; The acceleration increases with mass but resistance to acceleration does too, and I don't know how to code this.
I have tried looking into angular momentum but my knowledge of physics is very limited. I have this:
long double timeFrame = 0.01;
if(getNewAngle==true)
{
//Convert to radians.
myAngle = Angle*M_PI/180;
getNewAngle = false;
//Velocity starts at 0.
myVelocity = 0;
}
//Setup starting variables.
long double dLength = std::stod(Length,0);
long double dGravity = std::stod(Gravity,0);
long double dMass = std::stod(Mass,0);
long double dPeriod = std::stod(Period,0);
//Large amplitude pendulum acceleration formula
long double dAcceleration = -dMass*dGravity/dLength*sin(myAngle);
//Angular displacement formula;
long double dDisplacement = myVelocity*timeFrame+0.5*dAcceleration*pow(timeFrame,2);
myVelocity = dDisplacement/timeFrame;
myAngle = myAngle + dDisplacement;

This:
//Large amplitude pendulum acceleration formula
long double dAcceleration = -dMass*dGravity/dLength*sin(myAngle);
is incorrect. It should be this:
//Large amplitude pendulum acceleration formula
long double dAcceleration = -dGravity/dLength*sin(myAngle);
That's right, mass doesn't enter into it (unless you start to consider air resistance).

Related

Frequency - linear bins to logarithmic screenspace

I'm working on project, where I need to visualize spectral analysis to set some precise parameters. Now I'm with conversion of bins to screen space, because in linear space, magnitudes in lower frequencies are squashed together. Here's my code in c++:
float windowSize = 640;
float windowHeight = 480;
for (size_t i = 0; i < bins; i++)
{
float m = audioIn.getSpectrum.at(i)*windowHeight;
float pos = i;
drawLine(vec2(pos, 0), vec2(pos, m));
}
I was trying to compute pos by using different approaches, but failed miserably. I'm missing crucial knowledge about logarithms I guess.
DISCLAIMER: this is for personal art project, not homework assignment.
Typically spectrographs are displayed on a base 10 logarithmic scale.
Assuming bins in your case go from 0 Hz to nyquist Hz you might try something like this (for 44.1kHz audio):
float nyquist = 22050.0;
float logMax = log10(nyquist);
float log = log10((float)i * nyquist / (float)bins);
float pos = log / logMax * windowSize;

Accelerate to X velocity in Y seconds

How can I get something to go from X to Xgoal velocity in Y seconds?
The goalVelocity is set to (100, 100) and it does approach it but it takes way too long to get there.
I can multiply frameDelta by some number like 20 or 100 but I want to find out what to multiply frameDelta by to get it to reach goalVelocity in some number of seconds.
velocity, goalVelocity and origin are all Vec2f and frameDelta is a float
Right now I have this code:
velocity = approach(goalVelocity, velocity, frameDelta);
origin = origin + velocity * frameDelta;
The code for approach is:
inline float approach(float flGoal, float flCurrent, float dt)
{
float flDifference = flGoal - flCurrent;
if (flDifference > dt)
return flCurrent + dt;
if (flDifference < -dt)
return flCurrent - dt;
return flGoal;
}
inline Vec2f approach(Vec2f flGoal, Vec2f flCurrent, float dt)
{
return Vec2f(approach(flGoal.x, flCurrent.x, dt), approach(flGoal.y, flCurrent.y, dt));
}
Maybe I misunderstood your Question, but acceleration is just speed difference divided by time, so just multiply dt with X/Y.
A basic physics engine should look something like
Vec2f position, velocity, acceleration;
while (true)
{
acceleration = button ? thrust : 0;
velocity += acceleration * timeDelta;
position += velocity * timeDelta
redraw space ship at position;
sleep (timeDelta);
}
if you want to go from 0 to X velocity in Y seconds, then thrust = X/Y.

Automatic Gain Control click & pop bursts

This is my Automatic Gain Control Method, it works but I get a quick burst on the first impulse. How can I scale it down so it doesn't go past 0dbfs? Also the rate at 1e-4 somewhat works but it's too slow.
double AGC(double x)
{
double ref = pow(10.0, (-18.0/10.0); //-18dBFS Convert to Linear
double rate = 1.0; // coefficient when increasing/decreasing gain
x = x * m_Gain; //scale input(x)
m_Gain += (ref - (fabs(x) * fabs(x))) * rate;
return x;
}

How do I keep the jump height the same when using delta time?

I'm using delta time so I can make my program frame rate independent.
However I can't get the jump height it be the same, the character always jumps higher on a lower frame rate.
Variables:
const float gravity = 0.0000000014f;
const float jumpVel = 0.00000046f;
const float terminalVel = 0.05f;
bool readyToJump = false;
float verticalVel = 0.00f;
Logic code:
if(input.isKeyDown(sf::Keyboard::Space)){
if(readyToJump){
verticalVel = -jumpVel * delta;
readyToJump = false;
}
}
verticalVel += gravity * delta;
y += verticalVel * delta;
I'm sure the delta time is correct because the character moves horizontally fine.
How do I get my character to jump the same no matter the frame rate?
The formula for calculating the new position is:
position = initial_position + velocity * time
Taking into account gravity which reduces the velocity according to the function:
velocity = initial_velocity + (gravity^2 * time)
NOTE: gravity in this case is not the same as the gravity.
The final formula then becomes:
position = initial_position + (initial_velocity + (gravity^2 * time) * time
As you see from the above equation, initial_position and initial_velocity is not affected by time. But in your case you actually set the initial velocity equal to -jumpVelocity * delta.
The lower the frame rate, the larger the value of delta will be, and therefore the character will jump higher. The solution is to change
if(readyToJump){
verticalVel = -jumpVel * delta;
readyToJump = false;
}
to
if(readyToJump){
verticalVel = -jumpVel;
readyToJump = false;
}
EDIT:
The above should give a pretty good estimation, but it is not entirely correct. Assuming that p(t) is the position (in this case height) after time t, then the velocity given by v(t) = p'(t)', and the acceleration is given bya(t) = v'(t) = p''(t)`. Since we know that the acceleration is constant; ie gravity, we get the following:
a(t) = g
v(t) = v0 + g*t
p(t) = p0 + v0*t + 1/2*g*t^2
If we now calculate p(t+delta)-p(t), ie the change in position from one instance in time to another we get the following:
p(t+delta)-p(t) = p0 + v0*(t+delta) + 1/2*g*(t+delta)^2 - (p0 + v0*t + 1/2*g*t^2)
= v0*delta + 1/2*g*delta^2 + g*delta*t
The original code does not take into account the squaring of delta or the extra term g*delta*t*. A more accurate approach would be to store the increase in delta and then use the formula for p(t) given above.
Sample code:
const float gravity = 0.0000000014f;
const float jumpVel = 0.00000046f;
const float limit = ...; // limit for when to stop jumping
bool isJumping = false;
float jumpTime;
if(input.isKeyDown(sf::Keyboard::Space)){
if(!isJumping){
jumpTime = 0;
isJumping = true;
}
else {
jumpTime += delta;
y = -jumpVel*jumpTime + gravity*sqr(jumpTime);
// stop jump
if(y<=0.0f) {
y = 0.0f;
isJumping = false;
}
}
}
NOTE: I have not compiled or tested the code above.
By "delta time" do you mean variable time steps? As in, at every frame, you compute a time step that can be completely different from the previous?
If so, DON'T.
Read this: http://gafferongames.com/game-physics/fix-your-timestep/
TL;DR: use fixed time steps for the internal state; interpolate frames if needed.

Fixed timestep loop in C++

I am trying to implement a fixed timestep loop so that the game refreshes at a constant rate. I found a great article at http://gafferongames.com/game-physics/fix-your-timestep/ but am having trouble translating that into my own 2d engine.
The specific place I am referring to is the function in the last part "The Final Touch" which is what most people recommend. This is his function:
double t = 0.0;
const double dt = 0.01;
double currentTime = hires_time_in_seconds();
double accumulator = 0.0;
State previous;
State current;
while ( !quit )
{
double newTime = time();
double frameTime = newTime - currentTime;
if ( frameTime > 0.25 )
frameTime = 0.25; // note: max frame time to avoid spiral of death
currentTime = newTime;
accumulator += frameTime;
while ( accumulator >= dt )
{
previousState = currentState;
integrate( currentState, t, dt );
t += dt;
accumulator -= dt;
}
const double alpha = accumulator / dt;
State state = currentState*alpha + previousState * ( 1.0 - alpha );
render( state );
}
For myself, I am just moving a player across the screen keeping track of an x and y location as well as velocity rather than doing calculus integration. **I am confused as to what I would apply to the updating of the player's location (dt or t?). Can someone break this down and explain it further?
The second part is the interpolation which I understand as the formula provided makes sense and I could simply interpolate between the current and previous x, y player positions.
Also, I realize I need to get a more accurate timer.
If you can get at least microsecond accuracy, try this:
long int start = 0, end = 0;
double delta = 0;
double ns = 1000000.0 / 60.0; // Syncs updates at 60 per second (59 - 61)
while (!quit) {
start = timeAsMicro();
delta+=(double)(start - end) / ns;
end = start;
while (delta >= 1.0) {
doUpdates();
delta-=1.0;
}
}
See:
http://en.wikipedia.org/wiki/Integral
&
http://en.wikipedia.org/wiki/Numerical_integration
The function is a numerical technique (2nd link) for approximating the integral function (1st link).
You should review your high school physics. Simply put velocity is change in distance over change in time(dxdt), acceleration is change in velocity over change in time(dvdt) If you know dxdt you can get the distance by integrating it w/ respect to t, if you know dvdt you can get the velocity by integrating it with respect to t. Obviously this is a very simple explanation, but there are tons of references out there with more details if you so desire.