Exemplo n.º 1
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
Exemplo n.º 2
0
    def convert_to_inst(self, coords):
        """
        Convert the given coordinates to the instrument frame

        Parameters
        ----------
        coords : `astropy.coordinate.SkyCoord`
            The coordinates to transform to the instrument frame
        frame : `str`, optional
            The instrument coordinate frame (ILS or OPT)

        Returns
        -------
        tuple
            x and y coordinates
        """
        icrs_coords = coords.transform_to('icrs')
        cart_coords = icrs_coords.represent_as('cartesian')

        et = spiceypy.datetime2et(coords.obstime.to_datetime())
        sc = spiceypy.sce2c(SOLAR_ORBITER_ID, et)
        cmat, sc = spiceypy.ckgp(SOLAR_ORBITER_STIX_ILS_FRAME_ID, sc, 0, 'J2000')
        vec = cmat @ cart_coords.xyz.value
        # Rotate about z so +x towards the Sun
        # vec = np.array([[-1, 0, 0], [0, -1, 0], [0, 0, 1]]) @ vec
        distance, latitude, longitude = spiceypy.reclat(vec.reshape(3))

        y = (latitude + np.pi) * u.rad
        x = (np.pi/2 - longitude) * u.rad

        return x, y
Exemplo n.º 3
0
def find_cmatrix(ets_in):
    """find list of c-matrices given ephemeris times and time errors"""

    obs="-143"
    ref="J2000"
    inst = int(obs) * 1000
    matrices = []
    sctol = sp.sctiks(int(obs), SPICE_TOLERANCE)

    for et in ets_in:
        scticks = sp.sce2c(int(obs), et)
        [matrix, sc_time] = sp.ckgp(inst, scticks, sctol, ref)
        matrices.append(matrix)
    return matrices
Exemplo n.º 4
0
def getCameraMatrix(frame, spacecraft, instrument, ephemerisTime):
    """
    Get camera pointing matrix C.
    This is the world-to-camera matrix, from the base frame to the
    given instrument's fixed frame at the given ephemeris time.
    """
    sclkdp = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock double
    # sclkch = spice.sce2s(spacecraft, ephemerisTime) # spacecraft clock string
    # print 'sclkdp',sclkdp
    # see https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckgp_c.html
    tolerance = spice.sctiks(spacecraft, "0:00:800") # time tolerance
    C, clkout, found = spice.ckgp(instrument, sclkdp, tolerance, frame)
    if not found:
        print 'camera pointing matrix not found for time', sclkdp
        # continue
        C = None
    return C
Exemplo n.º 5
0
def cassini_ramdirection_SCframe(tempdatetime, target='CASSINI', frame='J2000', observ='titan', corrtn='NONE',
                                 output=False):
    et = spice.datetime2et(tempdatetime)

    state, ltime = spice.spkezr(target, et, frame, corrtn, observ)
    ramdir = spice.vhat(state[3:6])

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

    ram_unit = spice.mxv(cmat, ramdir)

    if output:
        print('ET        = {:20.6f}'.format(et))
        print('VX        = {:20.6f}'.format(ram_unit[0]))
        print('VY        = {:20.6f}'.format(ram_unit[1]))
        print('VZ        = {:20.6f}'.format(ram_unit[2]))

    return ram_unit
Exemplo n.º 6
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
Exemplo n.º 7
0
    def get_orientation(self, date, frame):
        """
        Get the orientation or roll, pith and yaw of STIX (ILS or OPT).

        Parameters
        ----------
        date : `datetime.datetime`
            Date at which to obtain orientation information
        frame : `str`
            Name of the coordinate frame
        Returns
        -------
        tuple
            Roll, pitch and yaw of the spacecraft
        """
        et = spiceypy.datetime2et(date)
        sc = spiceypy.sce2c(SOLAR_ORBITER_ID, et)
        cmat, sc = spiceypy.ckgp(SOLAR_ORBITER_SRF_FRAME_ID, sc, 0, frame)
        vec = cmat @ np.eye(3)
        roll, pitch, yaw = spiceypy.m2eul(vec, 1, 2, 3)
        roll, pitch, yaw = np.rad2deg([roll, pitch, yaw])*u.deg
        return roll, pitch, yaw
