def inter_bokeh(): epoch2000=datetime.datetime.strptime("01-01-2000 00:00","%d-%m-%Y %H:%M") epoch2000=time.mktime(epoch2000.timetuple()) lat=request.args.get('lat') long=request.args.get('lon') spkid=request.args.get('spkid') inicio=request.args.get('start') neo=spkid+".bsp" N=200 spi.kclear() spi.furnsh("/home/cristobal/horizons_iterface/github/neo-challege-2016/spice/meta.fgl") spi.furnsh("/home/cristobal/horizons_iterface/github/neo-challege-2016/spice/kernels/neos/"+neo) inicio=inicio.replace("Z","").replace("T"," ") final= dateutil.parser.parse(inicio)+datetime.timedelta(days=0.5) final=str(final.year)+"-"+str(final.month).zfill(2)+"-"+str(final.day).zfill(2)+" "+str(final.hour).zfill(2)+":"+str(final.minute).zfill(2)+":"+str(final.second).zfill(2)+"."+str(final.microsecond) tiempos=spi.str2et([inicio,final]) tiempos=np.linspace(tiempos[0],tiempos[1],N) ar=list() dec=list() times_list=list() for k in tiempos: temp=spi.spkez(int(neo.split(".")[0]),k,"J2000","LT+S",399) temp2=spi.recrad(temp[0][0:3]) ar.append(temp2[1]*(180/np.pi)) dec.append(temp2[2]*(180/np.pi)) times_list.append(datetime.datetime.utcfromtimestamp(k+epoch2000)) [altura,times_list]=conversion(ar,dec,times_list,lat,long) json.dumps(altura) bokeh_pinta(altura,list,neo) return app.send_static_file('spice.html')
def calc_spice(initi,final,neo,puntos,db): N=puntos#2880 #Precision spi.kclear() #Limpiamos el pool de los kernels. #MetaKernel con los datos genericos menos el neo. spi.furnsh("./meta.fgl") spi.furnsh("./kernels/neos/"+neo) #tiempos=spi.str2et(["Jun 20 2004","Dec 1, 2005"]) ini=initi#"Apr 24 2016 0:00:00" fin=final#"Jun 20 2016 0:00:00" #Fran: It would be better to directly put the number of seconds of J2000 instead of this shit... epoch2000=datetime.datetime.strptime("01-01-2000 00:00","%d-%m-%Y %H:%M") epoch2000=time.mktime(epoch2000.timetuple()) tiempos=spi.str2et([ini,fin]) tiempos=np.linspace(tiempos[0],tiempos[1],N) ar=list() dec=list() #pdb.set_trace() for k in tiempos: temp=spi.spkez(int(neo.split(".")[0]),k,"J2000","LT+S",399) temp2=spi.recrad(temp[0][0:3]) ar.append(temp2[1]*(180/np.pi)) dec.append(temp2[2]*(180/np.pi)) for k in range(len(tiempos)): document={"spkid":neo.split(".")[0],"name":neo.split(".")[0],"ra":ar[k],"dec":dec[k],"date":datetime.datetime.fromtimestamp(int(tiempos[k])+epoch2000)} day=str(document["date"].day).zfill(2)+str(document["date"].month).zfill(2)+str(document["date"].year) day="d"+day exec("db.%s.insert_one(document)"%day)
def TrueToEccAnom(self,ta): """Convert True Anomaly to Eccentric Anomaly https://en.wikipedia.org/wiki/Eccentric_anomaly#From_the_true_anomaly """ return sp.recrad(sp.vpack(self.eccChf + math.cos(ta) ,self.bOverA * math.sin(ta) ,0. ) )[iRA]
def interpolateOrbit(self, time, frame='ITRF93'): if frame not in ('ITRF93', 'J2000', 'ECI_TOD', 'ECLIPJ2000'): raise Exception( 'Currently only ITRF93/J2000 frames are supported.') et = SpiceyPy.str2et(str(time)) res, lt = SpiceyPy.spkezr('-123710', et, frame, 'None', 'EARTH') sv = StateVector() sv.setTime(time) sv.setPosition([x * 1000.0 for x in res[0:3]]) sv.setVelocity([x * 1000.0 for x in res[3:6]]) return sv
def invE(self,offsetArcLength=None,arcLengthArg=None,rtnIter=False): """Find eccentric anomaly corresponding to the input arc length""" ### Parse arguments assert not (offsetArcLength is not None and arcLengthArg is not None) if arcLengthArg is None: arcLengthTarget = self.arcChf + offsetArcLength else : arcLengthTarget = float(arcLengthArg) ### Initial estimate of Eccentric Anomaly ### - highest positive or negative multiple of halfpi that gives ### an arc length less than or equal to targetLength nQuad = int(arcLengthTarget / self.quadArc) arcLengthGuess = nQuad * self.quadArc if arcLengthGuess > arcLengthTarget: nQuad -= 1 arcLengthGuess -= self.quadArc eaGuess0 = eaGuess = nQuad * halfpi eaGuess0PlusTwoPi = eaGuess0 + twopi deltaArc = arcLengthTarget - arcLengthGuess tol = self.aChf * 1e-9 itter = 0 while abs(deltaArc) > tol: itter += 1 ### Vector from primary focus to Ecc. Anom. guess cosea = math.cos(eaGuess) sinea = math.sin(eaGuess) x = self.aChf * cosea y = self.bChf * sinea ### Delta-[x,y] of tangent at (x,y) for distance of deltaArc delx = -self.aChf * sinea dely = self.bChf * cosea fac = deltaArc / sp.vnorm(sp.vpack(delx,dely,0.)) delx *= fac dely *= fac ### Delta-vector tangent at (x,y) for distance of deltaArc ### - [X,Y,Z] = [x+delx, y+dely, 0] ### - scale X by 1/a and Y by 1/b to get Eccentric Anomaly eaGuess = sp.recrad(sp.vpack((x+delx)/self.aChf ,(y+dely)/self.bChf ,0. ) )[iRA] while eaGuess0 > eaGuess: eaGuess += twopi while (eaGuess0PlusTwoPi) <= eaGuess: eaGuess -= twopi arcLengthGuess = self.E(eaGuess) deltaArc = arcLengthTarget - arcLengthGuess return rtnIter and (eaGuess,itter,) or eaGuess
def RVtoRSW(R,V): """Convert R and V (Postion and Velocity) into RWS matrix""" #################################################################### ### Equations (1) ### Convert chief position and velocity to RSW1 unit vectors rHatEci = sp.vhat(R) wHatEci = sp.ucrss(R,V) ### W cross R, not R cross W which is in paper sHatEci = sp.ucrss(wHatEci,R) #################################################################### ### Equations (2) ### Combine RSW1 unit vector into [Rhat|Shat|What] matrix return numpy.vstack((rHatEci,sHatEci,wHatEci,))
def station(dat): if dat==0: #Robledo longi=4+(14/60)+(53/3600) #W (-1) lati=40+(25/60)+(54/3600) #N longi= -longi*(np.pi/180) lati=lati*(np.pi/180) alti=720/1000 #Va con Km # Datos de WGS84: #===================================== RE= 6378137.0/1000#Semieje mayor f=1/298.257223563 #Achatamiento Tierra #===================================== return spi.georec(longi,lati,alti,RE,f)
def main(): neo="2000433.bsp" N=200 ini="Apr 24 2016 0:00:00" fin="Apr 25 2016 0:00:00" ALT=390 LAT=40.123 LONG=-3.70 obser=EarthLocation(lat=LAT*u.deg,lon=LONG*u.deg,height=ALT*u.m) #=================================================== epoch2000=datetime.datetime.strptime("01-01-2000 00:00","%d-%m-%Y %H:%M") epoch2000=time.mktime(epoch2000.timetuple()) #=================================================== spi.kclear() spi.furnsh("./meta.fgl") spi.furnsh("./../kernels/neos/"+neo) tiempos=spi.str2et([ini,fin]) tiempos=np.linspace(tiempos[0],tiempos[1],N) alt_list=list() times_list=list() for k in tiempos: temp=spi.spkez(int(neo.split(".")[0]),k,"J2000","LT+S",399) temp2=spi.recrad(temp[0][0:3]) ar=(temp2[1]*(180/np.pi)) dec=(temp2[2]*(180/np.pi)) aux=datetime.datetime.utcfromtimestamp(k+epoch2000) fechas_aux=((str(aux.year)+"-"+str(aux.month).zfill(2)+"-"+str(aux.day).zfill(2)+" "+str(aux.hour).zfill(2)+":"+str(aux.minute).zfill(2)+":"+str(aux.second).zfill(2)+"."+str(aux.microsecond))) times_list.append(aux) fechas_aux=Time(fechas_aux) frames_loc=AltAz(obstime=fechas_aux,location=obser) #pdb.set_trace() alt_list.append((SkyCoord(ra=ar*u.deg,dec=dec*u.deg,frame='icrs')).transform_to(frames_loc).alt.value) #pdb.set_trace() output_file("spice.html",title="NEO SOURCE") p=figure(title="NEO Visual",x_axis_label="Time",tools="pan,box_zoom,reset,save,hover",y_axis_label="Elevation (deg)") p.line(times_list,alt_list,legend=neo) hover=p.select_one(HoverTool) hover.point_policy="follow_mouse" show(p)
def load_kernels(): kernels_to_load = [ 'fk/maven_v06.tf', 'ik/maven_iuvs_v01.ti', 'ck/mvn_app_rel_131118_141010_v1.bc', 'sclk/MVN_SCLKSCET.file.tsc', 'spk/trj_c_131118-140923_rec_v1.bsp', ] spicedir = Path('/home/klay6683/IUVS-ITF-SW/anc/spice') mvnkerneldir = spicedir / 'mvn' lskdir = spicedir / 'generic_kernels/lsk' sclkdir = mvnkerneldir / 'sclk' for kernel in kernels_to_load: spice.furnsh(str(mvnkerneldir / kernel)) for fname in sclkdir.iterdir(): spice.furnsh(str(sclkdir / fname)) spice.furnsh(str(lskdir / 'naif0011.tls'))
import SpiceyPy as sp rp=6500. ecc=.77 inc=0. lnode=0. argp=0. m0=0. t0=0. mu=398600.4415 a=rp/(1-ecc) b=a*math.sqrt(1-ecc**2) p=b*b/a t=2*sp.pi()*math.sqrt(a**3/mu) elts=[rp,ecc,inc,lnode,argp,m0,t0,mu] print(sp.conics(elts,0.)) print(sp.conics(elts,0.+t/2)) print(sp.conics(elts,0.+t)) print(dict(a=a,b=b,p=p,t=t,elts=elts,sqrtMuOverP=math.sqrt(mu/p),eccSqrtMuOverP=ecc*math.sqrt(mu/p))) N = 100 def Asincos(i): epoch = t * i / N state = sp.conics(elts,epoch) trueAnom = sp.recrad(state[:3])[1]
def main(): N=1000#1000 #Precision spi.kclear() #Limpiamos el pool de los kernels. #MetaKernel con los datos. spi.furnsh("./meta.fgl") #tiempos=spi.str2et(["Jun 20 2004","Dec 1, 2005"]) tiempos=spi.str2et(["Jun 20 2004","Feb 1, 2005"]) tiempos=np.linspace(tiempos[0],tiempos[1],N) #pdb.set_trace() #Esto es lo mas fino que he llegado: #try: a=list() #Chapuza metida tras sacar velocidad #===================================== x=list() y=list() z=list() dx=list() dy=list() dz=list() #============= for k in tiempos: #temp=spi.spkez(-82,k,"IAU_EARTH","None",399) temp=spi.spkez(2000433,k,"IAU_EARTH","None",399) x.append(temp[0][0]) #Este ya devuelve el vector completo y.append(temp[0][1]) z.append(temp[0][2]) dx.append(temp[0][3]) #Este ya devuelve el vector completo dy.append(temp[0][4]) dz.append(temp[0][5]) x=np.array(x) y=np.array(y) z=np.array(z) dx=np.array(dx) dy=np.array(dy) dz=np.array(dz) mdscc=station(0) #=========================== ==== print "Geocentric position for MDSCC:" print "----------------------------------" print mdscc print "----------------------------------" if False: a=np.array(a) x=list() y=list() z=list() for k in a[0]: x.append(k[0]) y.append(k[1]) z.append(k[2]) #Tenia el dato referedio al centro de masas de la Tierra. Ahora lo refiero a MDSCC. x=x-mdscc[0] y=y-mdscc[1] z=z-mdscc[2] plt.figure() plt.subplot(211) plt.plot(x,y) plt.xlabel("x [Km]") plt.ylabel("y [Km]") plt.subplot(212) plt.plot(y,z) plt.xlabel("y Km") plt.ylabel("z Km") plt.figure() plt.plot(dist(dx,dy,dz)) plt.title("Relative speed as seen from Robledo to Eros") plt.ylabel("Kilometers") plt.xlabel("Samples") plt.grid() fig=plt.figure() ax=fig.add_subplot(111,projection='3d') ax.plot(x,y,z,label="Eros to Robledo de Chavela") plt.legend() plt.show()
def main(): antes=datetime.datetime.now() N=100 #Precision spi.kclear() #Limpiamos el pool de los kernels. #MetaKernel con los datos. spi.furnsh("./meta.fgl") #tiempos=spi.str2et(["Jun 20 2004","Dec 1, 2005"]) ini="Apr 20 2016 0:00:00" fin="Apr 20 2017 0:00:00" tiempos=spi.str2et([ini,fin]) tiempos=np.linspace(tiempos[0],tiempos[1],N) #tiempos=spi.str2et(["Apr 20 2016 0:00:00"]) #pdb.set_trace() #pdb.set_trace() #Esto es lo mas fino que he llegado: #try: a=list() #Chapuza metida tras sacar velocidad #===================================== x=list() y=list() z=list() dx=list() dy=list() dz=list() #============= #Test para spaceapps #colat=list() #longi=list() #radio=list() ar=list() dec=list() radio=list() ayuda=list() #Test para spaceapps (end) for k in tiempos: #temp=spi.spkez(2000433,k,"IAU_EARTH","LT+S",399) temp=spi.spkez(2000433,k,"J2000","LT+S",399) #temp2=spi.xfmsta(temp[0],'RECTANGULAR','SPHERICAL',399) temp2=spi.recrad(temp[0][0:3]) #radio.append(temp2[0]) #colat.append(temp2[1]) #longi.append(temp2[2]) radio.append(temp2[0]) ayuda.append(temp2) ar.append(temp2[1]*(180/np.pi)) dec.append(temp2[2]*(180/np.pi)) x.append(temp[0][0]) #Este ya devuelve el vector completo y.append(temp[0][1]) z.append(temp[0][2]) dx.append(temp[0][3]) #Este ya devuelve el vector completo dy.append(temp[0][4]) dz.append(temp[0][5]) despues=datetime.datetime.now() #spi.xfmtsta(temp[0],'RECTANGULAR','SPHERICAL',399) pdb.set_trace() # despues-antes x=np.array(x) y=np.array(y) z=np.array(z) dx=np.array(dx) dy=np.array(dy) dz=np.array(dz) mdscc=station(0) #=========================== ==== print "Geocentric position for MDSCC:" print "----------------------------------" print mdscc print "----------------------------------" if False: a=np.array(a) x=list() y=list() z=list() for k in a[0]: x.append(k[0]) y.append(k[1]) z.append(k[2]) #Tenia el dato referedio al centro de masas de la Tierra. Ahora lo refiero a MDSCC. x=x-mdscc[0] y=y-mdscc[1] z=z-mdscc[2] #data2=list() #for k in range(len(x)): # data2.append(spi.recrad([x[k],y[k],z[k]])) #data2=np.array(data2) pdb.set_trace() plt.figure() plt.subplot(211) plt.plot(x,y) plt.xlabel("x [Km]") plt.ylabel("y [Km]") plt.subplot(212) plt.plot(y,z) plt.xlabel("y Km") plt.ylabel("z Km") plt.figure() plt.plot(dist(dx,dy,dz)) frase="Relative speed as seen from Robledo to Eros from %s to %s"%(ini,fin) plt.title(frase) plt.ylabel("Kilometers") plt.xlabel("Samples") plt.grid() fig=plt.figure() ax=fig.add_subplot(111,projection='3d') frase="Distance from Eros to Robledo. Starting: %s End: %s"%(ini,fin) ax.plot(x,y,z,label=frase) plt.legend() plt.show()
def inverseDeputy(self,stateDepEqcm=False): """Invert depyty-based calculations. Chief-only calculations were performed in __init__() method above """ #################################################################### ### Process argmument ... if stateDepEqcm: ### Use deputy state argument (6-vector), if supplied rDepEqcm = stateDepEqcm[:3] velDepEqcm = stateDepEqcm[3:] else: ### Use result of .Deputy() method if no state is supplied rDepEqcm = self.rDepEqcm velDepEqcm = self.velDepEqcm #################################################################### ### Equations (11 and 12) are already done in Equations 1 through 5 ### in the constructor __init__() above ### - .mtxEciToRsw1 ### - .{r,vel}ChfRsw1 ### - .lambdaPerigee ### - .trueAnom1 #################################################################### ### Equations (13) ### in the constructor __init__() above ### - .mtxEciToRsw1 self.zinvArcDep = self.arcChf + rDepEqcm[iAeq] self.zinvEccAnom2 = self.invE(arcLengthArg=self.zinvArcDep) self.zinvTrueAnom2 = self.XYtoTrueAnom(self.aChf * math.cos(self.zinvEccAnom2) ,self.bChf * math.sin(self.zinvEccAnom2) ) #################################################################### ### Equation (14) self.zinvDeltaLambdaDep = (twopi + self.zinvTrueAnom2 - self.trueAnom1) % twopi #################################################################### ### Equations (6) repeat from Deputy method, as 2 may be different ### Equivalent chief position at point 2, using PQW2 rChf2 = self.pChf / (1. + (self.eccChf * math.cos(self.zinvTrueAnom2))) pHat = self.vEccHatChf qHat = sp.ucrss([0.,0.,1.],pHat) self.zinvRChfPqw2 = sp.vscl(rChf2,sp.vadd(sp.vscl(math.cos(self.zinvTrueAnom2),pHat),sp.vscl(math.sin(self.zinvTrueAnom2),qHat))) self.zinvVelChfPqw2 = sp.vscl(math.sqrt(self.mu/self.pChf) ,sp.vadd(sp.vscl( -math.sin(self.zinvTrueAnom2),pHat) ,sp.vscl(self.eccChf+math.cos(self.zinvTrueAnom2),qHat) ) ) #################################################################### ### Equations (7) repeat from Deputy method, as 2 may be different ### Convert from PQW2 to RSW2 self.zinvMtxPqw2toRsw2 = RVtoRSW(self.zinvRChfPqw2,self.zinvVelChfPqw2) self.zinvRChfRsw2 = sp.mxv(self.zinvMtxPqw2toRsw2,self.zinvRChfPqw2) self.zinvVelChfRsw2 = sp.mxv(self.zinvMtxPqw2toRsw2,self.zinvVelChfPqw2) #################################################################### ### Equations (15) self.zinvDeltaPhiDep = rDepEqcm[iZeq] / rChf2 rDepHatRsw1 = sp.radrec(1., self.zinvDeltaLambdaDep, self.zinvDeltaPhiDep) #################################################################### ### - Equations (8) repeat from Deputy method, as deputy may differ ### - Transformation matrix from RSW to SEZ frame ### - Matrix is ROT2[90-deltaPhiDep] ROT3[deltaLambdaDep] self.zinvMtxRswToSez = sp.eul2m(halfpi-self.zinvDeltaPhiDep,self.zinvDeltaLambdaDep,0.,2,3,1) #################################################################### ### Equations (16) ### - Transform deputy unit vector from RSW1 to SEZ ### - Scale deputy unit vectors in RSW1 and in SEZ ### - factor is X (R) component of deputy EQCM X (R), plus R ### component of chief RSW2 ### - Transform deputy vector from RSW1 to ECI (transpose matrix) rDepHatSez = sp.mxv(self.zinvMtxRswToSez,rDepHatRsw1) sezScale = (rDepEqcm[iReq] + self.zinvRChfRsw2[iRrsw]) / rDepHatSez[iZsez] self.zinvRDepSez = sp.vscl(sezScale, rDepHatSez) self.zinvRDepRsw1 = sp.vscl(sezScale, rDepHatRsw1) self.zinvRDepEci = sp.mtxv(self.mtxEciToRsw1, self.zinvRDepRsw1) #################################################################### ### Equations (17) ### - final velocity displacements ### - Not working yet: what is rChf? self.zinvVelDepSez = sp.vpack(-velDepEqcm[iZeq] * sezScale / rChf2 #,(velDepEqcm[iAeq] + self.velChfRsw1[iSrsw]) * sezScale * self.zinvDeltaPhiDep / rChf2 ,(velDepEqcm[iAeq] + self.velChfRsw1[iSrsw]) * sezScale * math.cos(self.zinvDeltaPhiDep) / rChf2 ,velDepEqcm[iReq] + self.zinvVelChfRsw2[iRrsw] ) self.zinvVelDepRsw1 = sp.mtxv(self.zinvMtxRswToSez, self.zinvVelDepSez) self.zinvVelDepEci = sp.mtxv(self.mtxEciToRsw1, self.zinvVelDepRsw1) return self.zinvRDepEci,self.zinvVelDepEci
def test_getspiceyexception(): with pytest.raises(spice.stypes.SpiceyError): spice.furnsh(cwd+"/_null_kernel.txt")
def test_geterror(): spice.setmsg("some error occured") spice.sigerr("error") assert spice.failed() assert spice.getmsg("SHORT", 40) == "error" assert spice.getmsg("LONG", 200) == "some error occured"
def XYtoTrueAnom(self,x,y): return sp.recrad(sp.vpack(x-self.cChf,y,0.))[iRA]
def test_getspiceyexception(): with pytest.raises(spice.stypes.SpiceyError): spice.furnsh(cwd + "/_null_kernel.txt")
def __init__(self,stateChf,mu,stateDep=None): """Make chief-only calculations. Save deputy-based calculations for Deputy() method below; call it now if stateDep is provided mu = GM, km**3 s**-2 """ #################################################################### ### Extract ECI Positions and ECI velocities from 6-element ECI states ### Save mu in self object self.rChfEci,self.velChfEci = stateChf[:3], stateChf[3:] self.mu = mu #################################################################### ### Equations (1) and (2) ### Convert chief position and velocity to [Rhat|Shat|What]1 matrix self.mtxEciToRsw1 = RVtoRSW(self.rChfEci,self.velChfEci) #################################################################### ### Transform chief position and velocity to RSW1 frame (self.rChfRsw1 ,self.velChfRsw1 ) = [ sp.mxv(self.mtxEciToRsw1,v) for v in [self.rChfEci,self.velChfEci] ] #################################################################### ### Equations (3) - postponed to deputy calculation #################################################################### ### Equations (4) ### Eccentricity and semi-major axis ### - vHChf = momentum vector ### - self.pChf = semiparameter or semilatus rectum = distance from ### the primary focus to the orbit, measured ### perpendicular to the semi-major axis ### - self.eccChfSquared = Square of Eccentricity ### - derivation, dot product of vEccChf with itself, will always ### be non-negative ### - square root of (1-self.eccChfSquared) will throw math domain ### exception if eccentricity exceeds unity. ### - reciprocal of (1-self.eccChfSquared) will throw division by ### zero exception if eccentricity is unity ### - self.eccChf = Eccentricity (also Elliptic Modulus, k) ### - self.bOverA = ratio of semi-minor to semi-major axes' lengths ### - self.aChf = length of semi-major axis ### - self.bChf = length of semi-minor axis vHChf = sp.vcrss(self.rChfRsw1,self.velChfRsw1) self.pChf = sp.vdot(vHChf,vHChf) / self.mu vEccChf = sp.vsub(sp.vscl(1./self.mu,sp.vcrss(self.velChfRsw1,vHChf)),sp.vhat(self.rChfRsw1)) self.eccChfSquared = sp.vdot(vEccChf,vEccChf) self.eccChf = math.sqrt(self.eccChfSquared) self.bOverA = math.sqrt(1 - self.eccChfSquared) self.aChf = self.pChf / (1. - self.eccChfSquared) self.bChf = self.pChf / self.bOverA self.cChf = self.aChf * self.eccChf if self.eccChfSquared>0.: self.vEccHatChf = sp.vhat(vEccChf) else : self.vEccHatChf = sp.vhat(self.rChfRsw1) ### Use SPICE toolkit routine to calculate perfocal distance (rp), eccentricity, and semi-major axis self.rpChf,self.eccChfSpice,inc,lnode,argp,m0,t0,muTmp = sp.oscelt(stateChf,0.,self.mu) self.aChfSpice = self.rpChf / (1. - self.eccChfSpice) ### Quadrant arc length; used later self.quadArc = self.aChf * E(halfpi,self.eccChfSquared) #################################################################### ### Equations (5) ### Chief True anomaly posiiton ### Deputy True anomaly postponed to deputy calculation self.lambdaPerigee = sp.recrad(self.vEccHatChf)[iRA] self.trueAnom1 = (twopi - self.lambdaPerigee) % twopi #################################################################### ### Equations (6 through 9) - postponed to deputy calculation #################################################################### ### Equations (9) - chief only ### 9.1) Convert True Anomaly 1 (chief) to Eccentric Anomaly self.eccAnom1 = self.TrueToEccAnom(self.trueAnom1) ### Get the arc length from periapse to the chief self.arcChf = self.E(self.eccAnom1) #################################################################### ### Complete conversion to EQCM for Deputy if Deputy state is present if not (stateDep is None): self.Deputy(stateDep)
Test usage: python va2014.py [--mu=398600.4418] [ChiefStateECI DeputyStateECI] - State in ECI is six-element vector: X; Y; Z; Xdot; Ydot; Zdot. """ import os import sys import math import numpy from scipy.special import ellipeinc as E import SpiceyPy as sp halfpi = sp.halfpi() twopi = sp.twopi() dpr = sp.dpr() ### Indices: ECI (xyz); RSW (rsw); SEZ; R,RA,DEC (from sp.recrad(...)) iX, iY, iZ = \ iRrsw, iSrsw, iW = \ iSsez, iE, iZsez = \ iRadius, iRA, iDEC = \ iReq, iAeq, iZeq = \ xrange(3) ######################################################################## class VA2014:
def Asincos(i): epoch = t * i / N state = sp.conics(elts,epoch) trueAnom = sp.recrad(state[:3])[1] return state[3:5],numpy.array([math.cos(trueAnom),math.sin(trueAnom),1])
def initSpice(self): ll = self.db.getList() for val in ll: SpiceyPy.furnsh(val) SpiceyPy.furnsh(self.spkfile)
) PATH_VALUES = ( '.' ) PATH_SYMBOLS = ( 'K' ) ETNEARPRG = @2013-10-09T00:00:00 SPACECRAFT = 'JUNO' TARGET = 'EARTH' \begintext """ import SpiceyPy as spice dpr = spice.dpr() spice.furnsh('.'.join(__file__.split('.')[:-1]+['py'])) target = spice.gcpool('TARGET',0,1,99)[0] spacecraft = spice.gcpool('SPACECRAFT',0,1,99)[0] etnearca = spice.gdpool('ETNEARPRG',0,1)[0] targetID = spice.bods2c(target) et = etnearca state,lt = spice.spkezr(spacecraft,et,'J2000','NONE',target) dt = spice.vdot(state[:3],state[3:]) / spice.vdot(state[3:],state[3:]) oldet = et et = et - dt
def Deputy(self,stateDep): """Make depyty-based calculations. Chief-only calculations were performed in __init__() method above """ #################################################################### ### Extract Deputy ECI Position and velocity from 6-element deputy ### ECI state self.rDepEci,self.velDepEci = stateDep[:3], stateDep[3:] #################################################################### ### Equations (1) and (2) ### Convert deputy position and velocity to RSW using ### [Rhat|Shat|What]1 matrix (self.rDepRsw1 ,self.velDepRsw1 ) = [ sp.mxv(self.mtxEciToRsw1,v) for v in [self.rDepEci,self.velDepEci] ] #################################################################### ### Equations (3) ### Get delta-lambda to deputy as RA from (Radius,RA,DEC) ### returned by recrad. RrdDepRsw1 = sp.recrad(self.rDepRsw1) self.deltaLambdaDep = sp.recrad(self.rDepRsw1)[iRA] #################################################################### ### Equations (5) ### Deputy True anomaly self.trueAnom2 = (twopi + self.deltaLambdaDep - self.lambdaPerigee) % twopi #################################################################### ### Equations (6) ### Equivalent chief position at point 2, using PQW2 rChf2 = self.pChf / (1. + (self.eccChf * math.cos(self.trueAnom2))) pHat = self.vEccHatChf qHat = sp.ucrss([0.,0.,1.],pHat) self.rChfPqw2 = sp.vscl(rChf2,sp.vadd(sp.vscl(math.cos(self.trueAnom2),pHat),sp.vscl(math.sin(self.trueAnom2),qHat))) self.velChfPqw2 = sp.vscl(math.sqrt(self.mu/self.pChf) ,sp.vadd(sp.vscl( -math.sin(self.trueAnom2),pHat) ,sp.vscl(self.eccChf+math.cos(self.trueAnom2),qHat) ) ) #################################################################### ### Equations (7) ### Convert from PQW2 to RSW2 self.mtxPqw2toRsw2 = RVtoRSW(self.rChfPqw2,self.velChfPqw2) self.rChfRsw2 = sp.mxv(self.mtxPqw2toRsw2,self.rChfPqw2) self.velChfRsw2 = sp.mxv(self.mtxPqw2toRsw2,self.velChfPqw2) #################################################################### ### Equations (8) ### Transform Deputy vectors to SEZ frame ### - deltaPhiDep is DEC from [Radius,RA,DEC] of rDepRsw1 ### - Matrix is ROT2[90-deltaPhiDep] ROT3[deltaLambdaDep] self.deltaPhiDep = RrdDepRsw1[iDEC] self.mtxRswToSez = sp.eul2m(halfpi-self.deltaPhiDep,self.deltaLambdaDep,0.,2,3,1) self.rDepSez = sp.mxv(self.mtxRswToSez,self.rDepRsw1) self.velDepSez = sp.mxv(self.mtxRswToSez,self.velDepRsw1) #################################################################### ### Equations (9) ### Transform Deputy vectors from SEZ to EQCM frame ### 9.1) Convert True Anomalies 2 (Deputy) to Eccentric Anomaly 2 ### - https://en.wikipedia.org/wiki/Eccentric_anomaly#From_the_true_anomaly ### - Possible exceptions: divBy0; domain error. ### - Chief done in __init__() method above self.eccAnom2 = self.TrueToEccAnom(self.trueAnom2) ### Ensure .eccAnom2 is within PI/2 of .eccAnom1 while self.eccAnom2 > (self.eccAnom1+math.pi): self.eccAnom2 -= (2 * math.pi) while self.eccAnom2 <= (self.eccAnom1-math.pi): self.eccAnom2 += (2 * math.pi) ### 9.2) Get arc length from positive semi-major axis to deputy self.arcDep = self.E(self.eccAnom2) ### 9.3) Relate the deputy relative to chief at point 2 self.rDepEqcm = sp.vpack( self.rDepSez[iZsez] - self.rChfRsw2[iRrsw] , self.arcDep - self.arcChf , self.deltaPhiDep * rChf2 ) self.velDepEqcm = sp.vpack( self.velDepSez[iZsez] - self.velChfRsw2[iRrsw] #, (self.velDepSez[iE] * rChf2 / (RrdDepRsw1[iRadius] * self.deltaPhiDep )) - self.velChfRsw1[iE] , (self.velDepSez[iE] * rChf2 / (RrdDepRsw1[iRadius] * math.cos(self.deltaPhiDep))) - self.velChfRsw1[iE] , -self.velDepSez[iSsez] * rChf2 / RrdDepRsw1[iRadius] ) return self.rDepEqcm, self.velDepEqcm