How to reset a variable back to 0 after use in a loop in NXC - lego-mindstorms

For some odd reason the variable "angle" will not reset back to 0 when the loop ends.
All of the math is just calculating c = sqrt(a^2 + b^2 - 2abCos(theta)) the robot won't do all of the math in one line.
In the full code a and b are both changing variables and are based on ultrasonic sensor input.
The sub may be called up to 3 different times and the angle variable needs to start at 0 each time the sub is called.
I have tried putting float angle = 0; or just angle = 0; in every spot imaginable but nothing works. I have even tried using int angle = 0; in multiple places.
int angle, a, b, c, csqr, theta, cosTheta, aSqrd, bSqrd, atmb, twoab;
#define pi 3.14159265359
sub calculate()
{
repeat(2)
{
float a = 172.42;
float angle = angle + 3;
float theta = ((angle)*(pi/180));
float b = 172.42;
float cosTheta = cos(theta);
float aSqrd = pow(a, 2);
float bSqrd = pow(b, 2);
float atmb = (a * b);
float twoab = (2 * atmb);
float csqr = ((aSqrd + bSqrd) - (twoab * cosTheta));
float c = sqrt(csqr);
NumOut(0,0,angle);
Wait(3000);
ClearScreen();
}
float angle = 0;
}
task main()
{
calculate();
ClearScreen();
calculate();
}

Because float angle is local to the calculate method and hides the int angle in global scope. The int angle is not initialized to anything.

You have an uninitialized variable in the repeat(2) loop.
float angle = angle + 3;

Related

Problems and Inaccuracies Converting + Interpreting Unity Shadergraph to C#