Exemplo n.º 8
0
def getTargetPosition(target, craft, camera, time):
    """
    get position of target in world coordinates relative to the observing craft.
    """
    
    # get target code
    targetId = spice.bodn2c(target) # eg 'Jupiter'->599

    # get spacecraft instrument        
    spacecraft = -31 if craft=='Voyager1' else -32
    spacecraftBus = spacecraft * 1000
    spacecraftScanPlatform = spacecraftBus - 100
    spacecraftNarrowCamera = spacecraftScanPlatform - 1
    spacecraftWideCamera = spacecraftScanPlatform - 2
    # instrument = spacecraftBus # use for NAIF continuous kernels
    instrument = spacecraftScanPlatform # use for PDS discrete kernels

    # get ephemeris time
    # note: target and spacecraft locations are stored relative to J2000
    # time is utc time as string
    ephemerisTime = spice.str2et(time) # seconds since J2000 (will be negative)
    # sclkch = spice.sce2s(spacecraft, ephemerisTime) # spacecraft clock ticks, string
    # sclkdp = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double
    clockTicks = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double
    # print 'clockTicks',clockTicks

    # get position of target relative to spacecraft
    # this is the direction from craft to target in ECLIPB1950 frame
    observer = 'Voyager ' + craft[-1] # eg 'Voyager 1'
    frame = 'ECLIPB1950' # coordinate frame
    abberationCorrection = 'NONE'
    position, lightTime = spice.spkpos(target, ephemerisTime, frame,
                                       abberationCorrection, observer)
    # print 'target position relative to observer', position

    return position
Exemplo n.º 9
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
Exemplo n.º 10
0
    def get_orientation(dt, frame1='SOLO_SRF', frame2='SOLO_EQUAT_NORM'):
        """
        Get the orientation or roll, pith and yaw of STIX (ILS or OPT).
        Taken from https://github.com/i4Ds/STIXCore/blob/9a765a33f2e924ead669b9b99afc1e41a4d2d8e8/stixcore
        /ephemeris/tests/test_position.py#L28-L40
        Parameters
        ----------
        date : `datetime.datetime`
            Date at which to obtain orientation information
        frame : `str`
            Name of the coordinate frame
        Returns
        -------
        tuple
            Roll, pitch and yaw of the spacecraft

        
   SOLO mission specific generic frames:

      SOLO_SUN_RTN                Sun Solar Orbiter Radial-Tangential-Normal
      SOLO_SOLAR_MHP              S/C-centred mirror helioprojective
      SOLO_IAU_SUN_2009           Sun Body-Fixed based on IAU 2009 report
      SOLO_IAU_SUN_2003           Sun Body-Fixed based on IAU 2003 report
      SOLO_GAE                    Geocentric Aries Ecliptic at J2000 (GAE)
      SOLO_GSE                    Geocentric Solar Ecliptic at J2000 (GSE)
      SOLO_HEE                    Heliocentric Earth Ecliptic at J2000 (HEE)
      SOLO_VSO                    Venus-centric Solar Orbital (VSO)

   Heliospheric Coordinate Frames developed for the NASA STEREO mission:

      SOLO_ECLIPDATE              Mean Ecliptic of Date Frame
      SOLO_HCI                    Heliocentric Inertial Frame
      SOLO_HEE_NASA               Heliocentric Earth Ecliptic Frame
      SOLO_HEEQ                   Heliocentric Earth Equatorial Frame
      SOLO_GEORTN                 Geocentric Radial Tangential Normal Frame

   Heliocentric Generic Frames(*):

      SUN_ARIES_ECL               Heliocentric Aries Ecliptic   (HAE)
      SUN_EARTH_CEQU              Heliocentric Earth Equatorial (HEEQ)
      SUN_EARTH_ECL               Heliocentric Earth Ecliptic   (HEE)
      SUN_INERTIAL                Heliocentric Inertial         (HCI)

   Geocentric Generic Frames:

      EARTH_SUN_ECL   (*)         Geocentric Solar Ecliptic     (GSE)
      EARTH_MECL_MEQX (*)         Earth Mean Ecliptic and Equinox of date
                                  frame (Auxiliary frame for EARTH_SUN_ECL)
      EARTH_MECL_MEQX_J2000       Earth Mean Ecliptic and Equinox at J2000
                                  frame (Auxiliary frame for SOLO_GSE and
                                  SOLO_HEE)


        """
        

        et = sp.datetime2et(dt)
        sc = sp.sce2c(SOLAR_ORBITER_ID, et) #convert to clock ticks
        #tol=sp.sctiks(int(sc), "1:000")
        tol= 1.0
        #cmat, sc= sp.ckgp(SOLAR_ORBITER_SRF_FRAME_ID, sc, tol, 'SOLO_ECLIP_NORM')
        #cmat, sc= sp.ckgp(SOLAR_ORBITER_SRF_FRAME_ID, sc, tol, 'SOLO_EQUAT_NORM')
        frame_id=SOLAR_ORBITER_SRF_FRAME_ID if frame1=='SOLO_SRF' else SOLAR_ORBITER_STIX_OPT_FRAME_D

        cmat, sc= sp.ckgp(frame_id, sc, tol, frame2)
        #get c-matrix orientiation information
        roll, pitch, yaw = sp.m2eul(cmat, 1, 2, 3)
        #matrix to Euler angles

        # Following lines taken from from get_sunspice_roll.pro
        #https://www.heliodocs.com/xdoc/xdoc_list.php?dir=$SSW/packages/sunspice/idl
        #if abs(roll) > 2 *math.pi:
        #    roll=roll-math.copysign(2*math.pi,roll)
        #if abs(pitch) > 0.5* math.pi:
        #    #taken from idl code get_sunspice_roll.pro
        #    pitch = math.copysign(2*math.pi,  pitch) - pitch
        #    yaw = yaw - math.copysign(2*math.pi, yaw)
        #    roll = roll - math.copysign(2*math.pi, roll)
        roll, pitch, yaw = np.rad2deg([roll, pitch, yaw])#convert to arcmin

        #take from Frederic idl code
        #if yaw <0:
        #    yaw+=360
        #yaw = yaw-180
        pitch = -pitch
        roll = -roll


        return (roll, pitch, yaw)
