Ejemplo n.º 1
0
def search_stars(obsinfo, mag_limit=7.0):
    query = ("SELECT"
             " CATALOG_NUMBER,RA,DEC,VISUAL_MAGNITUDE,PARLAX,SPECTRAL_TYPE"
             " FROM HIPPARCOS")
    nmrows, _error, _errmsg = spice.ekfind(query)
    stars = []
    for row in range(nmrows):
        ra = spice.ekgd(1, row, 0)[0] * spice.rpd()
        dec = spice.ekgd(2, row, 0)[0] * spice.rpd()
        mag = spice.ekgd(3, row, 0)[0]
        vec = spice.radrec(1.0, ra, dec)
        tvec = spice.mxv(obsinfo.ref2obsmtx, vec)
        _tpa, tdist = vec_padist(obsinfo.center, tvec)
        if tdist < obsinfo.fov.fovmax and mag < mag_limit:
            parallax = spice.ekgd(4, row, 0)[0]
            spectral = spice.ekgc(5, row, 0)[0]
            distance = 1.0 / np.tan(parallax * spice.rpd())
            distance = spice.convrt(distance, "AU", "km")
            pos = tvec * distance
            vp = viewport_frustum(obsinfo.fov.bounds_rect, obsinfo.width,
                                  obsinfo.height, pos)
            star = {
                "hip_id": spice.ekgi(0, row, 0)[0],
                "position": tvec,
                "ra": ra,
                "dec": dec,
                "spectral_type": spectral,
                "visual_magnitude": mag,
                "distance": distance,
                "image_pos": vp[0:2],
                "color": get_star_color(spectral),
            }
            stars.append(star)
    return stars
Ejemplo n.º 2
0
def caps_all_anodes(tempdatetime):
    et = spice.datetime2et(tempdatetime)
    sclkdp = spice.sce2c(
        -82, et)  # converts an et to a continuous encoded sc clock (ticks)

    caps_els_anode_vecs = []
    for anodenumber, x in enumerate(np.arange(70, -90, -20)):
        # print(anodenumber, x)
        rotationmatrix_anode = spice.spiceypy.axisar(np.array(
            [1, 0, 0]), x * spice.rpd())  # Get angles for different anodes
        # print("rotationmatrix_anode", rotationmatrix_anode)
        postanode_rotation = spice.vhat(
            spice.mxv(rotationmatrix_anode, -spice.spiceypy.getfov(
                -82821, 20)[2]))  # Apply rotation for anodes
        # print("postanode_rotation", postanode_rotation)

        # print("caps_els_boresight", caps_els_boresight)
        cassini_caps_mat = spice.ckgp(
            -82821, sclkdp, 0, 'CASSINI_CAPS_BASE')[0]  # Get actuation angle
        # print("cassini_caps_mat", cassini_caps_mat)
        cassini_caps_act_vec = spice.mxv(
            cassini_caps_mat, postanode_rotation)  # Rotate with actuator
        # print("Actuating frame", cassini_caps_act_vec)

        CAPS_act_2_titan_cmat = spice.ckgp(
            -82000, sclkdp, 0,
            'IAU_TITAN')[0]  # Find matrix to transform to IAU_TITAN frame
        CAPS_act_2_titan_cmat_transpose = spice.xpose(
            CAPS_act_2_titan_cmat)  # Tranpose matrix
        rotated_vec = spice.mxv(CAPS_act_2_titan_cmat_transpose,
                                cassini_caps_act_vec)  # Apply Matrix
        # print("rotated_vec ", rotated_vec)
        caps_els_anode_vecs.append(rotated_vec)

    return caps_els_anode_vecs
