How to simulate pendulum movement with high amplitude in C# - c#

I need to make a C# simulator for a simple pendulum.
I have been searching the web for 3 days and I am stuck.
The problem is I have found many equations that would give the angle position as a function of time, which is perfect for my needs for making a visual simulation but the problem is those functions only works for angles smaller than 10, but I should be able to simulate from any angle.
Example of a equation that only works for small angles:
Source: http://hyperphysics.phy-astr.gsu.edu/hbase/pend.html#c2
And the equations that should work for any angle (Amplitude) are too complicated as it involves differential equations, and derivatives. I don't know how to implement these in C#.
Example of a equation that I think would work but I don't know how to use:
Source: http://www.sbfisica.org.br/rbef/pdf/070707.pdf
(Equation number 32)
the problem of this last equation is the "sn" that is Jacobi elliptic function sn(u;m) u, and I don't know how to use in C#
Can someone help? maybe with another equation that I could use programmatically, or helping me understand how I could use this last one if it would really works.

If you want to simulate the pendulum, you don't need the exact solution. The only you need is a sufficiently good approximation at every step of your simulation, combined with sufficient steps. This is similar to approximating a circle with a sufficiently large number of segments, each of them, tangent to the ideal circle.
Now, consider your pendulum has a deviation of theta degrees (or radians) from the vertical as depicted below:
The mass m will have a weight of m * g, where g is the gravity acceleration. Now, let's approximate the angle alpha where the pendulum will move in the next dt seconds (dt is the duration of one step, so dt is just a fraction of a second).
Since the acceleration on the tangent direction is g * cos(theta) we can approximate the tangent distance the pendulum would travel in dt seconds as if the acceleration were constant during this lapse:
d = v * dt + g * sin(theta) (dt)^2 / 2
where v is the tangential speed of the pendulum at the angular position theta. Now we can calculate alpha as
alpha = arcsin(d / r)
where r is the radius. Thus, the only that remains is to update the value of v so we can repeat the same in the next step. Here is how
v := v + g * sin(theta) * dt
Of course, when the pendulum starts you can initialize v = 0.
I haven't tried this myself, so please, let me know if this "simulated" approach worked for you. Good luck!

Related

converting xinput coordinates to a square

i'm working on a small c# program that uses xinput to read the xbox 360 thumb stick.
i have no problem with reading the coordinates and normalizing the values so i get a float between -1 and +1 for X and Y directions.
the problem i have is that the stick itself is physically limited to a circle and in my case i would like to "stretch out" the coordinates so it becomes more of a square than a circle.
the reason is that each direction is controlling a motor and if i move the stick for example top right i would like both X and Y to become 1.
since the stick is circular this is not possible and this also makes it impossible to make both motors run at full speed.
any advice?
So you want a point on a circle of radius r to be mapped to a point on a square of radius r on the same ray through the origin. Toward that goal you have to compute the radius using the usual formula
r = sqrt(x*x+y*y)
and then from that the scale factor
f = r / max ( abs(x), abs(y) )
and in the end replace x by f*x and y by f*y.
One can vary this computation by noting that the factor is
f = sqrt ( 1 + (x*x)/(y*y) )
if abs(y) > abs(x) and
f = sqrt ( 1 + (y*y)/(x*x) )
in the opposite case. Or by noting that the largest coordinate gets replaced by r and the smaller scaled accordingly, which also does not reduce the logistics by much.

Shortest distance from a point to this curve