Context
I've been trying to create a buoyancy script that samples the position of a point, tests if it's under a certain level (the "water level"), and adds a force on that position based on depth. Separately, I worked on creating a nice looking water shader in Shadergraph, and had the bright idea to add in waves using the Simple Noise node + vertex displacement.
However, the only way (I could think of) to use those displaced values as the float "water level" was to rewrite the entire node tree in C#, and use that to sample the "water level" at that position.
Problem
For some reason, the final displaced mesh and the calculated positions are different, causing the buoyancy script to assume that the "water level" is higher/lower than it is. The difference isn't large, so I'm assuming there's an error somewhere within either the C# Node Graph or C# Simple Noise translation.
Is that correct? If so, where and what's my misunderstanding? If not, what else could have gone wrong?
Approach
Node Graph
Image of the node graph for the wave vector displacement
*If you need zoomed in pictures, let me know!
All things considered, it's relatively simple. It:
Takes the world position as a UV, and offsets and tiles it.
Feeds the UV to a Simple Noise node, and multiplies the noise by a strength.
Clamps the output.
Repeats 1-3 again and adds both together for more detail.
Replaces the Y value of the vertex position with the combined wave value.
C# Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaveHeightCalculator : MonoBehaviour
{
// Step 1
[SerializeField] Material _waterMaterial;
[Header("Waves")]
[SerializeField] float _waveTiling;
[SerializeField] float _waveOffset;
[SerializeField] float _waveMin;
[SerializeField] float _waveMax;
[Header("Small Waves")]
[SerializeField] float _wavesSmallScale;
[SerializeField] float _wavesSmallStrength;
[SerializeField] Vector2 _wavesSmallVelocity;
[Header("Large Waves")]
[SerializeField] float _wavesLargeScale;
[SerializeField] float _wavesLargeStrength;
[SerializeField] Vector2 _wavesLargeVelocity;
// Step 2
private void OnValidate()
{
_waterMaterial = GetComponent<Renderer>().sharedMaterial;
SetVariables();
}
void SetVariables()
{
_waveTiling = _waterMaterial.GetFloat("_Wave_Tiling");
_waveOffset = _waterMaterial.GetFloat("_Wave_Offset");
_waveMin = _waterMaterial.GetFloat("_Wave_Min");
_waveMax = _waterMaterial.GetFloat("_Wave_Max");
_wavesSmallScale = _waterMaterial.GetFloat("_Waves_Small_Scale");
_wavesSmallStrength = _waterMaterial.GetFloat("_Waves_Small_Strength");
_wavesSmallVelocity = _waterMaterial.GetVector("_Waves_Small_Velocity");
_wavesLargeScale = _waterMaterial.GetFloat("_Waves_Large_Scale");
_wavesLargeStrength = _waterMaterial.GetFloat("_Waves_Large_Strength");
_wavesLargeVelocity = _waterMaterial.GetVector("_Waves_Large_Velocity");
}
// Step 3
public float GetWaveHeightAtPosition(Vector3 position)
{
Vector2 noiseMapUV;
noiseMapUV = new Vector2(position.x, position.z) * _waveTiling;
// Calculate Small Waves
Vector2 wavesSmallUVOffset = (Time.time / 20) * _wavesSmallVelocity;
float noiseValueAtUVPlusOffset = UnitySimpleNoiseAtUV(noiseMapUV + wavesSmallUVOffset, _wavesSmallScale);
float wavesSmall = noiseValueAtUVPlusOffset * _wavesSmallStrength;
// Calculate Large Waves
Vector2 wavesLargeUVOffset = (Time.time / 20) * _wavesLargeVelocity;
noiseValueAtUVPlusOffset = UnitySimpleNoiseAtUV(noiseMapUV + wavesLargeUVOffset, _wavesLargeScale);
float wavesLarge = noiseValueAtUVPlusOffset * _wavesLargeStrength;
// Combine
float waveHeight = wavesSmall + wavesLarge;
// Clamp
waveHeight = Mathf.Clamp(waveHeight, _waveMin, _waveMax);
// Offset
waveHeight += _waveOffset;
return waveHeight;
}
In the C# script, a couple of things are going on. Here's my thought process for it:
It assigns the relevant material properties to member variables.
It sets those variables in the OnValidate() function.
It uses those variables to calculate the wave value; equivalent to the "water level".
The script also contains and relies on my best attempt at translating the Simple Noise node from "Show Generated Code", which looked liked this.
Generated Code
inline float Unity_SimpleNoise_RandomValue_float (float2 uv)
{
float angle = dot(uv, float2(12.9898, 78.233));
#if defined(SHADER_API_MOBILE) && (defined(SHADER_API_GLES) || defined(SHADER_API_GLES3) || defined(SHADER_API_VULKAN))
// 'sin()' has bad precision on Mali GPUs for inputs > 10000
angle = fmod(angle, TWO_PI); // Avoid large inputs to sin()
#endif
return frac(sin(angle)*43758.5453);
}
inline float Unity_SimpleNnoise_Interpolate_float (float a, float b, float t)
{
return (1.0-t)*a + (t*b);
}
inline float Unity_SimpleNoise_ValueNoise_float (float2 uv)
{
float2 i = floor(uv);
float2 f = frac(uv);
f = f * f * (3.0 - 2.0 * f);
uv = abs(frac(uv) - 0.5);
float2 c0 = i + float2(0.0, 0.0);
float2 c1 = i + float2(1.0, 0.0);
float2 c2 = i + float2(0.0, 1.0);
float2 c3 = i + float2(1.0, 1.0);
float r0 = Unity_SimpleNoise_RandomValue_float(c0);
float r1 = Unity_SimpleNoise_RandomValue_float(c1);
float r2 = Unity_SimpleNoise_RandomValue_float(c2);
float r3 = Unity_SimpleNoise_RandomValue_float(c3);
float bottomOfGrid = Unity_SimpleNnoise_Interpolate_float(r0, r1, f.x);
float topOfGrid = Unity_SimpleNnoise_Interpolate_float(r2, r3, f.x);
float t = Unity_SimpleNnoise_Interpolate_float(bottomOfGrid, topOfGrid, f.y);
return t;
}
void Unity_SimpleNoise_float(float2 UV, float Scale, out float Out)
{
float t = 0.0;
float freq = pow(2.0, float(0));
float amp = pow(0.5, float(3-0));
t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
freq = pow(2.0, float(1));
amp = pow(0.5, float(3-1));
t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
freq = pow(2.0, float(2));
amp = pow(0.5, float(3-2));
t += Unity_SimpleNoise_ValueNoise_float(float2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
Out = t;
}
/* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreVertex' */
// Graph Vertex
// GraphVertex: <None>
/* WARNING: $splice Could not find named fragment 'CustomInterpolatorPreSurface' */
// Graph Pixel
struct SurfaceDescription
{
float4 Out;
};
Translated Code
float float_frac(float x) { return x - Mathf.Floor(x);}
Vector2 frac(Vector2 x) { return x - new Vector2(Mathf.Floor(x.x), Mathf.Floor(x.y));}
float sin(float x) { return Mathf.Sin(x);}
float dot(Vector2 a, Vector2 b) { return a.x * b.x + a.y * b.y;}
float float_floor(float x) { return Mathf.Floor(x);}
Vector2 floor(Vector2 x) { return new Vector2(Mathf.Floor(x.x), Mathf.Floor(x.y));}
float float_abs(float x) { return Mathf.Abs(x);}
Vector2 abs(Vector2 x) { return new Vector2(Mathf.Abs(x.x), Mathf.Abs(x.y));}
float pow (float x, float y) { return Mathf.Pow(x, y);}
float Unity_SimpleNoise_RandomValue_float (Vector2 uv)
{
float angle = dot(uv, new Vector2(12.9898f, 78.233f));
return float_frac(sin(angle) * 43758.5453f);
}
float Unity_SimpleNnoise_Interpolate_float (float a, float b, float t)
{
return (1.0f - t) * a + (t * b);
}
float Unity_SimpleNoise_ValueNoise_float (Vector2 uv)
{
Vector2 i = floor(uv);
Vector2 f = frac(uv);
f = (f * f) * (new Vector2 (3.0f, 3.0f) - new Vector2(2.0f, 2.0f) * f);
uv = abs(frac(uv) - new Vector2 (0.5f, 0.5f));
Vector2 c0 = i + new Vector2(0.0f, 0.0f);
Vector2 c1 = i + new Vector2(1.0f, 0.0f);
Vector2 c2 = i + new Vector2(0.0f, 1.0f);
Vector2 c3 = i + new Vector2(1.0f, 1.0f);
float r0 = Unity_SimpleNoise_RandomValue_float(c0);
float r1 = Unity_SimpleNoise_RandomValue_float(c1);
float r2 = Unity_SimpleNoise_RandomValue_float(c2);
float r3 = Unity_SimpleNoise_RandomValue_float(c3);
float bottomOfGrid = Unity_SimpleNnoise_Interpolate_float(r0, r1, f.x);
float topOfGrid = Unity_SimpleNnoise_Interpolate_float(r2, r3, f.x);
float t = Unity_SimpleNnoise_Interpolate_float(bottomOfGrid, topOfGrid, f.y);
return t;
}
float UnitySimpleNoiseAtUV(Vector2 UV, float Scale)
{
float t = 0.0f;
float freq = pow(2.0f, 0);
float amp = pow(0.5f, 3-0);
t += Unity_SimpleNoise_ValueNoise_float(new Vector2(UV.x*Scale/freq, UV.y*Scale/freq))*amp;
freq = pow(2.0f, 1);
amp = pow(0.5f, 3-1);
t += Unity_SimpleNoise_ValueNoise_float(new Vector2(UV.x * Scale / freq, UV.y * Scale / freq)) * amp;
freq = pow(2.0f, 2);
amp = pow(0.5f, 3-2);
t += Unity_SimpleNoise_ValueNoise_float(new Vector2(UV.x * Scale / freq, UV.y * Scale / freq)) * amp;
return t;
}

Get angle to land ballistic arc on target with fixed velocity projectile

So I was trying to follow the code in this question to get a turret that can fire ballistic projectiles with a fixed starting velocity and no drag to a given point on a 3D surface.
Find an angle to launch the projectile at to reach a specific point
But It's not quite working. The turret ends up aiming too high when the target is close, and too low when the target is further away. There is of course a specific distance at which it does hit the target but that distance is arbitrary, so that's not at all helpful to me.
The way the error scales makes me think I have a multiplication mistake, or am missing some multiplication or division, but I can't for the life of me figure out where I am going wrong. Can anyone point me in the right direction?
Code Below:
float CalculateAngle(float velocity)
{
float gravity = -Physics.gravity.y;
Vector3 modPos = target.position;
if (modPos.x < 0) modPos.x -= 2 * modPos.x;
if (modPos.y < 0) modPos.y -= 2 * modPos.y;
if (modPos.z < 0) modPos.z -= 2 * modPos.z;
modPos.x /= 10;
modPos.y /= 10;
modPos.z /= 10;
float deltaX = modPos.x - FirePoint.position.x;
float deltaZ = modPos.z - FirePoint.position.z;
float deltaY = modPos.y - FirePoint.position.y;
float horzDelta = Mathf.Sqrt(deltaX * deltaX + deltaZ * deltaZ);
float RHSFirstPart = (velocity * velocity) / (gravity * horzDelta);
float RHSSecondPart = Mathf.Sqrt(((velocity * velocity) * ((velocity * velocity) - (2 * gravity * deltaY))/ (gravity * gravity * horzDelta * horzDelta)) - 1);
float tanθ = RHSFirstPart - RHSSecondPart;
float angle = Mathf.Atan2(tanθ, 1) * Mathf.Rad2Deg;
if (angle < 0) return angle;
return -angle;
}
Edit 1:
Still struggling heavily with this. I just can't get the math to work. I went back to the original root of the knowledge here https://physics.stackexchange.com/questions/56265/how-to-get-the-angle-needed-for-a-projectile-to-pass-through-a-given-point-for-t then wrote a function that did the exact equation given in the answers, copying the input values and everything. Except when I run it it fails, as one of the values that needs to be squared is negative which throws a NaN. I assume I am going wrong somewhere in my equation but I've gone over it a hundred times and I am not spotting the error. My code:
float CalculateAngle3(float velocity)
{
float deltaX = 500;
float deltaY = 20;
float v = 100;
float vSqr = v * v;
float g = 9.81f * 9.81f;
float a = vSqr * (vSqr - 2 * g * deltaY);
float b = (g * g) * (deltaX * deltaX);
float c = a / b - 1;
float d = Mathf.Sqrt(c); //c is negitive causing an NaN
float e = vSqr / g * deltaX;
float tanθ = e - d;
return tanθ;
}
Edit 2:
Gave up. This guy solved it so I am just going to use his logic instead
: P
https://www.forrestthewoods.com/blog/solving_ballistic_trajectories/
Using it like such:
Vector3 s0;
Vector3 s1;
if (fts.solve_ballistic_arc(FirePoint.position, bomb.StartingVelocity.z, target.position, -Physics.gravity.y, out s0, out s1) > 0)
{
targetPosition = transform.position + s1;
SafetyEnabled = false;
}
else
{
//Don't fire if we don't have a solution
SafetyEnabled = true;
}
I'm going to leave the question open for now since it's still technically not answered. I still don't know why the original implementation wasn't working.
It is possible your quadratic formula is incorrect (I do not know why you did not code a separate small function that solves the quadratic equation for any three given coefficients, to make your code more readable and less prone to errors)
float RHSFirstPart = velocity / (gravity * horzDelta);
float RHSSecondPart = Mathf.Sqrt(RHSFirstPart*RHSFirstPart - 2*RHSFirstPart*deltaY/horzDelta - 1);
float tanθ = RHSFirstPart - RHSSecondPart;
A comment: In most applications we do not really need the actual angle but the values of cos(angle) and sin(angle) because these are the components of the unit vector which usually is sought (just like in your case). So no need to use inverse trigonometry to find an actual number, which slows down calculations and is may introduce unnecessary round-off errors.

How to draw multiple circles by using "LineRenderer"

There is a code for a drawing circle with LineRenderer.
but I want to draw multiple circles with different radius, I used "for loop" but there is one circle instead of multiple
public float ThetaScale = 0.01f;
public float radius = 3f;
private int Size;
private LineRenderer LineDrawer;
private float Theta = 0f;
void Start ()
{
LineDrawer = GetComponent<LineRenderer>();
}
void Update ()
{
Theta = 0f;
Size = (int)((1f / ThetaScale) + 1f);
LineDrawer.SetVertexCount(Size);
for (int l = 0; l < 5; l++)
{
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
LineDrawer.SetPosition(i, new Vector3(x, 0, y));
}
}
}
In every loop you always overwrite the same positions indices in the same line renderer. So you will always only have the last circle.
Note that it is also quite expensive to use SetPoisition repeatedly. As it says in the API you should rather work on an array and then use SetPoisitions to assign all positions at once.
One thing is a bit unclear though: If you use one single LineRenderer you won't get independent circles but they will always be connected at some point. Otherwise you would need 5 separated LineRenderer instances.
Option A: 5 circles but connected to each other since part of a single LineRenderer
void Start ()
{
LineDrawer = GetComponent<LineRenderer>();
LineDrawer.loop = false;
Theta = 0f;
// Use one position more to close the circle
Size = (int)((1f / ThetaScale) + 1f) + 1;
LineDrawer.positionCount = 5 * Size;
var positions = new Vector3[5 * Size];
for (int l = 0; l < 5; l++)
{
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
positions[5 * l + i] = new Vector3(x, 0, y);
}
}
LineDrawer.SetPositions(positions);
}
Option B: 5 separated circles in 5 separated LineRenderers
// Drag 5 individual LineRenderer here via the Inspector
public LineRenderer[] lines = new LineRenderer[5];
void Start ()
{
foreach(var line in lines)
{
line.loop = true;
Theta = 0f;
Size = (int)((1f / ThetaScale) + 1f);
line.positionCount = Size;
var positions = new Vector3[Size];
for(int i = 0; i < Size; i++)
{
Theta += (2.0f * Mathf.PI * ThetaScale);
float x = l * radius * Mathf.Cos(Theta);
float y = l * radius * Mathf.Sin(Theta);
positions[5 * l + i] = new Vector3(x, 0, y);
}
line.SetPositions(positions);
}
}
You missed few details here and there. Here, this will work:
using UnityEngine;
[ExecuteAlways]
[RequireComponent( typeof(LineRenderer) )]
public class CircularBehaviour : MonoBehaviour
{
[SerializeField][Min(3)] int _numSegments = 16;
[SerializeField][Min(1)] int _numCircles = 5;
[SerializeField] float _radius = 3f;
LineRenderer _lineRenderer;
void Awake ()
{
_lineRenderer = GetComponent<LineRenderer>();
_lineRenderer.loop = false;
_lineRenderer.useWorldSpace = false;
}
void Update ()
{
const float TAU = 2f * Mathf.PI;
float theta = TAU / (float)_numSegments;
int numVertices = _numSegments + 1;
_lineRenderer.positionCount = numVertices * _numCircles;
int vert = 0;
for( int l=1 ; l<=_numCircles ; l++ )
{
float r = _radius * (float)l;
for( int i=0 ; i<numVertices ; i++ )
{
float f = theta * (float)i;
Vector3 v = new Vector3{ x=Mathf.Cos(f) , y=Mathf.Sin(f) } * r;
_lineRenderer.SetPosition( vert++ , v );
}
}
}
}
But
as #derHugo explained, this is not what you're looking for exactly as all circles will be drawn connected.

