Beispiel #1
0
double AscentAP::GetTargetInclination ()
{
	double a=0.0, B=0.0;
	if (vessel->status == 0) {
		if (!launch_lat && !launch_lng) {
			double r;
			vessel->GetEquPos(launch_lng, launch_lat, r);
		}
		a = PI05-launch_lat;

		// correct launch azimuth for surface rotation
		const OBJHANDLE hRef = vessel->GetGravityRef();
		double R = oapiGetSize(hRef);           // planet mean radius
		double r = R + tgt_alt;                 // target orbit radius
		double M = oapiGetMass (hRef);          // reference body mass
		double v0 = sqrt(GGRAV*M/r);            // target orbit speed
		double vg = PI2*R/oapiGetPlanetPeriod(hRef)*cos(launch_lat);
		                                        // surface speed at launch position
		double vx0 = v0*sin(launch_azimuth);    // longitudinal velocity component
		double vx1 = vx0 + vg;                  // corrected for planet rotation
		double vy  = v0*cos(launch_azimuth);    // latitudinal velocity component
		B = atan2(vx1,vy);                      // effective launch azimuth
	}
	return PI05 - asin(sin(a)*sin(B));
}
Beispiel #2
0
void AttitudeReference::PostStep (double simt, double simdt, double mjd)
{
	valid_axes = false;
	valid_euler = false;
	valid_tgteuler = false;

	if (mode >= 4 && tgtmode == 3) {
		NAVHANDLE hNav = v->GetNavSource (navid);
		if (hNav) {
			VECTOR3 tvel,svel;
			v->GetGlobalVel (svel);
			NAVDATA data;
			OBJHANDLE hObj = NULL;
			oapiGetNavData (hNav, &data);
			switch (data.type) {
				case TRANSMITTER_IDS:
					hObj = data.ids.hVessel;
					break;
				case TRANSMITTER_XPDR:
					hObj = data.xpdr.hVessel;
					break;
				case TRANSMITTER_VTOL:
					hObj = data.vtol.hBase;
					break;
				case TRANSMITTER_VOR: {
					hObj = data.vor.hPlanet;
					MATRIX3 Rp;
					oapiGetRotationMatrix (hObj, &Rp);
					oapiGetGlobalVel (hObj, &tvel);
					tvel += mul (Rp, _V(-sin(data.vor.lng),0,cos(data.vor.lng)) * PI2/oapiGetPlanetPeriod(hObj)*oapiGetSize(hObj)*cos(data.vor.lat));
					tgt_rvel = svel-tvel;
					sprintf (oapiDebugString(), "rvel: x=%f, y=%f, z=%f", tgt_rvel.x, tgt_rvel.y, tgt_rvel.z);
					} return; // done
			}
			if (hObj) {
				oapiGetGlobalVel (hObj, &tvel);
				tgt_rvel = svel-tvel;
			} else {
				// TODO
			}
		}
	}
}
Beispiel #3
0
// ==============================================================================================================================================
//
void Orbit::GEO(OBJHANDLE ref)
{	
	if (!ref) {	GeoRef=NULL; return; }

	double obli  = oapiGetPlanetObliquity(ref);
	double peri  = oapiGetPlanetPeriod(ref);
	double trans = oapiGetPlanetTheta(ref);

	VECTOR3 rota, refd;
	PlanetAxis(obli,trans,&rota,&refd);

	VECTOR3 velo = crossp(rota,refd);
	double  myy  = oapiGetMass(ref)*GC;
	double  rad  = pow(fabs(peri)*sqrt(myy)/PI2, 2.0 / 3.0);
	double  vel  = sqrt(myy/rad);

	refd=set_length(refd,rad);
	velo=set_length(velo,vel);
	if (peri<0) velo=_V(0,0,0)-velo;

	Elements(refd,velo,myy);
	GeoRef=ref;
}
Beispiel #4
0
// ==============================================================================================================================================
//
void SyncMFD::Update(HDC hDC)
{

	int pos;
	int ld=MFD->LineHeight;
	int fbp=MFD->FirstButton;
	char *Mnu = {"BaseSync v3.2\0"};

	int width=MFD->width;
	int height=MFD->height;

	double w=(double) width;
	double h=(double) height;

	int i;
	VECTOR3 Rot,Off,opos;
	double obli,trans,per,offset,diff,p,op,t,time,lon,lat;
	double trl,heading;
	char   name[32];
	static const int MAXSOLN = 160;
	double times[MAXSOLN],diffs[MAXSOLN],heads[MAXSOLN];
	int sol_found = 0;
	double max_diff=1000;
	bool   draw_text=false;

	Orbit LEO,ShipOrbit,Ecliptic;

	SetTextColor(hDC,white);
	SetTextAlign(hDC,TA_LEFT);
	TextOut(hDC,5,1,Mnu, (int)strlen(Mnu));

	if (mode.enc==0) Text(hDC,5,1+ld,"Latitude");
	if (mode.enc==1) Text(hDC,5,1+ld,"Closest passage");
	if (mode.enc==2) Text(hDC,5,1+ld,"Apoapsis");
	if (mode.enc==3) Text(hDC,5,1+ld,"Periapsis");

	if (sync_num<1) sync_num=1;
	if (sync_num>99) sync_num=99;


	OBJHANDLE ref = oapiGetObjectByName(trgt->ref);
	if (ref==NULL) {
    usingGS2 = false;
    trgt = &bstrgt;
    ref=ship->GetSurfaceRef();
  }

	if (ref==NULL) return;



	ShipOrbit.Elements(ship->GetHandle(), ref);
	Ecliptic.Ecliptic();

	oapiGetObjectName(ref, trgt->ref, 31);


  // Rotation elements

	obli   = oapiGetPlanetObliquity(ref);
	trans  = oapiGetPlanetTheta(ref);
	per    = oapiGetPlanetPeriod(ref);
	offset = oapiGetPlanetCurrentRotation(ref);

	// LEO
	LEO.LEO(ref);

  if (!usingGS2) {
    OBJHANDLE tgt = oapiGetBaseByName(ref, trgt->name);
    if (tgt) {
		  oapiGetObjectName(tgt,trgt->name,32);
		  oapiGetBaseEquPos(tgt,&trgt->lon, &trgt->lat);
	  }
	  else strcpy(trgt->name,"Surface");
  }


	double trle=ShipOrbit.TrlOfNode(&LEO);
	double EqI=angle(ShipOrbit.norv, LEO.norv);
	double ang=asin(sin(trgt->lat) / sin(EqI));

	double apos=limit(trle+ang);
	double bpos=limit(trle+PI-ang);

	double atime=ShipOrbit.TimeTo(apos);
	double btime=ShipOrbit.TimeTo(bpos);

	double dist=ShipOrbit.PeriapsisDistance();
	double apodist = dist=ShipOrbit.AopapsisDistance();
	if (dist<oapiGetSize(ref)) dist=oapiGetSize(ref);

	double zoom=w/(2.55 * (apodist + apodist + dist) / 3.0);
	double r=oapiGetSize(ref)*zoom;

	double x=w/2,y=h/2;
	double intpos=0;

	if (display_texts&2) {
		SelectObject(hDC,solid_pen_dgrey);
		DrawEllipse(hDC,x-r,y-r,x+r,y+r,w,h);

		if (mode.enc==0) {  // Latitude
			if ((sync_sel&1)==0) SelectObject(hDC,solid_pen_y), intpos=apos;
			else SelectObject(hDC,solid_pen_dgrey);
			r=ShipOrbit.Radius(apos)*zoom;
			DrawLine(hDC,x,y,x+r*cos(apos),x-r*sin(apos),w,h,false);

			if ((sync_sel&1)==1) SelectObject(hDC,solid_pen_y), intpos=bpos;
			else SelectObject(hDC,solid_pen_dgrey);
			r=ShipOrbit.Radius(bpos)*zoom;
			DrawLine(hDC,x,y,x+r*cos(bpos),x-r*sin(bpos),w,h,false);
		}

		if (mode.enc==1) { // Closest Passage
			r=ShipOrbit.Radius(sync_trl)*zoom;
			intpos=sync_trl;

			SelectObject(hDC,solid_pen_y);
			DrawLine(hDC,x,y,x+r*cos(sync_trl),x-r*sin(sync_trl),w,h,false);
		}

		if (mode.enc==2 || mode.enc==3) { // Aopapsis Periapsis
			SelectObject(hDC,solid_pen_y);
			r=ShipOrbit.Radius(sync_trl)*zoom;
			DrawLine(hDC,x,y,x+r*cos(sync_trl),x-r*sin(sync_trl),w,h,false);

			SelectObject(hDC,solid_pen_grey);
			r=ShipOrbit.Radius(sync_line)*zoom;
			DrawLine(hDC,x,y,x+r*cos(sync_line),x-r*sin(sync_line),w,h,false);
		}

		ShipOrbit.SetProjection(&ShipOrbit);
		ShipOrbit.GDIDraw(hDC,green,w,h,zoom,true,true);

		if (mode.deo) {
			r=ShipOrbit.Radius(deo.trlBurn)*zoom;
			SelectObject(hDC,solid_pen_white);
			DrawLine(hDC,x,y,x+r*cos(deo.trlBurn),x-r*sin(deo.trlBurn),w,h,false);
		}
	}



	if (EqI>=trgt->lat || mode.enc!=0) {
		// Usual case... target in range

		draw_text=true;
		SetTextColor(hDC,green);
		pos=(fbp+(ld*8));

		if (display_texts&1 && !mode.deo) {
			if (mode.enc==0) {
				Text(hDC,5,pos," #: Time:");
			Text(hDC,width/2,pos,"Lon Diff:"), pos+=ld;
			}	else {
				Text(hDC,5,pos," #: Time:");
			Text(hDC,5+width/3,pos,"  Dist:");
			Text(hDC,5+width*2/3,pos,"  Heading:"), pos+=ld;
			}
		}

		if (atime<btime && atime>0) sync_sel=0;
		else if (btime>0) sync_sel=1;
		else sync_sel=0;

		for (i=0;i<MAXSOLN;i++) {
			times[i]=0;
			diffs[i]=0;
		}
		sync_min = -1;


		if (ShipOrbit.ecc<1 && mode.enc==0) {
			for (i=0;i<MAXSOLN;i++) {

				if (i&1) time=MAX(atime, btime);
				else     time=MIN(atime, btime);

				if (time==atime) op=apos;
				else             op=bpos;

				p=(double)i;
				if (i>1) time+=ShipOrbit.Period()*floor(p/2);

				t = time/86400;
				PlanetAxis(obli,trans,offset,per,t,&Rot,&Off);

				opos=ShipOrbit.Position(op);

				LonLat(opos,Rot,Off,&lon,&lat);
				diff=lon-trgt->lon;

				if (fabs(diff)<max_diff) {
					max_diff=fabs(diff), sync_time=time, sync_trl=op;
					sync_min=i;
				}

				times[i]=time;
				diffs[i]=diff;
				if (time > 0.0 && diff >0.0) {
					sol_found++;
					if (sol_found==sync_num) break;
				}
			}
		}


		max_diff=1e10;

		if (ShipOrbit.ecc<1 && mode.enc==1) {

			double posit=ShipOrbit.trl;

			for (i=0;i<MAXSOLN;i++) {

				InterpolateClosestPassage(ref,&ShipOrbit,trgt->lon,trgt->lat,posit,&diff,&time,&heading,&trl);

				posit=trl+PI05;

				if (diff<max_diff && diff>0) {
					max_diff=diff, sync_time=time, sync_trl=limit(trl);
					sync_min=i;
				}

				heads[i]=heading;
				times[i]=time;
				diffs[i]=diff;
				if (time > 0.0 && diff >0.0) {
					sol_found++;
					if (sol_found==sync_num) break;
				}
			}
		}

		if (ShipOrbit.ecc<1 && (mode.enc==2 || mode.enc==3)) {
			for (i=0;i<MAXSOLN;i++) {

				if (mode.enc==2) sync_line=limit(ShipOrbit.lpe+PI);
				else sync_line=limit(ShipOrbit.lpe);

				time=ShipOrbit.TimeTo(sync_line) + ShipOrbit.Period() * (double)i;
				t = time / 86400.0;

				PlanetAxis(obli,trans,offset,per,t,&Rot,&Off);

				VECTOR3 gpv=VectorByLonLat(Rot,Off,trgt->lon,trgt->lat);
							VECTOR3 pos=ShipOrbit.Position(sync_line);

				diff = angle(gpv,pos);
				heading = nangle(pos-gpv,Rot,gpv);

				ShipOrbit.Longitude(gpv,NULL,NULL,&trl);

				if (diff<max_diff && diff>0) {
					max_diff=diff, sync_time=time, sync_trl=limit(trl);
					sync_min=i;
				}

				if (time==0) time=0.1;
				heads[i]=heading;
				times[i]=time;
				diffs[i]=diff;
				if (time > 0.0 && diff >0.0) {
					sol_found++;
					if (sol_found==sync_num) break;
				}
			}
		}

		// Hyperbolic Orbit
		if (ShipOrbit.ecc>=1 && (atime>0 || btime>0)) {
			mode.enc=0;
			for (i=0;i<2;i++) {

				if (atime>0 && btime>0) {
					if (i&1) time=MAX(atime, btime);
					else     time=MIN(atime, btime);
				}
				else time=(atime>0 ? atime : btime);

				op = (time==atime? apos : bpos);

				p=(double)i;
				if (i>1) time+=ShipOrbit.Period()*floor(p/2);
				t = time/86400;
				PlanetAxis(obli,trans,offset,per,t,&Rot,&Off);

				opos=ShipOrbit.Position(op);
				LonLat(opos,Rot,Off,&lon,&lat);
				diff=lon-trgt->lon;

				if (fabs(diff)<max_diff) {
					max_diff=fabs(diff), sync_time=time, sync_trl=op;
					sync_min=i;
				}

				times[i]=time;
				diffs[i]=diff;

				if (atime<0 || btime<0) break;
			}
		}

		if (sync_min > -1) {
			sol.num = sync_min+1;
			sol.tSol = times[sync_min];
			sol.dist = diffs[sync_min];
			sol.hdg = heads[sync_min];
			sol.dataValid = true;
		} else {
			sol.dataValid = false;
		}

		double rad=oapiGetSize(ref);
		int no=0;
		int disp_i = 1;

		if (display_texts&1 && !mode.deo) {
			for (i=0;i<MAXSOLN;i++) {
				if (i==sync_min) SetTextColor(hDC,lyellow);
				else SetTextColor(hDC,lgreen);
				if (times[i]>0.0 && diffs[i]>=0.0) {
					if (disp_i >= sync_dispmin && disp_i <= sync_dispmin+7) {
						if (mode.enc==0) {
							sprintf(name,"%2d: ",disp_i);
							Text(hDC,5,pos,name,times[i]);
							TextA(hDC,width/2,pos,"",diffs[i]*DEG), pos+=ld;
						}	else { // enc_mode 1,2,3
							no++;
							sprintf(name,"%2d: ",disp_i);
							Text(hDC,5,pos,name,times[i]);
							Text(hDC,5+width/3,pos,"  ",diffs[i]*rad);
							TextA(hDC,5+width*2/3,pos,"  ",heads[i]*DEG), pos+=ld;
						}
					}
					disp_i++;
					if (disp_i > sync_num) break;
				}
			}
		}
		sync_sel+=sync_min;
	}	else {
		// We are in Latitude mode, and the target is outside of our inclination - i.e. no solution

		sol.dataValid = false;
		SetTextAlign(hDC,TA_CENTER);
		SetTextColor(hDC,yellow);
		pos=(fbp+(ld*8));
		Text(hDC,width/2,pos,"Target Out of Range"); pos+=ld;
	}



	if (mode.dir) {
		// Calculate burn for plane change correction in DIRECT mode

		if (EqI<trgt->lat && mode.enc==0) {
			double trl;
			PlanetAxis(obli,trans,offset,per,0,&Rot,&Off);
			VECTOR3 gpv = VectorByLonLat(Rot,Off,trgt->lon,trgt->lat);
			ShipOrbit.Longitude(gpv,NULL,NULL,&trl);
			sync_time=ShipOrbit.TimeTo(trl);
			sync_trl=trl;
		}

		time_to_int=sync_time;
		double trl=sync_trl;

		PlanetAxis(obli,trans,offset,per,time_to_int/86400.0,&Rot,&Off);
		VECTOR3 pos = ShipOrbit.Position(trl);
		VECTOR3 gpv = VectorByLonLat(Rot,Off,trgt->lon,trgt->lat);
		VECTOR3 lan = crossp(gpv, pos);
		VECTOR3 nor = ShipOrbit.norv;

		ShipOrbit.Longitude(lan,NULL,NULL,&sol.trlBurn);

		sol.rIn = fabs(asin(dotp(gpv,nor)));

		double a = ShipOrbit.TimeToPoint(sol.trlBurn);
		double b = ShipOrbit.TimeToPoint(limit(sol.trlBurn+PI));

		if (fabs(a)<fabs(b)) sol.tToBurn =a, sol.nmlBurn=true;
		else				 sol.tToBurn =b, sol.nmlBurn=false;

		sol.dV = sol.rIn*ShipOrbit.ang/ShipOrbit.Radius(sol.trlBurn);
		sol.tBurn =BurnTimeBydV(sol.dV,ship);

	}	else {
		// Calculate burn for plane change correction in EQUATORIAL mode

		sol.trlBurn=ShipOrbit.TrlOfNode(&LEO);
		sol.rIn=MAX(trgt->lat-EqI,0);

		double a=ShipOrbit.TimeToPoint(sol.trlBurn);
		double b=ShipOrbit.TimeToPoint(limit(sol.trlBurn+PI));

		if (fabs(a)<fabs(b)) sol.tToBurn =a, sol.nmlBurn=true;
		else				 sol.tToBurn =b, sol.nmlBurn=false;

		sol.dV = sol.rIn*ShipOrbit.ang/ShipOrbit.Radius(sol.trlBurn);
		sol.tBurn =BurnTimeBydV(sol.dV,ship);
	}

	if (display_texts&2) {
		ShipOrbit.DrawPlaneIntersection(hDC,sol.trlBurn,w/2,h/2,zoom,grey);
	}

	SetTextAlign(hDC,TA_LEFT);
	pos=1;
	SetTextColor(hDC,grey);
  if (usingGS2) {
	  Text(hDC,width*1/2,pos,"Linked ","to GS"); pos+=ld;

    // Check if GS2 changed target
    if (bstrgt.lat != gs2trgt->lat || bstrgt.lon != gs2trgt->lon) {
        strcpy(bstrgt.ref, gs2trgt->ref);
        strcpy(bstrgt.name, gs2trgt->name);
        bstrgt.lat = gs2trgt->lat;
        bstrgt.lon = gs2trgt->lon;
        bstrgt.alt = gs2trgt->alt;
        bstrgt.ang = gs2trgt->ang;
        bstrgt.ant = gs2trgt->ant;
    }

  } else {
	  Text(hDC,width*1/2,pos,"Ref ",trgt->ref); pos+=ld;
  }
  Text(hDC,width*1/2,pos,"Tgt ",trgt->name); pos+=ld;

	if (display_texts&1) {
		if (!mode.deo) {
			// Display the burn solution for plane change

			deo.dataValid = false;
			pos=fbp;
			SetTextColor(hDC,lgreen);

			if (trgt->lat<0) TextA(hDC,5,pos,"Lat ",fabs(DEG*trgt->lat),"S"), pos+=ld;
			else TextA(hDC,5,pos,"Lat ",DEG*trgt->lat,"N"), pos+=ld;

			if (trgt->lon<0) TextA(hDC,5,pos,"Lon ",fabs(DEG*trgt->lon),"W"), pos+=ld;
			else TextA(hDC,5,pos,"Lon ",DEG*trgt->lon,"E"), pos+=ld;

			TextA(hDC,5,pos,"EqI ",EqI*DEG), pos+=ld;


			PlanetAxis(ref,0,&Rot,&Off);
			VECTOR3 base_pos = VectorByLonLat(Rot,Off,trgt->lon,trgt->lat);

			VECTOR3 ship_pos; ship->GetRelativePos(ref,ship_pos);
			VECTOR3 ship_vel; ship->GetRelativeVel(ref,ship_vel);

			VECTOR3 gsp=GroundSpeedVector(ref,ship);
			VECTOR3 zero=crossp(ship_pos,ship_vel);
			double head = nangle(gsp,zero,ship_pos);

      double baseHeight = oapiGetSize(ref);
#if ORBITER_VERSION == 2016
      ELEVHANDLE eh = oapiElevationManager(ref);
      if (eh) {
        baseHeight += oapiSurfaceElevation(ref, trgt->lon, trgt->lat);
      }
#endif


			TextA(hDC,5,pos,"Hed ",head*DEG), pos+=ld;
			Text(hDC,5,pos, "GSp ",length(gsp)), pos+=ld;
			Text(hDC,5,pos, "Dst ",angle(ship_pos,base_pos)*baseHeight), pos+=ld;
			if (sol.dataValid) {
        double altitude = length(ShipOrbit.Position(intpos));
        altitude -= baseHeight;
				Text(hDC,5,pos, "Alt ",altitude);
      }
			pos+=ld;


			pos=fbp;
			int xx=width/2;
			SetTextColor(hDC,green);
			if (mode.dir) Text(hDC,xx,pos,"Direct:"), pos+=ld;
			else Text(hDC,xx,pos,"Equator:"), pos+=ld;

			SetTextColor(hDC,lgreen);
			TextA(hDC,xx,pos,"RIn ",sol.rIn*DEG), pos+=ld;
			TextA(hDC,xx,pos,"LAN ",sol.trlBurn*DEG), pos+=ld;
			Text(hDC,xx,pos," Tn ",sol.tToBurn), pos+=ld;
      if (abs(sol.tBurn) > 0.1) {
  			if (sol.nmlBurn) Text(hDC,xx,pos,"PlC ",sol.tBurn,"s (+)"), pos+=ld;
	  		else Text(hDC,xx,pos,"PlC ",sol.tBurn,"s (-)"), pos+=ld;
		  	Text(hDC,xx,pos," dV ",sol.dV,"m/s"), pos+=ld;
      } else {
        Text(hDC,xx,pos,"PlC 0.000s"), pos+=ld;
		  	Text(hDC,xx,pos," dV 0.000m/s"), pos+=ld;
      }

      if (sol.dataValid) {
        burn.dV = sol.dV;
        burn.orientation = sol.nmlBurn ? 1 : -1;
        burn.tToInstBurn = sol.tToBurn;
        burn.dataValid = true;
      } else {
        burn.dataValid = false;
      }

		}	else {
			// Display the deorbit parameters and burn solution

			pos=fbp;
			SetTextColor(hDC,white);
			Text(hDC,5,pos,"De-Orbit Program"), pos+=2*ld;

			SetTextColor(hDC,lgreen);
      if (usingGS2) {
			  Text(hDC,5,pos, "Ang, Ant, Alt from GS"), pos+=ld;
        TextA(hDC,5,pos,"GS Ang ",trgt->ang*DEG), pos+=ld;
			  TextA(hDC,5,pos,"GS Ant ",trgt->ant*DEG), pos+=ld;
			  Text(hDC,5,pos, "GS Alt ",trgt->alt,"km"), pos+=2*ld;
      } else {
        TextA(hDC,5,pos,"Ang ",bstrgt.ang*DEG), pos+=ld;
			  TextA(hDC,5,pos,"Ant ",bstrgt.ant*DEG), pos+=ld;
			  Text(hDC,5,pos, "Alt ",bstrgt.alt,"km"), pos+=2*ld;
      }
			double pre;
			ComputeDeOrbit(ShipOrbit.myy,ShipOrbit.rad,trgt->alt*1000+oapiGetSize(ref),trgt->ang,&pre,&deo.dV);
			deo.dV=ShipOrbit.vel-deo.dV;

			deo.trlBurn = limit(sync_trl - trgt->ant - pre);
			deo.tInstBurn = ShipOrbit.TimeToPoint(deo.trlBurn);
			deo.tBurn = BurnTimeBydV(deo.dV,ship);
			deo.tToBurn = deo.tInstBurn - 0.5 * deo.tBurn;

			Text(hDC,5,pos, "TBn ",deo.tToBurn,"s"), pos+=ld;
			TextA(hDC,5,pos,"TrL ",deo.trlBurn*DEG), pos+=ld;
			Text(hDC,5,pos, " dV ",deo.dV,"m/s"), pos+=ld;
			Text(hDC,5,pos, " BT ",deo.tBurn,"s"), pos+=2*ld;

			if (ShipOrbit.ecc>0.015) {
				SetTextColor(hDC,lgreen);
				Text(hDC,5,pos,"De-orbit burn data only accurate"); pos+=ld;
				Text(hDC,5,pos,"if your Ecc is 0.015 or less."); pos+=ld;
				Text(hDC,5,pos,"(If burn complete, please ignore.)"); pos+=ld;pos+=ld;
			}
			if (!mode.dir) {
				SetTextColor(hDC,lgreen);
				Text(hDC,5,pos,"Use \"Direct\" mode to re-synchronize"); pos+=ld;
				Text(hDC,5,pos,"the approach after the de-orbit");
			}
			deo.dataValid = true;
      burn.dV = -deo.dV;
      burn.orientation = 0;
      burn.tToInstBurn = deo.tToBurn;
      burn.dataValid = true;
		}
	}

	if (!MMPut_done) {
    mma.PutMMStruct("BaseSyncTarget", &bstrgt);
    mma.PutMMStruct("BaseSyncMode", &mode);
    mma.PutMMStruct("BaseSyncSolution", &sol);
    mma.PutMMStruct("BaseSyncDeorbit", &deo);
    mma.PutMMStruct("BaseSyncBurn", &burn); // To be removed after BTC synchronization
		if (burn.dataValid)
        {
            mma.Put("dv", burn.dV);
            mma.Put("InstantaneousBurnTime", burn.tToInstBurn);
            mma.Put("Orientation", burn.orientation);
        }
        else
        {
          mma.Delete("dv");
          mma.Delete("InstantaneousBurnTime");
          mma.Delete("Orientation");
        }
		MMPut_done = true;
	}
}
Beispiel #5
0
// ==============================================================================================================================================
//
bool SyncMFD::InterpolateClosestPassage(OBJHANDLE ref, Orbit *src, double lon,double lat,double orbit,double *diff,double *tim,double *head,double *tr)
{
	VECTOR3 Rot,Off;
	Orbit LEO;
	int i;
	double obli = 0.0;
	double trans = 0.0;
	double per = 0.0;
	double offset = 0.0;
	double size = 0.0;
	double time = 0.0;

	// Rotation elements
	obli   = oapiGetPlanetObliquity(ref);
	trans  = oapiGetPlanetTheta(ref);
	per    = oapiGetPlanetPeriod(ref);
	offset = oapiGetPlanetCurrentRotation(ref);
	size   = oapiGetSize(ref);

	LEO.LEO(ref);

	double step  = PI2/16.01;
	double start = orbit;
	double end   = orbit+PI2+(step/2.0);
	double trl, dst2;
	double dot,old_dot=0;


	VECTOR3 pos = _V(0,0,0);
	VECTOR3 vel = _V(0,0,0);
	VECTOR3 gpv = _V(0,0,0);
	VECTOR3 spd = _V(0,0,0);
	VECTOR3 relv = _V(0,0,0);
	VECTOR3 relp = _V(0,0,0);

	bool no_intercept=true;
	bool first=true;

	for (trl=start;trl<end;trl+=step) {

		// Caluclate time to a location
		time=Trl2Time(trl,src)/86400.0;

		// Caluclate Planets Rotation offset at that time
		PlanetAxis(obli,trans,offset,per,time,&Rot,&Off);

		// Calculate Ship's position vector and distance^2
		pos  = src->Position(trl);
		dst2 = dotp(pos,pos);

		// Reset the distance to correspond a surface position.
		pos  = set_length(pos,size);

		// Compute ship's surface velocity vector direction
		vel = crossp(src->norv,pos);

		// Compute ship's surface velocity vector magnitude
		vel = set_length(vel,src->ang*size/dst2);

		// Compute base's position vector
		gpv = VectorByLonLat(Rot,Off,lon,lat)*size;

		// Compute speed of the base
		spd = GroundSpeedVector(ref,time,lon,lat);

		// Copmute relative position to the base
		relv = (vel-spd);
		relp = (pos-gpv);

		dot = dotp(relv,relp);

		if (old_dot<0 && dot>0 && !first) {
			if (angle(pos,gpv)<PI05) {
				start=trl-step;
				no_intercept=false;
				break;
			}
		}

		first=false;
		old_dot=dot;
	}


    // Return N/A if no passage points found
	if (no_intercept) {
		if (head) *head = 0;
		if (diff) *diff = 0;
		if (tim)  *tim  = 0;
		if (tr)   *tr   = start+PI2-PI05;
		return false;
	}


	trl=start;
	old_dot=-1; // We are approaching the base
	double trll=0;
	no_intercept=true;

	for (i=0;i<24;i++) {

		step/=2.0;

		// Caluclate time to a location
		time=Trl2Time(trl,src)/86400.0;

		// Caluclate Planets Rotation offset at that time
		PlanetAxis(obli,trans,offset,per,time,&Rot,&Off);

		// Calculate Ship's position vector and distance^2
		pos  = src->Position(trl);
		dst2 = dotp(pos,pos);

		// Reset the distance to correspond a surface position.
		pos  = set_length(pos,size);

		// Compute ship's surface velocity vector direction
		vel = crossp(src->norv,pos);

		// Compute ship's surface velocity vector magnitude
		vel = set_length(vel,src->ang*size/dst2);

		// Compute base's position vector
		gpv = VectorByLonLat(Rot,Off,lon,lat)*size;

		// Compute speed of the base
		spd = GroundSpeedVector(ref,time,lon,lat);

		// Copmute relative position to the base
		relv = (vel-spd);
		relp = (pos-gpv);

		dot = dotp(relv,relp);

		trll=trl;
		if (dot==0) {
			 no_intercept=false;
			 break; // closest position archived, break
		}

		if (dot>0) { // base is behind of us, step back
			trl=trl-step;
			no_intercept=false;  // Verify, We have a base passage.
		}
		else trl=trl+step;	// base is front of us, cuntinue stepping
	}


	double dif=angle(pos, gpv);

	VECTOR3 zero=crossp(pos,spd);

	if (head) *head = nangle(relp,zero,pos);
	if (diff) *diff = dif;
	if (tim)  *tim  = time*86400.0;
	if (tr)   *tr   = trll;

	return true;
}