I need to find the distance of multiple points to a curve of the form: f(x) = a^(k^(bx))
My first option was using its derivative, using a line of the form with the inverse of the derivative, giving it coordinates of the Point and intersecting it with the original curve. Finally, we calculate the distance between points with simple geometry.
That's the mathematical process that I usually follow. I need to save time (since I'm doing a genetic algorithms program) so I need an efficient way to do this. Ideas?
The distance between a point (c,d) and your curve is the minimum of the function
sqrt((c-x)^2 + (d-a^(k^(bx)))^2)
To find its minimum, we can forget about the sqrt and look at the first derivative. Find out where it's 0 (it has to be the minimal distance, as there's no maximum distance). That gives you the x coordinate of the nearest point on the curve. To get the distance you need to calculate the y coordinate, and then calculate the distance to the point (you can just calculate the distance function at that x, it's the same thing).
Repeat for each of your points.
The first derivative of the distance function, is, unfortunately, a kind of bitch. Using Wolfram's derivator, the result is hopefully (if I haven't made any copying errors):
dist(x)/dx = 2(b * lna * lnk * k^(bx) * a^(k^(bx)) * (a^(k^(bx)) - d) - c + x)
To find distance from point to curve it's not a simple task, for that you need to find the global of function where f(x) is the function which determine your curve.
For that goal you could use:
Simplex method
Nelder_Mead_method
gradient_descent
This methods implemented in many libraries like Solver Foundation, NMath etc.

create sketchy / wobbly line using 1D perlin noise

Could somebody help me get started with pseudo code or steps to use the 1D perlin noise to draw sketchy/wobbly lines as depicted in the page
http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
(source: virgin.net)
I did find that aforge.net has functions for 1D and 2D perlin noise functions. It shows an example ofusing the 2D noise to generate clouds.
http://www.aforgenet.com/framework/docs/html/f2f36ce1-ddab-389e-b538-0ccaca81fa87.htm
But am not sure how to go about using it to generate wobbly lines.
Only difference you need to make going from 1D to 2D is to calculate the slope. Once you have the slope and the 1D noise, just add that noise in the direction perpendicular to the direction of slope.
I saw your question hoping for pseudocode as an answer. I ended up not using the gradient (I already have a simplex noise function that would be difficult to make compatible) but doing something else.
The idea is to choose an interval length (unity is fine, but larger ones will yield less rounding error) and using a random seed consider the noise interval [s, s + I] where I is the interval length and s is the seed. You then "wrap" it around a circle by mapping an angle theta to I / (2 * Pi) * theta. However, you need to make sure that the noise values of s and s + I are the same, else you would have a discontinuity in the circle. This is easy, however; given x in [s, s + I], just do this:
interpolate(x, s, I)
mid <- noise(s) - noise(s + I)
out <- noise(x)
out <- out + (x - s) / I * mid
out <- out - (s + I - x) / I * mid
return out
Note that if x = s, we subtract mid, and if x = s + I, we add mid.
We now have a mapping from an angle to a noise value. Given the radius we wish our circle to have, we can set the minimum and maximum values of the noise then, for any theta we wish to evaluate, just add the corresponding value to the radius of the circle. In polar coordinates, this looks like:
radius(theta)
s <- randomDouble
I <- 1
theta <- theta / (2 * pi)
dr <- interpolate(theta, s, I)
dr <- dr * (noisemax - noisemin) / 2 + (noisemax + noisemin) / 2
return dr + r
assuming you already have your average radius (r) and the variance you want (noisemin, noisemax), and that your noise function outputs values in [-1, 1]. You will want a tight spread between noisemax and noisemin, else your circle will be mostly wobble.
For a square the process it the same but you do not need any controls or interpolation, just the scaling factors and an interval square side length.
You can get fancy and do a nonlinear interpolation but I don't really see the need, and it might mess up the simplex noise.

When to Normalize a Vector?