Ejemplo n.º 3
0
def caps_crosstrack(tempdatetime, windspeed):
    et = spice.datetime2et(tempdatetime)

    state, ltime = spice.spkezr("CASSINI", et, "IAU_TITAN", "NONE", "titan")
    ramdir = spice.vhat(state[3:6])
    # print("ramdir",ramdir)

    # Gets Attitude
    sclkdp = spice.sce2c(
        -82, et)  # converts an et to a continuous encoded sc clock (ticks)
    ckgp_output = spice.ckgp(-82000, sclkdp, 0, "IAU_TITAN")
    cmat = ckgp_output[0]

    spacecraft_axis = np.array([0, 0, 1])
    rotated_spacecraft_axis = spice.mxv(cmat, spacecraft_axis)
    # print("cmat", cmat)
    # print("rotated spacecraft axis",rotated_spacecraft_axis)
    ram_unit = spice.mxv(cmat, -ramdir)  # Ram Unit in SC coords
    # print("ram_unit",ram_unit)

    if windspeed < 0:
        rotationmatrix = spice.axisar(np.array([0, 0, -1]), 90 * spice.rpd())
    if windspeed > 0:
        rotationmatrix = spice.axisar(np.array([0, 0, -1]), -90 * spice.rpd())

    # print(rotationmatrix)
    crossvec = spice.mxv(
        rotationmatrix,
        ram_unit)  # Rotate ram unit to find crosstrack velocity vector
    # print("temp crossvec",crossvec)
    # print("vsep SC Frame",spice.vsep(ram_unit,crossvec)*spice.dpr())
    cmat_t = spice.xpose(cmat)
    crossvec_titan = spice.mxv(cmat_t,
                               crossvec)  # Transform back to IAU Titan Frame

    # print("crossvec", crossvec)
    # print("crossvec_titan", crossvec_titan, spice.unorm(crossvec_titan))
    # print("vsep titan frame", spice.vsep(ramdir, crossvec_titan) * spice.dpr())

    return crossvec_titan
Ejemplo n.º 4
0
def rotate_CAPS_SCframe(CAPS_actuation, instrument, anodes=False):
    """
    Returns the CAPS pointing vector after actuation in the SC frame
    """
    naifiddict = {'ims': -82820, 'els': -82821, 'ibs1': -82822, 'ibs2': -82823, 'ibs3': -82824}
    naifid = naifiddict[instrument]

    if not anodes:
        rotationmatrix = spice.spiceypy.axisar(np.array([0, 0, -1]), CAPS_actuation * spice.rpd())
        temp = spice.mxv(rotationmatrix, spice.spiceypy.getfov(naifid, 20)[2])

    if (instrument == 'ims' or instrument == 'els') and anodes == True:
        temp = []

        rotationmatrix_act = spice.spiceypy.axisar(np.array([0, 0, -1]), CAPS_actuation * spice.rpd())

        for anodenumber, x in enumerate(np.arange(70, -90, -20)):
            rotationmatrix_anode = spice.spiceypy.axisar(np.array([-1, 0, 0]), x * spice.rpd())
            postanode_rotation = spice.mxv(rotationmatrix_anode, spice.spiceypy.getfov(naifid, 20)[2])

            temp.append(spice.mxv(rotationmatrix_act, postanode_rotation))

    return temp
Ejemplo n.º 5
0
import os
import sys
import math
import gaiaif_util
import spiceypy as sp

rpd = sp.rpd()

if "__main__" == __name__:

  ### RA,Dec box
  ### Circle
  ### Polygon (non-convex quadrilateral)
  ### Polygon (convex quadrilateral)
  for fov in (gaiaif_util.FOV([[315,89.2],[15,89.8]])
             ,gaiaif_util.FOV([[345,89.3],0.5])
             ,gaiaif_util.FOV([[30,89],[0,88.5],[5.0,88.9],[270,89]])
             ,gaiaif_util.FOV([[30,89],[0,88.5],[315,88.5],[270,89]])
             ,gaiaif_util.FOV([[225,89],[0,88.5],[315,88.5],[90,89]])
             ,):

    radec_boxes = fov.get_radec_boxes()
    ###for radec_box in radec_boxes: print(radec_box) 
    if fov.POLYGONTYPE == fov.fovtype:
      print(dict(fov_is_convex=fov.is_convex()))

    def inbox(ra,dec):
      for ralo,rahi,declo,dechi in radec_boxes:
        if ra<ralo: continue
        if ra>rahi: continue
        if dec<declo: continue
