Exemple #1
0
    def from_spice(cls,
                   *args,
                   sensor_frame,
                   target_frame,
                   center_ephemeris_time,
                   ephemeris_times=[],
                   **kwargs):
        frame_chain = cls()

        times = np.array(ephemeris_times)

        sensor_time_dependent_frames, sensor_constant_frames = cls.frame_trace(
            sensor_frame, center_ephemeris_time)
        target_time_dependent_frames, target_constant_frames = cls.frame_trace(
            target_frame, center_ephemeris_time)

        time_dependent_frames = list(
            zip(sensor_time_dependent_frames[:-1],
                sensor_time_dependent_frames[1:]))
        constant_frames = list(
            zip(sensor_constant_frames[:-1], sensor_constant_frames[1:]))
        target_time_dependent_frames = list(
            zip(target_time_dependent_frames[:-1],
                target_time_dependent_frames[1:]))
        target_constant_frames = list(
            zip(target_constant_frames[:-1], target_constant_frames[1:]))

        time_dependent_frames.extend(target_time_dependent_frames)
        constant_frames.extend(target_constant_frames)

        for s, d in time_dependent_frames:
            quats = np.zeros((len(times), 4))
            avs = np.zeros((len(times), 3))
            for j, time in enumerate(times):
                state_matrix = spice.sxform(spice.frmnam(s), spice.frmnam(d),
                                            time)
                rotation_matrix, avs[j] = spice.xf2rav(state_matrix)
                quat_from_rotation = spice.m2q(rotation_matrix)
                quats[j, :3] = quat_from_rotation[1:]
                quats[j, 3] = quat_from_rotation[0]

            rotation = TimeDependentRotation(quats, times, s, d, av=avs)
            frame_chain.add_edge(rotation=rotation)

        for s, d in constant_frames:
            quats = np.zeros(4)
            rotation_matrix = spice.pxform(spice.frmnam(s), spice.frmnam(d),
                                           times[0])
            quat_from_rotation = spice.m2q(rotation_matrix)
            quats[:3] = quat_from_rotation[1:]
            quats[3] = quat_from_rotation[0]

            rotation = ConstantRotation(quats, s, d)

            frame_chain.add_edge(rotation=rotation)

        return frame_chain
Exemple #2
0
    def frame_chain(self):
        """
        Return the root node of the rotation frame tree/chain.

        The root node is the J2000 reference frame. The other nodes in the
        tree can be accessed via the methods in the FrameNode class.

        This property expects the ephemeris_time property/attribute to be defined.
        It should be a list of the ephemeris seconds past the J2000 epoch for each
        exposure in the image.

        Returns
        -------
        FrameNode
            The root node of the frame tree. This will always be the J2000 reference frame.
        """
        if not hasattr(self, '_root_frame'):
            j2000_id = 1  #J2000 is our root reference frame
            self._root_frame = FrameNode(j2000_id)

            sensor_quats = np.zeros((len(self.ephemeris_time), 4))
            sensor_times = np.array(self.ephemeris_time)
            body_quats = np.zeros((len(self.ephemeris_time), 4))
            body_times = np.array(self.ephemeris_time)
            for i, time in enumerate(self.ephemeris_time):
                sensor2j2000 = spice.pxform(spice.frmnam(self.sensor_frame_id),
                                            spice.frmnam(j2000_id), time)
                q_sensor = spice.m2q(sensor2j2000)
                sensor_quats[i, :3] = q_sensor[1:]
                sensor_quats[i, 3] = q_sensor[0]

                body2j2000 = spice.pxform(spice.frmnam(self.target_frame_id),
                                          spice.frmnam(j2000_id), time)
                q_body = spice.m2q(body2j2000)
                body_quats[i, :3] = q_body[1:]
                body_quats[i, 3] = q_body[0]

            sensor2j2000_rot = TimeDependentRotation(sensor_quats,
                                                     sensor_times,
                                                     self.sensor_frame_id,
                                                     j2000_id)
            sensor_node = FrameNode(self.sensor_frame_id,
                                    parent=self._root_frame,
                                    rotation=sensor2j2000_rot)

            body2j2000_rot = TimeDependentRotation(body_quats, body_times,
                                                   self.target_frame_id,
                                                   j2000_id)
            body_node = FrameNode(self.target_frame_id,
                                  parent=self._root_frame,
                                  rotation=body2j2000_rot)
        return self._root_frame
