コード例 #1
0
ファイル: BSOrbit.cpp プロジェクト: ADSWNJ/BaseSyncMFD
// ==============================================================================================================================================
//
void Orbit::Elements(char *bo,char *re) 
{
	VECTOR3 r,v;

	OBJHANDLE body=oapiGetObjectByName(bo);
	OBJHANDLE ref=oapiGetObjectByName(re);

	if (body==NULL || ref==NULL) return;

	double myy = oapiGetMass(ref) * GC;

	oapiGetRelativePos(body,ref,&r);
	oapiGetRelativeVel(body,ref,&v);

	Elements(r,v,myy);
}
コード例 #2
0
void Dragonfly::LoadState (FILEHANDLE scn, void *vs)
{
    char *line;
	while (oapiReadScenario_nextline (scn, line)) {
        if (!strnicmp (line, "UPPERANT", 8)) {
			sscanf (line+8, "%f %f %i %i %i", &UP_pos ,&UY_pos,&UP_handle, &UY_handle,&UAnt_handle);
		} else if (!strnicmp (line, "LOWERANT", 8)) {
			sscanf (line+8, "%f %f %i %i %i", &LP_pos, &LY_pos,&LP_handle,&LY_handle,&LAnt_handle);
			//SetGearParameters (gear_proc);
		} else if (!strnicmp (line, "HATCH", 5)) {
			sscanf (line+5, "%f %i", &dock_latched, &latch_handle);
		} else if (!strnicmp (line, "ANTTRG", 6)) {
			Dock_target_object=oapiGetObjectByName(line+7);
			//sscanf (line+5, "%f %i", &dock_latched, &latch_handle);
        } else {
            ParseScenarioLineEx (line, vs);
			// unrecognised option - pass to Orbiter's generic parser
        }
    }

	    SetAnimState (anim_UY_ant, UY_pos);
		float ang=(150-UY_pos*300.0)/180.0*acos(-1);
	    Upper_ant_pitch.trans.P.rotparam.axis=_V(cos(ang),0,-sin(ang));	 
        SetAnimState (anim_UP_ant, UP_pos);		
	    
		SetAnimState (anim_LY_ant, LY_pos);
		ang=(150-LY_pos*300.0)/180.0*acos(-1);
	    Lower_ant_pitch.trans.P.rotparam.axis=_V(cos(ang),0,-sin(ang));	 
        SetAnimState (anim_LP_ant, LP_pos);		

	    SetAnimState (anim_latch, dock_latched);
};
コード例 #3
0
ファイル: Sync.cpp プロジェクト: ADSWNJ/BaseSyncMFD
// ==============================================================================================================================================
//
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;
	}
}