Ejemplo n.º 6
0
def EarthRepeatOrbits(jk,
                      e,
                      Variable,
                      VarType,
                      isHighFidelity=False,
                      printStatus=False):
    """Find a set of repeating ground track orbits around Earth (Earth-repeat orbits)."""

    # importing the required modules
    import spiceypy as spice
    import math
    import numpy as np

    Result = 0
    Nsolutions = 0

    # Error handling
    jkSize = jk.shape
    if (int(jkSize[1]) != 2):
        print(
            'Incorrect matrix size for jk matrix. Only two coloumns are required.'
        )
        return Result
    elif (VarType != 'Alti') and (VarType != 'Inclin'):
        print(
            'Inrecognized input for the argument specifying the variable type.'
        )
        return Result
    elif e >= 1.0 or e < 0:
        print(
            'Only circular or elliptical orbits are possible. Check the value of eccentricity.'
        )
        return Result
    elif (Variable[1] - Variable[0]) % Variable[2] != 0:
        print(
            'Integer number of steps are not possible. Check inputs for the argument - "Variable".'
        )
        return Result

    # Extracting the parameters
    spice.furnsh("./External_files/Spice_kernels/kernel_load.txt")
    muE = spice.bodvrd('Earth', 'GM', 1)
    mu = muE[1][0]  # [km3/s2] for earth
    J2 = 1082.63E-6  #J2 for earth
    RE = spice.bodvrd('EARTH', 'RADII', 3)
    Re = RE[1][0]  # [km], Average radius of Earth
    De = 86164.1004  # [s], Sidereal day
    k2 = 0.75 * J2 * math.sqrt(mu) * Re * Re
    r2d = 1 / spice.rpd()  # Radian to degree conversion

    # Creating storage
    steps = int((Variable[1] - Variable[0]) / Variable[2]) + 1
    Result = np.zeros(int(jkSize[0]) * int(steps) * 6)
    Result.shape = [int(jkSize[0]), int(steps), 6]

    # Computations
    for count in range(0, jkSize[0]):  #looping over j and k values

        for rowCount in range(0, int(steps)):  #looping over variable values
            j = jk[count, 0]
            k = jk[count, 1]

            # Extracting the value of variable
            var = Variable[0] + rowCount * Variable[2]

            # Storing values known so far
            Result[count, rowCount, 0] = j
            Result[count, rowCount, 1] = k
            Result[count, rowCount, 2] = e
            Result[count, rowCount, 3] = var
            Result[count, rowCount, 4] = math.nan  # to be computed
            Result[count, rowCount, 5] = math.nan  # to be computed

            if isHighFidelity == False:
                if VarType == 'Alti':
                    a = (Re + var) / (1 - e)
                    T = 2 * math.pi * math.sqrt(a**3 / mu)

                    DeltaL1 = -2 * math.pi * (T / De)
                    # DeltaL2 = C1 * cosi
                    C1 = (-3 * math.pi * J2 * Re**2) / (a**2 * (1 - e**2)**2)
                    C2 = -2 * math.pi * k / j - DeltaL1
                    C3 = 2 * math.pi * k / j - DeltaL1

                    # Inverse cosine
                    if (C2 < 0) & (abs(C2 / C1) <= 1):
                        DeltaL2 = C2
                        i = math.acos(
                            DeltaL2 / C1) * r2d  # for i = [0, 90] deg
                        Result[count, rowCount, 4] = i
                        Nsolutions += 1
                    elif (C2 > 0) & (abs(C2 / C1) <= 1):
                        DeltaL2 = C2
                        i = math.acos(
                            DeltaL2 / C1) * r2d  # for i = (90, 180] deg
                        Result[count, rowCount, 4] = i
                        Nsolutions += 1
                    elif (C3 < 0) & (abs(C3 / C1) <= 1):
                        DeltaL2 = C3
                        i = math.acos(
                            DeltaL2 / C1) * r2d  # for i = [0, 90] deg
                        Result[count, rowCount, 5] = i
                        Nsolutions += 1
                    elif (C3 > 0) & (abs(C3 / C1) <= 1):
                        DeltaL2 = C3
                        i = math.acos(
                            DeltaL2 / C1) * r2d  # for i = (90, 180] deg
                        Result[count, rowCount, 5] = i
                        Nsolutions += 1
                elif VarType == 'Inclin':
                    print(
                        'Function is not defined for low fidelity + unknown inclination case.'
                    )
                    return Result
            else:
                if VarType == 'Alti':
                    a = (Re + var) / (1 - e)
                    C1 = -2 * k2 * (a**-3.5) * (
                        (1 - e**2)**-2) * De * r2d  # RAAN_dot = C1 * cos(i)
                    C2 = k2 * (a**-3.5) * (
                        (1 - e**2)**
                        -2) * De * r2d  # omega_dot = C2 *(5*(cosd(i))^2 -1)
                    C3 = k2 * (a**-3.5) * (
                        (1 - e**2)**
                        -1.5) * De * r2d  # M_dot = C3 *(3*(cosd(i))^2 -1)
                    n = De * r2d * math.sqrt(mu / a**3)

                    # For the quadratic equation A*x^2 + B*x +C = 0 with x = cos(i)
                    A = 5 * C2 + 3 * C3
                    B = C1 * j / k
                    C = n - 360 * j / k - (C2 + C3)
                    D = B**2 - 4 * A * C

                    if D >= 0:
                        if (D == 0) & (abs(-B / (2 * A)) <= 1):
                            i1 = math.acos(-B / (2 * A))
                            Result[count, rowCount, 4] = i1 * r2d
                            Nsolutions += 1
                        elif (D > 0):
                            x1 = (-B + math.sqrt(D)) / (2 * A)
                            x2 = (-B - math.sqrt(D)) / (2 * A)
                            if abs(x1) <= 1:
                                i1 = math.acos(x1)
                                Result[count, rowCount, 4] = i1 * r2d
                                Nsolutions += 1
                            if abs(x2) <= 1:
                                i2 = math.acos(x2)
                                Result[count, rowCount, 5] = i2 * r2d
                                Nsolutions += 1
                elif VarType == 'Inclin':

                    a0 = math.pow(
                        (mu * De**2 * k**2 / (4 * math.pi**2 * j**2)), 1 / 3)
                    iterations = 0
                    i = var
                    L_dot = 360

                    while True:
                        iterations = iterations + 1

                        RAAN_dot = -2 * k2 * math.pow(a0, -3.5) * math.cos(
                            i / r2d) * math.pow(1 - e**2, -2) * De * r2d
                        omega_dot = k2 * math.pow(
                            a0, -3.5) * (5 * (math.cos(i / r2d))**2 -
                                         1) * math.pow(1 - e**2, -2) * De * r2d
                        M_dot = k2 * math.pow(a0, -3.5) * (
                            3 * (math.cos(i / r2d))**2 - 1) * math.pow(
                                1 - e**2, -1.5) * De * r2d
                        n = (j / k) * (L_dot - RAAN_dot) - (omega_dot + M_dot)

                        a1 = (mu / (n / (De * r2d))**2)**(1 / 3)

                        if iterations > 1000:
                            a0 = a1
                            break
                        elif (abs(a1 - a0) < 10**(-10)):
                            a0 = a1
                            break
                        else:
                            a0 = a1

                    # Only tracking the feasible solutions i.e. positive altitudes
                    if ((a0 * (1 - e)) - Re) > 0:
                        Nsolutions += 1
                        Result[count, rowCount, 4] = (a0 * (1 - e)) - Re

    # Printing the status of solutions obtained
    if printStatus == True:
        print(Nsolutions,
              ' solutions are obtained for the Earth-repeat orbits.')

    return Result
