//--------------------------------------------------------------------- // //--------------------------------------------------------------------- public static bool get_launch_params(CelestialBody depBody, ref DepManuever manuever) { BodyData depData = new BodyData(); depBody.get_data(ref depData); double mu = depData.gravParameter; double R = depData.radius; double r0 = R + manuever.h; double vk = Math.Sqrt(mu / r0); double i = manuever.orbit.i * math.RAD; double Omega = manuever.orbit.Omega * math.RAD; if (i < Math.Abs(manuever.launchLat)) return false; double sin_A = Math.Cos(i)/Math.Cos(manuever.launchLat); double A = Math.Asin(sin_A); double ny = -Math.Cos(A); double nz = sin_A; double D = ny * ny + nz * nz * Math.Pow(Math.Sin(manuever.launchLat), 2); double sin_d = -(nz * Math.Cos(Omega) * Math.Sin(manuever.launchLat) + ny * Math.Sin(Omega)) * Math.Sin(i) / D; double cos_d = (nz * Math.Sin(Omega) * Math.Sin(manuever.launchLat) - ny * Math.Cos(Omega)) * Math.Sin(i) / D; double d = math.arg(sin_d, cos_d); double rotAngle_ref = d - manuever.launchLon; double omega = 2 * Math.PI / depData.rotationPeriod; double rotAngle = depBody.get_rotation_angle(manuever.startTime)*math.RAD; double dT = 0; if (rotAngle >= rotAngle_ref) { dT = (rotAngle - rotAngle_ref) / omega; } else { dT = 21600 - (rotAngle_ref - rotAngle) / omega; } manuever.launchTime = manuever.startTime - dT; KCalendar.sec_to_date(manuever.launchTime, ref manuever.launchDate); // Debug rotAngle = depBody.get_rotation_angle(manuever.launchTime)*math.RAD; // Relative azimuth calculation double vs = omega*R*Math.Cos(manuever.launchLat); double sin_Ar = (vk * sin_A - vs) / Math.Sqrt(vk * vk + vs * vs - 2 * vk * vs * sin_A); manuever.azimuth = Math.Asin(sin_Ar) / math.RAD; return true; }
//--------------------------------------------------------------------- // Transfer dV calculation //--------------------------------------------------------------------- public static void get_depatrure_manuever(CelestialBody depBody, CelestialBody craft, double t1, ref DepManuever manuever) { OrbitPos depPos = new OrbitPos(); depBody.get_position(t1, ref depPos); // Calculation SOI departure velocity Vector3D Vd = depBody.get_velocity(depPos.theta); Vector3D Vc = craft.get_velocity(0); Vector3D Vro = Vc - Vd; double v_ro = Vro.lenght(); // Depatrure hyperbolic orbit calculation Vector3D x1 = depBody.get_cartesian_pos(depPos.theta); double u = 0; get_transfer_orientation(x1, Vro, ref manuever.orbit.i, ref manuever.orbit.Omega, ref u); if (manuever.orbit.i > 90.0) { manuever.orbit.i = 180.0 - manuever.orbit.i; manuever.orbit.Omega += 180.0; if (manuever.orbit.Omega > 360) manuever.orbit.Omega -= 360; } // Eject dV calculation BodyData depData = new BodyData(); depBody.get_data(ref depData); double ro = depData.sphereOfInfluence; double R = depData.radius; double mu = depData.gravParameter; double h = manuever.h; double v0 = Math.Sqrt(2 * mu * (1 / (R + h) - 1 / ro) + v_ro * v_ro); manuever.dv = v0 - Math.Sqrt(mu / (R + h)); // Time of hyperbolic departure calculation double vk = Math.Sqrt(mu / (R + h)); manuever.orbit.e = (v0 * v0 / vk / vk - 1); double p = (R + h) * (1 + manuever.orbit.e); double cos_theta = (p / ro - 1) / manuever.orbit.e; double theta = Math.Acos(cos_theta); manuever.orbit.a = p / (manuever.orbit.e * manuever.orbit.e - 1); double n = Math.Sqrt(mu / manuever.orbit.a) / manuever.orbit.a; double thH2 = Math.Sqrt((manuever.orbit.e - 1) / (manuever.orbit.e + 1)) * Math.Tan(theta / 2); double H = Math.Log((1 + thH2) / (1 - thH2)); double M = manuever.orbit.e * Math.Sinh(H) - H; double dT = M / n; manuever.orbit.omega = (Math.Acos(1/manuever.orbit.e) - Math.PI/2) / math.RAD; // Low orbit wait time calculation double waitTime = manuever.turns * 2 * Math.PI * (R + h) / vk; manuever.ejectTime = t1 - dT; manuever.startTime = t1 - dT - waitTime; KCalendar.sec_to_date(manuever.ejectTime, ref manuever.ejectDate); KCalendar.sec_to_date(manuever.startTime, ref manuever.startDate); }
//--------------------------------------------------------------------- // //--------------------------------------------------------------------- private void buttonHomanSearch_Click(object sender, EventArgs e) { double t0 = KCalendar.date_to_sec(int.Parse(textBeginYear.Text.ToString()), int.Parse(comboBeginDay.Text.ToString()), int.Parse(comboBeginHour.Text.ToString()), int.Parse(comboBeginMin.Text.ToString()), int.Parse(comboBeginSec.Text.ToString())); double t1 = KCalendar.date_to_sec(int.Parse(textEndYear.Text.ToString()), int.Parse(comboEndDay.Text.ToString()), int.Parse(comboEndHour.Text.ToString()), int.Parse(comboEndMin.Text.ToString()), int.Parse(comboEndSec.Text.ToString())); int dep_idx = get_body_index(comboHomanArrivList.Text.ToString()); int arr_idx = get_body_index(comboHomanDepList.Text.ToString()); // Check same reference body!!! if (Bodies[dep_idx].get_ref_body() != Bodies[arr_idx].get_ref_body()) { labelNoTransfer.Text = "Bodies must have same reference body!\nPlease, change other bodies"; return; } Transfer trans = new Transfer(); double psi = Convert.ToDouble(textPsi.Text) * RAD; bool ready = Lambert.get_transfer_date(t0, t1, Bodies[dep_idx], Bodies[arr_idx], psi, ref trans); if (!ready) { panelHomanRes.Visible = false; labelNoTransfer.Text = "Transfer is imposible in changed period"; return; } labelNoTransfer.Text = ""; panelHomanRes.Visible = true; KDate deltaDate = new KDate(); KCalendar.DeltaDate(trans.arrivTime - trans.depTime, ref deltaDate); labelArivDate.Text = trans.depDate.year.ToString() + "y " + trans.depDate.day.ToString() + "d " + trans.depDate.hour.ToString() + "h " + trans.depDate.min.ToString() + "m " + trans.depDate.sec.ToString() + "s"; labelDepDate.Text = trans.arrivDate.year.ToString() + "y " + trans.arrivDate.day.ToString() + "d " + trans.arrivDate.hour.ToString() + "h " + trans.arrivDate.min.ToString() + "m " + trans.arrivDate.sec.ToString() + "s"; labelTransTime.Text = deltaDate.year.ToString() + "y " + deltaDate.day.ToString() + "d " + deltaDate.hour.ToString() + "h " + deltaDate.min.ToString() + "m " + deltaDate.sec.ToString() + "s"; labelSmiMajorAxis.Text = Math.Round(trans.orbit.a, 0).ToString() + " m"; labelEccentricity.Text = Math.Round(trans.orbit.e, 4).ToString(); labelInclination.Text = Math.Round(trans.orbit.i, 4).ToString() + " deg"; labelLAN.Text = Math.Round(trans.orbit.Omega, 4).ToString() + " deg"; labelArgPe.Text = Math.Round(trans.orbit.omega, 4).ToString() + " deg"; CelestialBody craft = new CelestialBody(); BodyData craft_data = new BodyData(); craft_data.name = "Space craft"; craft_data.orbit = trans.orbit; craft.set_data(ref craft_data); craft.set_refGravParameter(Bodies[dep_idx].get_refGravParameter()); DepManuever manuever = new DepManuever(); manuever.h = double.Parse(textAltitude.Text)*1000.0; manuever.turns = int.Parse(textWaitTurns.Text); Lambert.get_depatrure_manuever(Bodies[dep_idx], craft, trans.depTime, ref manuever); labelDeltaV.Text = Math.Round(manuever.dv, 2).ToString(); labelInc.Text = Math.Round(manuever.orbit.i, 4).ToString(); labelStartLAN.Text = Math.Round(manuever.orbit.Omega, 4).ToString(); labelEjectDate.Text = manuever.ejectDate.year.ToString() + "y " + manuever.ejectDate.day.ToString() + "d " + manuever.ejectDate.hour.ToString() + "h " + manuever.ejectDate.min.ToString() + "m " + manuever.ejectDate.sec.ToString() + "s"; double latDeg = double.Parse(textLatDeg.Text); double latMin = double.Parse(textLatMin.Text); double latSec = double.Parse(textLatSec.Text); double lonDeg = double.Parse(textLonDeg.Text); double lonMin = double.Parse(textLonMin.Text); double lonSec = double.Parse(textLonSec.Text); manuever.launchLat = (latDeg + latMin / 60.0 + latSec / 3600.0) * RAD; manuever.launchLon = (lonDeg + lonMin / 60.0 + lonSec / 3600.0) * RAD; if (radioButtonSouth.Checked) manuever.launchLat = -manuever.launchLat; if (radioButtonWest.Checked) manuever.launchLon = -manuever.launchLon; bool flag = Lambert.get_launch_params(Bodies[dep_idx], ref manuever); if (flag) { labelStartDate.Text = manuever.launchDate.year.ToString() + "y " + manuever.launchDate.day.ToString() + "d " + manuever.launchDate.hour.ToString() + "h " + manuever.launchDate.min.ToString() + "m " + manuever.launchDate.sec.ToString() + "s"; labelAzimuth.Text = Math.Round(manuever.azimuth, 2).ToString(); } // Draw trajectory DrawTransOrbit(panelTransOrbit, trans, Bodies[dep_idx], Bodies[arr_idx], craft); }