My object is moving too fast in Unity?

I am suppose to implement a CatMull Rom Spline, and I have it implemented, but the sphere moves to the points extremely fast. I thought if I used Time.DeltaTime it would slow it down, but it moves too rapidly.
Function to compute point on curve:
Vector3 ComputePointOnCatmullRomCurve(float u, int segmentNumber)
{
// TODO - compute and return a point as a Vector3
// Points on segment number 0 start at controlPoints[0] and end at controlPoints[1]
// Points on segment number 1 start at controlPoints[1] and end at controlPoints[2]
// etc...
Vector3 point = new Vector3();
float c0 = ((-u + 2f) * u - 1f) * u * 0.5f;
float c1 = (((3f * u - 5f) * u) * u + 2f) * 0.5f;
float c2 = ((-3f * u + 4f) * u + 1f) * u * 0.5f;
float c3 = ((u - 1f) * u * u) * 0.5f;
Vector3 p0 = controlPoints[(segmentNumber - 1) % NumberOfPoints];
Vector3 p1 = controlPoints[segmentNumber % NumberOfPoints];
Vector3 p2 = controlPoints[(segmentNumber + 1) % NumberOfPoints];
Vector3 p3 = controlPoints[(segmentNumber + 2) % NumberOfPoints];
point.x = (p0.x * c0) + (p1.x * c1) + (p2.x * c2) + (p3.x * c3);
point.y = (p0.y * c0) + (p1.y * c1) + (p2.y * c2) + (p3.y * c3);
point.x = (p0.z * c0) + (p1.z * c1) + (p2.z * c2) + (p3.z * c3);
return point;
}
**Update Function: **
void Update ()
{
// TODO - use time to determine values for u and segment_number in this function call
// 0.5 Can be used as u
time += DT;
segCounter++;
Vector3 temp = ComputePointOnCatmullRomCurve(time, segCounter);
transform.position = temp;
}
Variables:
const int NumberOfPoints = 8;
Vector3[] controlPoints;
const int MinX = -5;
const int MinY = -5;
const int MinZ = 0;
const int MaxX = 5;
const int MaxY = 5;
const int MaxZ = 5;
float time = 0;
const float DT = 0.01f;
public static int segCounter = 0;
EDIT: Sorry the calculations, and all of that is correct. It's straight from the slides, I just need help with the update function :(
Using Time.deltaTime allows you to be framerate independent. This means that if the framerate drops, or a frame takes longer than the others, your object will adapt the moving distance to keep a constant speed. This is generally a good idea.
Back to your case: Basically you want to pass a position to your function. You currently pass the time. If your catmull rom considers that 0 is the start and 1 is the destination, then after exactly 1 second, you will be at the end of the spline. (Note that this is where being framerate independent is interesting: Whatever the frame rate is. you reach the end in one second). Now, how to convert from time to position. Easy
position = time*speed;
Since time is in second, speed is in units per seconds. Say your catmullrom is one unit long. If speed is two, if will take one second to travel it twice. so half a second to travel it. Since you want to lower the speed, you might want to use values below 1. Try this:
void Update ()
{
time += Time.deltaTime;
var speed = 0.1f;
var splinePos = speed * time;
segCounter++;
Vector3 temp = ComputePointOnCatmullRomCurve(splinePos, segCounter);
transform.position = temp;
}