Ejemplo n.º 7
0
import spiceypy as sp
import traceback as tb

do_debug = 'DEBUG' in os.environ

########################################################################
### Parse command-line argument(s), setup parameters

### --hang=<cone half-angle, degrees>
default_hang = 30.0
hangdeg = float(
    ([default_hang] +
     [s[7:] for s in sys.argv[1:] if s.startswith('--hang=')]).pop())

### Conversion factors between degrees and radians
dpr, rpd = sp.dpr(), sp.rpd()

### Cone half-angle and samples of Declinations, from 0 to (89.5-delta)
decdegs = [(0.5 * decdec) - (decdec > 0 and 1e-6 or 0)
           for decdec in range(180)]

### Convert to radians
hangrad = rpd * hangdeg
decrads = [rpd * decdeg for decdeg in decdegs]

### Trig functions of same
tansqhang = math.tan(hangrad)**2
sinhang = math.sin(hangrad)
coshang = math.cos(hangrad)

### List of triples of tan(Dec) squared, cos(Dec), and Dec
Ejemplo n.º 8
0
"""
Compare gaiaif_util.py corrections for parallax and stellar aberration
to equivalent correction in SPICE

"""
import os
import math
import fov_cmd
import sqlite3 as sl3
import spiceypy as sp
import gaiaif_util as gifu

