0

I have a c++ program that creates a list of offsets that correspond to traversing around an ellipse. I need to vary the velocity so that more time (i.e. more of the produced offsets) are near the far ends of the oval. The oval is long and skinny, and the current way I am calculating the offsets results in more offsets near the center of the ellipse, which is the opposite of what i want.

code:

// breathingPeriod, intervalMS, and yRadius are variables.
// Good defaults are: breathingPeriod = 5, intervalMs = 10, yRadius = 20
const int points = breathingPeriod * 1000 / intervalMS;
const double velocityCoeff = 360 / (breathingPeriod * 1000);
const zRadius = 3;
std::ofstream out("output.txt");


for(int i = 0; i < points; ++i)
{
    const int age = intervalMS * i;
    const uint64_t thetaDeg = static_cast<uint64_t>(age * velocityCoeff) % 360;
    const double thetaRad = thetaDeg * M_PI / 180.0;
    const double tanTheta = tan(thetaRad);
    double zOffset= (yRadius* zRadius) / sqrt(pow(yRadius, 2) + pow(zRadius, 2) * pow(tanTheta, 2));

    if(thetaRad > M_PI_2 && thetaRad <= 3 * M_PI_2)
    {
        zOffset = -zOffset;
    }
    const double yOffset = zOffset * tanTheta;
    double xOffset = 0;
    std::string str;
    str += std::to_string(xOffset) + " " + std::to_string(yOffset) + " " + std::to_string(zOffset) + "\n";

    out << str;
}
out.close;

I have tried varying the velocity based on cos of the previous angle, but i have yet to get that to work successfully.

While the movement is similar to an orbit, It doesn't need to follow most of the rules orbits do. Also, the input parameters are completely different from a normal orbital mechanics equation, and the objective is to create offsets for a single object over time, rather than to figure out the position of a large number of objects given an observer position and a database of stellar coordinates.

S. Casey
  • 167
  • 2
  • 8
  • 4
    You need a physicist, not a programmer. https://en.wikipedia.org/wiki/Kepler's_laws_of_planetary_motion Scroll down to "Position as a function of time." – Jive Dadson Mar 19 '18 at 14:40
  • Those laws seem a lot more complicated than what I have so far. Are you sure that the only way to vary the velocity is by rewriting this using Kepler's laws? I'm not trying to model planetary motion after all. If so, where would I find a physicist that I can ask about this? The physics stack exchange seems to have even more complicated stuff and I'm not sure that they will be familiar with the code part. – S. Casey Mar 19 '18 at 14:59
  • 1
    Go to the physicists to get the formula. It might be simpler than you imagine. Try to implement it. If you can't, call us again. – Jive Dadson Mar 19 '18 at 15:01
  • Alright, thanks Jive. – S. Casey Mar 19 '18 at 15:02
  • Possible duplicate of [How to draw sky chart?](https://stackoverflow.com/questions/9646360/how-to-draw-sky-chart) – Spektre Mar 19 '18 at 15:27
  • @S.Casey see the duplicate I linked there you will find both equation and code ... also see [Is it possible to make realistic n-body solar system simulation in matter of size and mass?](https://stackoverflow.com/a/28020934/2521214) it might give you more ideas ... – Spektre Mar 19 '18 at 15:28
  • @Spektre While I appreciate the suggestion, and according to the page linked to in the sky chart question the orbiting object moves fastest at perihelion, which is what i want, I don't have most of the variables listed. The only values I have currently are the radius at perihelion and aphelion, and the period. How would I get the Keplerian elements from those three variables? The problem is a lot closer to a train on an elliptic track that slows down at the far ends than a planet in orbit, but if orbital mechanics is the best way to simulate it then I'll use that. – S. Casey Mar 19 '18 at 16:53
  • *varying the velocity based on cos of the previous angle* ... Why does this not work? – Ripi2 Mar 19 '18 at 20:10
  • 1
    @Ripi2 that is too complicated to do with low accuracy results... due to properties of ellipse and speed behavior. Kepler and or Newton / D'Lambert are the simplest and more accurate approaches. – Spektre Mar 19 '18 at 20:14
  • 1
    @S.Casey I added simple C++ code using just `a,b,M` into the [duplicate](https://stackoverflow.com/a/25403425/2521214) not using the other orbital parameters – Spektre Mar 19 '18 at 20:15
  • 1
    @S.Casey I added better image describing the Kepler equation into the duplicate – Spektre Apr 04 '18 at 11:06

1 Answers1

1

It sounds from your question as though you'd like a way of tuning the spacing of sample points around the ellipse, rather than having a particular physical system that is generating an orbit. Obviously, if you have an elliptical orbit defined by a gravitational field, then the equations for that are well known, and provide a fixed relationship between the velocity and position as functions of time.

If all you want is a tunable spacing of your points around the ellipse, then one way you can achieve this is simply to have your "angle" parameter varying non-linearly, but in a way that still guarantees to monotonically cover the range [0,2*pi]. Suppose that you have a "time" coordinate that covers the range [0,2*pi], but your "angle" is defined by the following relation:

enter image description here

where the skewness parameter, a, must be in the range (-0.5, 0.5) to ensure that the angle does not backtrack at any point on the curve. If a=0.3, this produces a trend like this:

enter image description here

where the gradient of the curve is steepest near where theta is a multiple of pi, and shallowest near odd multiples of pi/2.

Your ellipse can then be generated by the usual recipe:

enter image description here

Suppose we generate a sequence of 100 points uniformly spaced in t, and start with a=0, then we get a profile like this:

enter image description here

If we increase a to 0.2, we get points that become more tightly grouped near the y-axis:

enter image description here

Increasing a still further to 0.48, we get an even tighter bunching:

enter image description here

In Python, this can be implemented by something like the following:

import numpy

xRadius = 10
yRadius = 5
skew = 0.48

t = numpy.linspace(0, 2 * numpy.pi, 100)
theta = t + skew * numpy.sin(2*t)
x = xRadius * numpy.cos(theta)
y = yRadius * numpy.sin(theta)

Obviously, the corresponding code in C++ is more verbose, but straightforward to implement.

rwp
  • 1,786
  • 2
  • 17
  • 28