I am learning XNA and in almost all of the educational kits found on http://creators.xna.com/en-US/. I always see a call to Normalize() on a vector. I understand that normalize basically converts the vector into unit length, so all it gives is direction.
Now my question is When to normalize and what exactly does it help me in. I am doing 2D programming so please explain in 2D concepts and not 3D.
EDIT: Here is code in the XNA kit, so why is the Normalize being called?
if (currentKeyboardState.IsKeyDown(Keys.Left)
|| currentGamePadState.DPad.Left == ButtonState.Pressed)
{
catMovement.X -= 1.0f;
}
if (currentKeyboardState.IsKeyDown(Keys.Right)
|| currentGamePadState.DPad.Right == ButtonState.Pressed)
{
catMovement.X += 1.0f;
}
if (currentKeyboardState.IsKeyDown(Keys.Up)
|| currentGamePadState.DPad.Up == ButtonState.Pressed)
{
catMovement.Y -= 1.0f;
}
if (currentKeyboardState.IsKeyDown(Keys.Down)
|| currentGamePadState.DPad.Down == ButtonState.Pressed)
{
catMovement.Y += 1.0f;
}
float smoothStop = 1;
if (catMovement != Vector2.Zero)
{
catMovement.Normalize();
}
catPosition += catMovement * 10 * smoothStop;
In your example, the keyboard presses give you movement in X or Y, or both. In the case of both X and Y, as when you press right and down at the same time, your movement is diagonal. But where movement just in X or Y alone gives you a vector of length 1, the diagonal vector is longer than one. That is, about 1.4 (the square root of 2).
Without normalizing the movement vector, then diagonal movement would be faster than just X or Y movement. With normalizing, the speed is the same in all 8 directions, which I guess is what the game calls for.
One common use case of vector normalization when you need to move something by a number of units in a direction. For example, if you have a game where an entity A moves towards an entity B at a speed of 5 units/second, you'll get the vector from A to B (which is B - A), you'll normalize it so you only keep the direction toward the entity B from A's viewpoint, and then you'll multiply it by 5 units/second. The resulting vector will be the velocity of A and you can then simply multiply it by the elapsed time to get the displacement by which you can move the object.
It depends on what you're using the vector for, but if you're only using the vectors to give a direction then a number of algorithms and formulas are just simpler if your vectors are of unit length.
For example, angles: the angle theta between two unit vectors u and v is given by the formula cos(theta) = u.v (where . is the dot product). For non-unit vectors, you have to compute and divide out the lengths: cos(theta) = (u.v) / (|u| |v|).
A slightly more complicated example: projection of one vector onto another. If v is a unit vector, then the orthogonal projection of u onto v is given by (u.v) v, while if v is a non-unit vector then the formula is (u.v / v.v) v.
In other words: normalize if you know that all you need is the direction and if you're not certain the vector is a unit vector already. It helps you because you're probably going to end up dividing your direction vectors by their length all the time, so you might as well just do it once when you create the vector and get it over with.
EDIT: I assume that the reason Normalize is being called in your example is so that the direction of velocity can be distinguished from the speed. In the final line of the code, 10 * smoothStop is the speed of the object, which is handy to know. And to recover velocity from speed, you need to multiply by a unit direction vector.
You normalize any vector by dividing each component by the magnitude of the vector, which is given by the square root of the sum of squares of components. Each component then has a magnitude that varies between [-1, 1], and the magnitude is equal to one. This is the definition of a unit vector.

slight changes in long lat for varations of point with the same location

Bit of a weird one this. I'm rendering datasets on a map and need to split out points that have exactly the same long and lat. I had the idea of grouping my dataset by long and lat and where they are the same adjusting slightly so that they are visible as seperate entities on the map - rather than overlapping.
I'm using linq to group them and then enumerating my grouped items and I'd like to spiral the adjusted points around the orginal point (this is a requirement as I may have a few hundred points that are the same geographically) so that they spread out from the original point.
Does anyone know of a simple calculation i can add to my loop to adjust the items in this manner.
Thanks,
The math behind this is pretty simple. A circle can be represented by the sine function in the x-axis and the cosine function in the y-axis. Here's some pseudo-code:
int num = OverlappingPoints.Length;
for(int i = 0; i < num; ++i)
{
int radius = 50;
// using 2*pi because most math functions use radians... change 2*pi to 360 if your math library uses 360 degrees instead of 2*pi radians to represent a circle.
Map.Plot(OverlappingPoints[i].Latitude + radius*sin(2*pi*i/num),
OverlappingPoints[i].Latitude + radius*cos(2*pi*i/num));
}
That pseudo-code, if properly implemented, will draw the points out in a circle around the original point. Change the radius multiplier to the sine and cosine functions if you want to increase the radius of the circle. If you want the points to spiral out instead of making a circle, choose a number of points per circle revolution and replace num with that number in the sin/cos functions. Also, increase the radius after each loop iteration, probably by using a number and multiplying it by the loop index. (i.e. you could change radius to 50*i).
Hope this helps.

Categories

Resources