### Setup debugging and conversions; define some string constants
do_debug = 'DEBUG' in os.environ
rpd, aupkm = sp.rpd(), sp.convrt(1., 'km', 'au')
(
    earth,
    ssb,
    j2000,
    none,
    LT,
    LTS,
    ra_dec,
    declination,
    equals,
) = 'earth 0 j2000 none lt lt+s ra/dec declination ='.upper().split()

sp.furnsh('de421.bsp')

gaia_db = 'gaia.sqlite3'
Ejemplo n.º 9
0
           

if Question ==1:
############ Question 1 - validation, solved using approach 2 
    
    
    i = 28.0 # %deg
    e = 0.0 # assumption
    D = 86164.1004 #s - import from spice
    muE = spice.bodvrd( 'EARTH', 'GM', 1 ); #km3/s2 for earth 
    mu = muE[1][0]
    J2 = 1082.63E-6 #J2 for earth - import from spice
    RE = spice.bodvrd('EARTH','RADII',3)
    Re = RE[1][0] # Radius of Earth, from SPICE - pck00010.tpc, 6378.1366 km
    L_dot = 360.0
    r2d = 1/spice.rpd() # Radians per degree
    print('r2d2 is: ',r2d)
    k2 = 0.75 * J2 * math.sqrt(mu)* Re*Re
    
    
    
    # Method 1 # READ 10.2.1. of the course handbook
    jkStore = np.matrix('14, 1; 43, 3; 29, 2; 59, 4; 74, 5 ; 15,1')
    #jk = jkStore[0][0]
    #print(jk)
    
    
    ## Method 2 # READ 10.2.1. of the course handbook
    #jkStore2 = np.array([14, 1, 43, 3, 29, 2, 59, 4, 74, 5 , 15, 1])
    #jkStore2.shape = [6,2] # READ 10.2.1. of the course handbook
    
Ejemplo n.º 10
0
def caps_crosstrack_spice(tempdatetime, windspeed):
    et = spice.datetime2et(tempdatetime)
    sclkdp = spice.sce2c(
        -82, et)  # converts an et to a continuous encoded sc clock (ticks)

    state, ltime = spice.spkezr("CASSINI", et, "IAU_TITAN", "NONE", "titan")
    ramdir = spice.vhat(state[3:6])
    # print("ramdir",ramdir)

    # Gets Attitude
    sclkdp = spice.sce2c(
        -82, et)  # converts an et to a continuous encoded sc clock (ticks)
    ckgp_output = spice.ckgp(-82000, sclkdp, 0, "IAU_TITAN")
    cmat = ckgp_output[0]
    print("cmat", cmat)

    ram_unit = spice.mxv(cmat, ramdir)  # Ram Unit in SC coords
    # print("ram_unit", ram_unit)
    anglediff = spice.vsepg(
        ram_unit[:2], np.array([0, 1, 0]),
        2)  # Find azimuthal angle between normal boresight and ram direction
    # print("anglediff", anglediff * spice.dpr())
    cassini_ram_mat = spice.rotate(-anglediff, 3)
    # print("cassini_ram_mat", cassini_ram_mat)
    # Rotates rotational axis with actuation
    # cassini_caps_mat = spice.ckgp(-82821, sclkdp, 0, 'CASSINI_CAPS_BASE')[0]  # Rotation matrix of actuation
    # print("cassini_caps_mat", cassini_caps_mat)
    anode_rotational_axis = spice.mxv(cassini_ram_mat,
                                      np.array([1, 0,
                                                0]))  # Rotate with actuator
    print("Rotational Axis", anode_rotational_axis)

    rotationmatrix_1 = spice.spiceypy.axisar(anode_rotational_axis,
                                             -70 * spice.rpd())
    rotationmatrix_2 = spice.spiceypy.axisar(anode_rotational_axis,
                                             70 * spice.rpd())

    ram_unit_rotated1 = spice.mxv(rotationmatrix_1, ram_unit)
    ram_unit_rotated2 = spice.mxv(rotationmatrix_2, ram_unit)
    scframe_spiceplane = spice.psv2pl([0, 0, 0], ram_unit_rotated1,
                                      ram_unit_rotated2)
    print("ram_unit", ram_unit, ram_unit_rotated1, ram_unit_rotated2)
    print("SC frame spice normal",
          spice.psv2pl([0, 0, 0], ram_unit_rotated1, ram_unit_rotated2))
    cmat_t = spice.xpose(cmat)
    ram_unit_rotated1_titan = spice.mxv(
        cmat_t, ram_unit_rotated1)  # Transform back to IAU Titan Frame
    ram_unit_rotated2_titan = spice.mxv(
        cmat_t, ram_unit_rotated2)  # Transform back to IAU Titan Frame
    spiceplanenormal = spice.mxv(cmat_t, spice.pl2nvp(scframe_spiceplane)[0])

    # Old method finding normal in titan frame
    # spiceplane = spice.psv2pl(state[:3], ram_unit_rotated1_titan, ram_unit_rotated2_titan)
    # spiceplanenormal = spice.pl2nvp(spiceplane)[0]

    print("SPICE NORMAL", spiceplanenormal)
    # print("Spice normal, sc frame", scframe_spicenormal_titan)

    if windspeed > 0:
        spiceplanenormal = -1 * spiceplanenormal
        print("spice plane fipped", windspeed, spiceplanenormal)

    print("vsep titan frame",
          spice.vsep(ramdir, spiceplanenormal) * spice.dpr())

    return spiceplanenormal, ram_unit_rotated1_titan, ram_unit_rotated2_titan