Exemple #3
0
    def info(self):
        """Read and Output info about the loaded kernels
        """
        spice.kclear()

        spice.furnsh(self.metakernel)

        self.spkList = [
            self.SpkPlanet, self.SpkEros, self.SpkEros2, self.SpkMath,
            self.SpkNearLanded, self.SpkNearOrbit, self.SpkStations
        ]

        self.ckList = [self.Ck]
        self.pckList = [self.PckEros1, self.PckEros2]

        # check SPK coverage
        self.bodies = {}
        self.bodies_coverage = {}
        for spk in self.spkList:
            idcell = spice.spkobj(spk)
            for code in idcell:
                cover = spice.stypes.SPICEDOUBLE_CELL(1000)
                spice.spkcov(spk, code, cover)
                self.bodies[str(code)] = spice.bodc2n(code)
                self.bodies[spice.bodc2n(code)] = code
                self.bodies_coverage[str(code)] = [x for x in cover]
                self.bodies_coverage[spice.bodc2n(code)] = [x for x in cover]

        # check CK coverage
        self.ckframes = {}
        self.ckframes_coverage = {}
        for ck in self.ckList:
            idcell = spice.ckobj(ck)
            for code in idcell:
                cover = spice.ckcov(ck, code, True, 'SEGMENT', 0.0, 'TDB')
                self.ckframes[str(code)] = spice.frmnam(code)
                self.ckframes[spice.frmnam(code)] = code
                self.ckframes_coverage[str(code)] = [x for x in cover]
                self.ckframes_coverage[spice.frmnam(code)] = [x for x in cover]

        # check pck coverage
        self.pckframes = {}
        for pck in self.pckList:
            ids = spice.stypes.SPICEINT_CELL(1000)
            spice.pckfrm(pck, ids)
            for code in ids:
                self.pckframes[str(code)] = spice.frmnam(code)
                self.pckframes[spice.frmnam(code)] = code

        spice.kclear()
Exemple #4
0
def target2frame(target):

    if target == '67P/C-G':
        target_frame = '67P/C-G_CK'
    elif target == '21 LUTETIA':
        target_frame = 'LUTETIA_FIXED'
    elif target == 'DIDYMOS' or target == 'DIDYMOON':
        target_frame = '{}_FIXED'.format(target)
    else:
        try:
            target_frame = 'IAU_' + target.upper()
            target_frame_id = spiceypy.namfrm(target_frame)
            if target_frame_id == 0:
                raise Exception
        except:
            try:
                target_id = str(spiceypy.bodn2c(target))
                target_frame = spiceypy.frmnam(int(target_id))
            except:
                target_id += '000'
                target_frame = spiceypy.frmnam(int(target_id))


    return target_frame
Exemple #5
0
def cov_int(object_cov,
            object_id,
            kernel,
            time_format='TDB',
            global_boundary=False,
            report=False):
    """
    Generates a list of time windows out of a SPICE cell for which either
    the SPICE API spkcov_c or ckcov_c have been run.


    :param object_cov: SPICE
    :type object_cov:
    :param object_id: Object ID or Name for which we provide the coverage
    :type object_id: Union[str, int]
    :param kernel: Kernel name for which the coverage is being checked
    :type kernel: str
    :param time_format: Desired output format; 'UTC' or 'CAL'
    :type time_format: str
    :param global_boundary: Boolean to indicate whether if we want all the coverage windows or only the absolute start and finish coverage times
    :type global_boundary: bool
    :param report: If True prints the resulting coverage on the screen
    :type report: bool
    :return: Time Windows in the shape of a list
    :rtype: list
    """
    boundaries = False

    if '/' in kernel:
        kernel = kernel.split('/')[-1]

    #
    # Reporting should only be activated if we are not asking for global
    # boundaries.
    #
    if report and not global_boundary:

        try:
            body_name = spiceypy.bodc2n(object_id)
        except:
            body_name = spiceypy.frmnam(object_id, 60)

        print("Coverage for {} in {} [{}]:".format(body_name, kernel,
                                                   time_format))

    number_of_intervals = list(range(spiceypy.wncard(object_cov)))
    interval_start_list = []
    interval_finish_list = []
    coverage = []

    for element in number_of_intervals:
        et_boundaries = spiceypy.wnfetd(object_cov, element)

        if time_format == 'CAL' or time_format == 'UTC':
            boundaries = et2cal(et_boundaries, format=time_format)
        else:
            boundaries = et_boundaries

        interval_start = boundaries[0]
        interval_finish = boundaries[1]

        if report and not global_boundary:

            print("Interval {}: {} - {}\n".format(element, boundaries[0],
                                                  boundaries[1]))

        coverage.append(interval_start)
        coverage.append(interval_finish)
        interval_start_list.append(interval_start)
        interval_finish_list.append(interval_finish)

    #
    # If the global_boundary parameter is set the only output is the global
    # coverage start and finish
    #
    if global_boundary:

        start_time = min(interval_start)
        finish_time = max(interval_finish)

        coverage = et2cal([start_time, finish_time], format=time_format)

    return coverage