Exemplo n.º 11
0
def getCameraMatrix(craft, camera, time):
    """
    get the camera matrix for the given craft and camera at a utc time. 
    assumes libimg.loadKernels has been called.
    returns C, the 3x3 rotation matrix as a numpy array. 
    """
    
    # get target code
    # targetId = spice.bodn2c(target) # eg 'Jupiter'->599

    # get spacecraft instrument        
    spacecraft = -31 if craft=='Voyager1' else -32
    spacecraftBus = spacecraft * 1000
    spacecraftScanPlatform = spacecraftBus - 100
    spacecraftNarrowCamera = spacecraftScanPlatform - 1
    spacecraftWideCamera = spacecraftScanPlatform - 2
    # instrument = spacecraftBus # use for NAIF continuous kernels
    instrument = spacecraftScanPlatform # use for PDS discrete kernels

    # get field of view and focal length
    # f is the focal length relative to the screen halfwidth of 1.0
    # i.e. screen coordinates are -1.0 to 1.0
    #. use ik
    # print 'camera',camera
    fov = config.cameraFOVs[camera] # degrees - 0.424 or 3.169
    screenHalfwidth = 1.0
    f = screenHalfwidth / math.tan(fov/2 * math.pi/180) 
    # print 'f=focal length',f
    
    # get ephemeris time
    # note: target and spacecraft locations are stored relative to J2000
    # time is utc time as string
    ephemerisTime = spice.str2et(time) # seconds since J2000 (will be negative)
    # sclkch = spice.sce2s(spacecraft, ephemerisTime) # spacecraft clock ticks, string
    # sclkdp = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double
    clockTicks = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double
    # print 'clockTicks',clockTicks

    # # get position of target relative to spacecraft
    # # this is the direction from craft to target in ECLIPB1950 frame
    # observer = 'Voyager ' + craft[-1] # eg 'Voyager 1'
    # frame = 'ECLIPB1950' # coordinate frame
    # abberationCorrection = 'NONE'
    # position, lightTime = spice.spkpos(target, ephemerisTime, frame,
    #                                    abberationCorrection, observer)
    # print 'target position relative to observer', position

    # get camera pointing matrix C
    # C is the world-to-camera transformation matrix.
    # ie C is a rotation matrix from the base frame 'frame' to
    # the instrument-fixed frame at the time clockTicks +/- tolerance.
    # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/ckgp_c.html
    tolerance = spice.sctiks(spacecraft, "0:00:800") # time tolerance
    frame = 'ECLIPB1950' # coordinate frame
    # ckgp is 'camera kernel get pointing'
    # note: the pointing information is stored in the time frame J2000,
    # but the coordinates are in the ECLIPB1950 coordinate frame.
    C, clkout, found = spice.ckgp(instrument, clockTicks, tolerance, frame)
    # print 'C=camera pointing matrix - transform world to camera coords'
    # print C

    return C