Ejemplo n.º 11
0
import os
import sys
import math
import numpy
import spiceypy as sp

try: dpr
except:
  dpr = sp.dpr()                                       ### degree / Radian
  rpd = sp.rpd()                                       ### Radian / degree
  rpmas = sp.convrt(1.,'arcseconds','radians') * 1e-3  ### Radian / milliarcsecond
  aupkm = sp.convrt(1.,'km','au')                      ### Astonomical Unit / kilometer
  recip_clight = 1.0 / sp.clight()


########################################################################
class FOV(object):
  """
Field-Of-View (FOV) and methods to determine if a ray is inside the FOV

Attributes

.L            Length of FOV argument to .__init__
.fovtype      FOV type:  FOV.CIRCLETYPE; RADECBOXTYPE;,.POLYGONTYPE
.radecdegs    List of [RA,Dec] pairs of input vectors/vertices, degrees
.uvfovxyzs    List of Unit vectors of [X,Y,Z] triples of input vectors
.hangdeg      Cone half-angle for circle FOV, degrees
.hangrad      Cone half-angle for circle FOV, radians
.radec_boxes  List of lists:  FOV bounding boxes; ralo,rahi,declo,dechi
.convex       True is FOV is convex, else False
    lats.append(lat)
    lons.append(lon)
data['Altitude'] = alts
data['Longitude'] = lons
data['Latitude'] = lats

data = data[data['Peak Energy'] > 15]
data.dropna(subset=['Bulk Azimuth'], inplace=True)
data = data[(data["Actuation Direction"]=="positive") | (data["Actuation Direction"]=="negative")]

velocityseries = pd.Series(dtype=float)
flybyslist = data.Flyby.unique()

for counter, flyby in enumerate(data.Flyby.unique()):
    tempdf = data[data['Flyby'] == flyby]
    tempvelocities = [np.sin(x * spice.rpd()) * titan_flybyvelocities[flyby] for x in
                      tempdf["Bulk Deflection from Ram Angle"]]

    tempseries = pd.Series(data=tempvelocities, name=flyby)
    tempseries.reset_index(drop=True, inplace=True)
    velocityseries = velocityseries.append(tempseries)

data.reset_index(drop=True, inplace=True)
velocityseries.reset_index(drop=True, inplace=True)
velocityseries.name = "Crosstrack velocity"

absvelocityseries = abs(velocityseries)
absvelocityseries.name = "Absolute Crosstrack velocity"
data = pd.concat([data, velocityseries, absvelocityseries], axis=1)
data["Azimuthal Ram Time temp"] = pd.to_datetime(data["Azimuthal Ram Time"]).apply(lambda x: x.replace(microsecond=0))
data.drop_duplicates(subset="Azimuthal Ram Time temp",inplace=True)