Hi We are supposed to model the height and velocity of a rocket in c++ for our final project. Having user input the total flight time and delta time for the points during flight that they wish to measure. The following is the code I have written for this project. The velocity is supposed to start positive and after 60 seconds at which point there is no fuel left and thus no thrust the velocity should start becoming negative. However both my height and velocity are coming out as negative from the start and reaching negative infinite by the end.
#include <iostream>
using namespace std;
int main()
{
float *v;
float *h;
float a;
double mass=0.0, thrust, time, dt;
double g = 32.2;
double K = 0.008;
cout << "enter time";
cin >> time;
cout << "enter dt";
cin >> dt;
a = (time/dt);
v = new float[a];
h = new float[a];
v[0] = 0;
h[0] = 0;
float tt = 0;
// for loop to calculate velocity and time
for(int i = 0; i <= (time/dt) ; i++)
{
tt = dt + tt;
if( tt <= 60)
{
mass = (3000-(40*tt)/g);
thrust = 7000;
}
if ( tt > 60)
{
mass = 3000/g;
thrust = 0;
}
// these are the formulas for velocity and height position our prof gave us
v[i+1] = v[i] - (K/mass)*v[i]*v[i-1] * dt + (thrust/mass - g)*dt;
h[i+1] = v[i+1] * dt + h[i];
}
// for loop to output
for(int i = 0; i <= (time/dt); i++)
{
cout << i << " - " << "Velocity:" << v[i+1] << " Position:" << h[i+1] <<endl;
}
return 0;
}
sample output:
enter time120
enter dt.01
0 - Velocity:-0.298667 Position:-0.00298667
1 - Velocity:-0.597333 Position:-0.00896
2 - Velocity:-0.895999 Position:-0.01792
3 - Velocity:-1.19467 Position:-0.0298666
4 - Velocity:-1.49333 Position:-0.0448
5 - Velocity:-1.792 Position:-0.0627199
6 - Velocity:-2.09066 Position:-0.0836266
7 - Velocity:-2.38933 Position:-0.10752
<...i left out a lot of numbers in the middle to not make this post too long...>
11994 - Velocity:-inf Position:-inf
11995 - Velocity:-inf Position:-inf
11996 - Velocity:-inf Position:-inf
11997 - Velocity:-inf Position:-inf
11998 - Velocity:-inf Position:-inf
11999 - Velocity:-inf Position:-inf
12000 - Velocity:-inf Position:-inf
Program ended with exit code: 0
I have compared with my friends who are getting good results and we can not determine a difference between their code and mine. I have the rest of my program complete and working fine I just cannot figure out why my calculations are wrong
Ignoring the out-of-bounds access to v[-1] when i is zero, there is something wrong with your thrust, mass, or g.
thrust is 7000, mass is 3000 at time = 0. That means thrust/mass is just over 2. With g=32 (really? you are doing rocketry calculations in imperial units?), that means the rocket never has enough thrust to counter gravity, and just sits on the pad.
Edit: That would be reality. Because this is a fairly simple simulation, and doesn't include a "pad", in the model the rocket starts free-falling to the centre of the earth.
You are using v[i-1] but i starts out at 0, therefore this calculation is going to use whatever happens to be at v[-1]. I suggest you initialize i to 1 (and then check all the uses of i to ensure that the correct array elements will be used).
I am not 100% convinced about the forumla, I dont understand why it contains a v[i] and a v[i-1] term. Anyhow, even if correct, in the first iteration (i==0) you are accesing out of bounds of the velocity array: v[i-1]. That is undefined behaviour.
To fix this, either review the formula, does it really contain a v[i-1] term? ..or start the iteration at i=1 (and initialize v[0] and v[1]).
Thank you guys for your help I was able to solve it.
#include <iostream>
using namespace std;
int main()
{
double *v;
double *h;
double g = 32.2;
double K = .008;
double mass;
double t;
double dt;
double tt = 0;
double thrust;
cout << "t \n";
cin >> t;
cout << "dt \n";
cin >> dt;
double a = t/dt;
v = new double[a];
h = new double[a];
v[0] = 0;
h[0] = 0;
for (int i = 0; i <= a; i++)
{
tt = tt+dt;
if( tt == 0)
{
thrust = 7000;
mass = (3000 -40*dt)/g;
v[i+1] = v[i] + ((thrust/mass)-g)*dt;
}
else if( tt > 0 && tt < 60)
{
thrust = 7000;
mass = (3000 - 40 *tt)/g;
v[i+1] = v[i] - ((K/mass)*v[i]*v[i-1] * dt) + ((thrust/mass) - g)*dt;
}
else if (tt > 60)
{
thrust = 0;
mass = 600/g;
v[i+1] = v[i] - ((K/mass)*v[i]*v[i-1] * dt) + ((thrust/mass) - g)*dt;
}
h[i+1] = v[i+1] * dt + h[i];
}
cout << " end results \n";
for(int i = 0; i <= a; i++)
{
cout << i << " v - " << v[i] << " h - " << h[i] <<endl;
}
return 0;
}
New results:
t
120
dt
.01
end results
0 v - 0 h - 0
1 v - 0.429434 h - 0.00429434
2 v - 0.858967 h - 0.012884
3 v - 1.2886 h - 0.02577
4 v - 1.71833 h - 0.0429534
5 v - 2.14817 h - 0.064435
6 v - 2.5781 h - 0.090216
7 v - 3.00813 h - 0.120297
You can see below at 60s where the velocity changes due to no more thrust
5997 - Velocity:890.361
5998 - Velocity:890.392
5999 - Velocity:890.422
6000 - Velocity:886.697
6001 - Velocity:882.985
6002 - Velocity:879.302
Related
#include <cmath> \\not sure if I need cmath
#include <iostream>
using namespace std;
this while loop serves to loop the " enter number of terms to approximate.
while (a != 0)
{
here is the Leibniz formula:
double c = 0.00, d = 0.00;
for (int i = 1; i <= a)
{
if (i % 2 != 0)
{
d = 1 / (1 + 2 * (i - 1));
}
else
{
d = -1 / (1 + 2 * (i - 1));
}
c = c + d;
i = i + 1
}
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(5);
cout << "The approximation for Leibniz's Formula is " << c << "
using "<< a <<" terms." << endl;
here is the Wallis formula:
double e = 1.00;
for (int u = 0; u<a; u++)
{
e = e * (2 * a / (2 * a - 1))*(2 * a / (2 * a + 1));
}
cout << "The approximation for Wallis' Formula is " << e << " using
"<< a <<" terms." << endl;
cout << endl;
cout << "Enter the number of terms to approximate (or zero to
quit):" << endl;
cin >> a;
}
For a=1 I am getting 1.0000 in the first formula output and 0.00000 in the second formula output
A line like this
d = 1 / (1 + 2 * (i - 1));
will use integer arithmetics to calculate the result, and then convert the int result to a double.
Change it to
d = 1.0 / (1 + 2 * (i - 1));
or even
d = 1.0 / (1.0 + 2.0 * (i - 1.0));
There are many mistakes in this code. First, comments in c++ use //, not \\.
#include <cmath> //not sure if I need cmath
You have to have two semicolons in for statements, even if you don't need loop-expression.
for (int i = 1; i <= a;)
The d will evaluate to 0 for every i that is greater than 1. You are using integer division, when you clearly want floating point division. You have to tell that to the compiler like this.
d = 1.0 / (1 + 2 * (i - 1));
When the left argument of division operator is double compiler will know, that you want to perform a floating point division. If it would be int as in your code, integer division would be performed and result converted to double.
Also in the Wallis formula you misplaced a for u, and also u parameter should start at 1, not 0. Also the integer division problem persists here.
double e = 1.00;
for (int u = 1; u<a; u++)
{
e = e * (2.0 * u / (2.0 * u - 1))*(2.0 * u / (2.0 * u + 1));
}
If you fix this all, the program starts to output valid results.
Hello all you wonderful people, easy question here,
I have a bit of code here to calculate a best-fit line equation. I'm having trouble with the while loop that's nested in the for loop. Currently, "while(points >> Xi >> Yi)" is only running once, and then (I'm guessing) as it's reached the end of the document, it isn't repeating itself. How can I get it to repeat 1000 times? Can't use arrays, we haven't been taught those in class yet ;(.
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
double measureSSE(double m, double b, double Xi, double Yi)
{
return (Yi - ((m * Xi) + b)) * (Yi - ((m * Xi) + b));
}
int main()
{
double Xi = 0, Yi = 0;
double m = 0, b = 0;
double dm = 0, db = 0;
double SSE = 0;
ifstream points("points.txt");
if(points.is_open())
{
for(int counter = 0; counter < 1000; counter++)
{
while(points >> Xi >> Yi)
{
dm += -2 * Xi * (Yi - (m * Xi) - b);
db += -2 * (Yi - (m * Xi) - b);
m -= .01 * dm;
b -= .01 * db;
SSE += measureSSE(m, b, Xi, Yi);
}
cout << "SSE: " << SSE << endl;
}
cout << "Final Model: y = " << m << "x + " << b << endl;
points.close();
}
else cout << "Unable to open file." << endl;
}
Assuming you want to restart the iteration-through-file from scratch each time, you need to seek the read cursor before your while loop so that it works even when a previous run reached EOF. You'll also need to first clear the EOF flag (unless you're writing C++11 or later, in which this is done for you).
The language doesn't have any special rule to do this for you when you re-enter a while loop predicated on extraction from a stream.
for(int counter = 0; counter < 1000; counter++)
{
// Clear EOF flag, and revert to the beginning of the stream
points.clear();
points.seekg(0);
// Extract all "points" from the file
while(points >> Xi >> Yi)
I'm not quite sure what SSE is supposed to do here as you never actually use its value other than for debug output. I might suggest resetting its value to 0 on each iteration of the for loop, if I knew what it did. :)
I would like to simulate a point mass within a closed box. There is no friction and the point mass obeys the impact law. So there are only elastic collisions with the walls of the box. The output of the program is the time, position (rx,ry ,rz) and velocity (vx,vy,vz). I plot the trajectory by using GNUplot.
The problem I have now is, that the point mass gets energy from somewhere. So their jumps get each time more intense.
Is someone able to check my code?
/* Start of the code */
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
struct pointmass
{
double m; // mass
double r[3]; // coordinates
double v[3]; // velocity
};
// Grav.constant
const double G[3] = {0, -9.81, 0};
int main()
{
int Time = 0; // Duration
double Dt = 0; // Time steps
pointmass p0;
cerr << "Duration: ";
cin >> Time;
cerr << "Time steps: ";
cin >> Dt;
cerr << "Velocity of the point mass (vx,vy,vz)? ";
cin >> p0.v[0];
cin >> p0.v[1];
cin >> p0.v[2];
cerr << "Initial position of the point mass (x,y,z)? ";
cin >> p0.r[0];
cin >> p0.r[1];
cin >> p0.r[2];
for (double i = 0; i<Time; i+=Dt)
{
cout << i << setw(10);
for (int j = 0; j<=2; j++)
{
////////////position and velocity///////////
p0.r[j] = p0.r[j] + p0.v[j]*i + 0.5*G[j]*i*i;
p0.v[j] = p0.v[j] + G[j]*i;
///////////////////reflection/////////////////
if(p0.r[j] >= 250)
{
p0.r[j] = 500 - p0.r[j];
p0.v[j] = -p0.v[j];
}
else if(p0.r[j] <= 0)
{
p0.r[j] = -p0.r[j];
p0.v[j] = -p0.v[j];
}
//////////////////////////////////////////////
}
/////////////////////Output//////////////////
for(int j = 0; j<=2; j++)
{
cout << p0.r[j] << setw(10);
}
for(int j = 0; j<=2; j++)
{
cout << p0.v[j] << setw(10);
}
///////////////////////////////////////////////
cout << endl;
}
}
F = ma
a = F / m
a dt = F / m dt
a dt is acceleration over a fixed time - the change in velocity for that frame.
You are setting it to F / m i
it is that i which is wrong, as comments have suggested. It needs to be the duration of a frame, not the duration of the entire simulation so far.
I am a little concerned about the time loop along with other commenters - make sure that it represents an increment of time, not a growing duration.
Still, I think the main problem is you are changing the sign of all three components of velocity
on reflection.
That's not consistent with the laws of physics -conservation of linear momentum and energy - at the boundaries.
To see this, consider the case if your particle is moving in just the x-y plane (velocity in z is zero) and about to hit the wall at x= L.
The collision looks like this:
The force exerted on the point mass by the wall acts perpendicular to the wall. So there is no change in the momentum component of the particle parallel to the wall.
Applying conservation of linear momentum and kinetic energy, and assuming a perfectly elastic collision, you will find that
The component of velocity perpendicular to the wall DOES change sign
The component of velocity parallel to the wall DOES NOT change sign
In three dimensions, to have an accurate simulation, you have to work out the momentum components parallel and perpendicular to the wall on collision and code the resulting velocity changes.
In other words, this code:
///////////////////reflection/////////////////
if(p0.r[j] >= 250)
{
p0.r[j] = 500 - p0.r[j];
p0.v[j] = -p0.v[j];
}
else if(p0.r[j] <= 0)
{
p0.r[j] = -p0.r[j];
p0.v[j] = -p0.v[j];
}
//////////////////////////////////////////////
does not model the physics of reflection correctly. To fix it here is an outline of what to do:
Take the reflection checks out of the loop over x,y,z coordinates (but still within the time loop)
The collision condition for all six walls needs to be checked,
according to the direction of the normal vector to the wall.
For example for the right wall of the cube defined by X=250, 0<=Y<250, 0<=Z<250, the normal vector is in the negative X direction. For the left wall defined by X=0, 0<=Y<250, 0<=Z<250, the normal vector is in the positive X direction.
So on reflection from those two walls, the X component of velocity changes sign because it is normal (perpendicular) to the wall, but the Y and Z components do NOT change sign because they are parallel to the wall.
Apply similar considerations at the top and bottom wall (constant Y), and front and back wall (constant Z), of the cube -left as exercise to work out the normals to those surfaces.
Finally you shouldn't change sign of the position vector components on reflection, just the velocity vector. Instead recompute the next value of the position vector given the new velocity.
OK, so there are a few issues. The others have pointed out the need to use Dt rather than i for the integration step.
However, you are correct in stating that there is an issue with the reflection and energy conservation. I've added an explicit track of that below.
Note that the component wise computation of the reflection is actually fine other than the energy issue.
The problem was that during a reflection the acceleration due to gravity changes. In the case of the particle hitting the floor, it was acquiring kinetic energy equal to that it would have had if it had kept falling, but the new position had higher potential energy. So the energy would increase by exactly twice the potential energy difference between the floor and the new position. A bounce off the roof would have the opposite effect.
As noted below, once strategy would be to compute the actual time of reflection. However, actually working directly with energy is much simpler as well as more robust. However, please note although the the simple energy version below ensures that the speed and position are consistent, it actually does not have the correct position. For most purposes that may not actually matter. If you really need the correct position, I think we need to solve for the bounce time.
/* Start of the code */
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
struct pointmass
{
double m; // mass
double r[3]; // coordinates
double v[3]; // velocity
};
// Grav.constant
const double G[3] = { 0, -9.81, 0 };
int main()
{
// I've just changed the initial values to speed up unit testing; your code worked fine here.
int Time = 50; // Duration
double Dt = 1; // Time steps
pointmass p0;
p0.v[0] = 23;
p0.v[1] = 40;
p0.v[2] = 15;
p0.r[0] = 100;
p0.r[1] = 200;
p0.r[2] = 67;
for (double i = 0; i<Time; i += Dt)
{
cout << setw(10) << i << setw(10);
double energy = 0;
for (int j = 0; j <= 2; j++)
{
double oldR = p0.r[j];
double oldV = p0.v[j];
////////////position and velocity///////////
p0.r[j] = p0.r[j] + p0.v[j] * Dt + 0.5*G[j] * Dt*Dt;
p0.v[j] = p0.v[j] + G[j] * Dt;
///////////////////reflection/////////////////
if (G[j] == 0)
{
if (p0.r[j] >= 250)
{
p0.r[j] = 500 - p0.r[j];
p0.v[j] = -p0.v[j];
}
else if (p0.r[j] <= 0)
{
p0.r[j] = -p0.r[j];
p0.v[j] = -p0.v[j];
}
}
else
{
// Need to capture the fact that the acceleration switches direction relative to velocity half way through the timestep.
// Two approaches, either
// Try to compute the time of the bounce and work out the detail.
// OR
// Use conservation of energy to get the right speed - much easier!
if (p0.r[j] >= 250)
{
double energy = 0.5*p0.v[j] * p0.v[j] - G[j] * p0.r[j];
p0.r[j] = 500 - p0.r[j];
p0.v[j] = -sqrt(2 * (energy + G[j] * p0.r[j]));
}
else if (p0.r[j] <= 0)
{
double energy = 0.5*p0.v[j] * p0.v[j] - G[j] * p0.r[j];
p0.r[j] = -p0.r[j];
p0.v[j] = sqrt(2*(energy + G[j] * p0.r[j]));
}
}
energy += 0.5*p0.v[j] * p0.v[j] - G[j] * p0.r[j];
}
/////////////////////Output//////////////////
cout << energy << setw(10);
for (int j = 0; j <= 2; j++)
{
cout << p0.r[j] << setw(10);
}
for (int j = 0; j <= 2; j++)
{
cout << p0.v[j] << setw(10);
}
///////////////////////////////////////////////
cout << endl;
}
}
I found many similar topics but none of them gives me clear explanation.
I have to write program which calculates Pi squared to n digits using this taylor series:
π^2 = 12 ( 1/1^2 - 1/2^2 + 1/3^2 - 1/4^2 + ... )
I wrote this:
#include <iostream>
#include <math.h>
using namespace std;
int main() {
int n;
cout << "How many digits?" << endl;
cin >> n;
long double Pi2 = 0;
int i = 1;
while( precision is less than n ) {
if ((i%2) == 1) {
Pi2 += 1/pow(i,2);
i+=1;
}
else {
Pi2 -= 1/pow(i,2);
i+=1;
}
}
Pi2 *= 12;
cout << Pi2 << endl;
return 0;
}
and I have no idea what to write in while() ? When should this loop stop?
If You know the required precision, You can calculate the right value for the maximum value for n before You start the loop.
Second thing: start with the most less number if You start adding all delta values.
Similar to this
int ndigits;
cout << "How many digits?" << endl;
cin >> ndigits;
int n = int( pow( double(10), double(ndigits)/2 ) + 0.5 );
long double Pi2 = 0;
int i = 1;
for( int i=n; i>0; --i )
{
if ((i%2) == 1) {
Pi2 += 1/pow(long double(i),2);
}
else {
Pi2 -= 1/pow(long double(i),2);
}
}
Pi2 *= 12;
A method to consider is using ndigits to create an 'epsilon' value.
Let's assume ndigits is 3. That give an epsilon of 0.0001
if the difference between your value from the previous iteration, and the current iteration is less than 0.0001, then you can assume you have the value you are after, and terminate the while loop.
A warning though. Doubles and long doubles have an upper limit on the number of digits they can hold accurately.
I have a flow layout. Inside it I have about 900 tables. Each table is stacked one on top of the other. I have a slider which resizes them and thus causes the flow layout to resize too.
The problem is, the tables should be linearly resizing. Their base size is 200x200. So when scale = 1.0, the w and h of the tables is 200.
I resize by a fixed amount each time making them 4% bigger each time. This means I would expect them to grow by 8 pixels each time. What happens is, every few resizes, the tables grow by 9 pixels. I use doubles everywhere. I have tried rounding, floor and ceil but the problem persists. What could I do so that they always grow by the correct amount?
void LobbyTableManager::changeTableScale( double scale )
{
setTableScale(scale);
}
void LobbyTableManager::setTableScale( double scale )
{
scale += 0.3;
scale *= 2.0;
std::cout << scale << std::endl;
agui::Gui* gotGui = getGui();
float scrollRel = m_vScroll->getRelativeValue();
setScale(scale);
rescaleTables();
resizeFlow();
...
double LobbyTableManager::getTableScale() const
{
return (getInnerWidth() / 700.0) * getScale();
}
void LobbyFilterManager::valueChanged( agui::Slider* source,int val )
{
if(source == m_magnifySlider)
{
DISPATCH_LOBBY_EVENT
{
(*it)->changeTableScale((double)val / source->getRange());
}
}
}
void LobbyTableManager::renderBG( GraphicsContext* g, agui::Rectangle& absRect, agui::Rectangle& childRect )
{
int cx, cy, cw, ch;
g->getClippingRect(cx,cy,cw,ch);
g->setClippingRect(absRect.getX(),absRect.getY(),absRect.getWidth(),absRect.getHeight());
float scale = 0.35f;
int w = m_bgSprite->getWidth() * getTableScale() * scale;
int h = m_bgSprite->getHeight() * getTableScale() * scale;
int numX = ceil(absRect.getWidth() / (float)w) + 2;
int numY = ceil(absRect.getHeight() / (float)h) + 2;
float offsetX = m_activeTables[0]->getLocation().getX() - w;
float offsetY = m_activeTables[0]->getLocation().getY() - h;
int startY = childRect.getY() + 1;
if(moo)
{
std::cout << "TS: " << getTableScale() << " Scr: " << m_vScroll->getValue() << " LOC: " << childRect.getY() << " H: " << h << std::endl;
}
if(moo)
{
std::cout << "S=" << startY << ",";
}
int numAttempts = 0;
while(startY + h < absRect.getY() && numAttempts < 1000)
{
startY += h;
if(moo)
{
std::cout << startY << ",";
}
numAttempts++;
}
if(moo)
{
std::cout << "\n";
moo = false;
}
g->holdDrawing();
for(int i = 0; i < numX; ++i)
{
for(int j = 0; j < numY; ++j)
{
g->drawScaledSprite(m_bgSprite,0,0,m_bgSprite->getWidth(),m_bgSprite->getHeight(),
absRect.getX() + (i * w) + (offsetX),absRect.getY() + (j * h) + startY,w,h,0);
}
}
g->unholdDrawing();
g->setClippingRect(cx,cy,cw,ch);
}
void LobbyTable::rescale( double scale )
{
setScale(scale);
float os = getObjectScale();
double x = m_baseHeight * os;
if((int)(x + 0.5) > (int)x)
{
x++;
}
int oldH = getHeight();
setSize(m_baseWidth * os, floor(x));
...
I added the related code. The slider sends a value changed which is multiplied to get a 4 percent increase (or 8 percent if slider moves 2 values etc...) then the tables are rescaled with this.
The first 3 are when the table size increased by 9, the 4th time it increased by 8px. But the scale factor increases by 0.04 each time.
Why is the 4th time inconsistant?
the pattern seems like 8,8,8,9,9,9,8,8,8,9,9,9...
It increases by 1 pixel more for a few and then decreases by 1 ten increases by 1 etc, thats my issue...
I still don't see the "add 4%" code there (in a form I can understand, anyway), but from your description I think I see the problem: adding 4% twice is not adding 8%. It is adding 8.16% (1.04 * 1.04 == 1.0816). Do that a few more times and you'll start getting 9 pixel jumps. Do it a lot more times and your jumps will get much bigger (they will be 16 pixel jumps when the size gets up to 400x400). Which, IMHO is how I like my scaling to happen.