Simulate Terminal Velocity

I am working on building a little game program like this one for a sky diving sim and I have got a lot of the equations down but my terminal velocity is way too high for the given alt for any of this. I have been looking at this and gone over it the only thing I can think of is that I have one of the measurements wrong or something. Any help will be appreciated with this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GasLaws
{
class Program
{
static void Main(string[] args)
{
double temperature;
double airPressure;
double airDensity;
double tV;
double alt;
//constants
const double gasCont = 287.05;
const double startTemp = 15; //this is C ground level
const double aidRate = 0.0065; //adiobatic rate for temperature by elevation
//Human Constannts
const double drag = 0.7; //in meters
const double area = 7.5; //ft^2
const double wieght = 175;
Console.WriteLine("Enter the alt in feet");
int tempint = Int32.Parse(Console.ReadLine());
alt = (double)tempint * 0.3048; //convert feet to meters
Console.WriteLine("Alt = " + alt + " m");
//calculate air pressur
airPressure = AirPressure(alt);
temperature = CalTemp(startTemp, alt, aidRate);
airDensity = AirDensity(airPressure, gasCont, temperature);
tV = TerminalVelocity(wieght, drag, airDensity, area);
//pasue screen for a second
Console.ReadLine();
}
//p = 101325(1-2.25577 * 10^-5 * alt) ^5
//this calculates correctly
private static double AirPressure(double al)
{
double tempAlt = 1 - 2.25577 * 0.00001 * al;
Console.WriteLine("Inside eq = " + tempAlt);
tempAlt = Math.Pow(tempAlt, 5 );
Console.WriteLine("Power of 5 = " + tempAlt);
tempAlt = 101325 * tempAlt;
Console.WriteLine("Pressure is = " + tempAlt + " Pascal");
return tempAlt;
}
//temperature calculation
// use adiobatic rate to calculate this
//this is right
private static double CalTemp(double t, double al, double rate) //start temperature and altitude
{
double nTemp = t;
for (int i = 0; i < al; i++)
{
nTemp -= rate;
}
Console.WriteLine("Temperature in for loop = " + nTemp);
return nTemp;
}
//claculate like this
//D Pressure / gas constant * temperature
//this works fine
private static double AirDensity(double pres, double gas, double temp)
{
temp = temp + 273.15; //convert temperautre to Kelvans
double dens = pres / (gas * temp);
dens = dens / 1000;
Console.WriteLine("PResure = " + pres);
Console.WriteLine("Gas cont = " + gas);
Console.WriteLine("Temperture = " + temp);
Console.WriteLine("Air Density is: " + dens);
return dens;
}
private static double TerminalVelocity(double w, double cd, double p, double a)
{
double v = (2 * w) / (cd * p * a) ;
v = Math.Sqrt(v);
Console.WriteLine("Terminal Velocity = " + v);
return v;
}
}
}
Your formula doesn't seem to include gravitational acceleration, and you are also mixing SI and US/imperial units. What unit will your calculated velocity have? It would probably be easier if you stay with SI units only. Another thing that looks a little strange is this line:
const double drag = 0.7; //in meters
The drag coefficient is a dimensionless number. It shouldn't have a physical unit (like meter).
The correct formula is:
v = sqrt((2 * m * g) / (d * A * C))
The variables, with corresponding SI units, are:
m [kg] - Mass of falling body.
g [m/s^2] - Gravitational acceleration.
d [kg/m^3] - Air density.
A [m^2] - Projected area.
C [-] - Drag coefficient.
If you use these units, the formula will yield the velocity in [m/s]. As an example. let's try the following values with units as above: m=80, g=9.8, d=1, A=0.7, C=0.7
This gives the terminal velocity v = 57 m/s which seems reasonable.