Unverified Commit 5124f92b authored by Oleg Alexandrov's avatar Oleg Alexandrov Committed by GitHub
Browse files

Fixes for MSL (#580)

* Some potential fixes for MSL

Post-conflict fixes

More conflict merging

More reconciliation with recent ale

More reconciliation

Fix for pixel size

* Bugfix for focal length lookup for nav cam

* Make some MSL tests pass

Undo some tests

* Fix for nadir mode with MSL cameras

* Spellcheck

* Add changelog note for MSL

* CHANGELOG: Spell

* Move changelog note
parent cf11ad78
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ release.


### Fixed
### Fixed
- Fixed LRO MiniRF drivers naif keywords focal to pixel and pixel to focal translations to be correct. [#569](https://github.com/DOI-USGS/ale/pull/569)
- Fixed LRO MiniRF drivers naif keywords focal to pixel and pixel to focal translations to be correct. [#569](https://github.com/DOI-USGS/ale/pull/569)
- Bugfix for position and orientation for MSL cameras (driver MslMastcamPds3NaifSpiceDriver). Validated that Nav and Mast LBL files (for both left and right sensor) produce correctly positioned and oriented CSM cameras, that are self-consistent and consistent with a prior DEM for the site. [#580](https://github.com/DOI-USGS/ale/pull/580) 


### Changed
### Changed
- Removed the affine6p library and replaced affine6p's affine transformation with a numpy solution [#579](https://github.com/DOI-USGS/ale/pull/579) 
- Removed the affine6p library and replaced affine6p's affine transformation with a numpy solution [#579](https://github.com/DOI-USGS/ale/pull/579) 
@@ -77,3 +78,6 @@ release.
- Chandrayaan1_mrffr IsisLabelNaifSpice driver, tests and test data [#519](https://github.com/DOI-USGS/ale/pull/519)
- Chandrayaan1_mrffr IsisLabelNaifSpice driver, tests and test data [#519](https://github.com/DOI-USGS/ale/pull/519)
- MGS MOC Narrow Angle IsisLabelNaifSpice driver, tests, and test data [#517](https://github.com/DOI-USGS/ale/pull/517)
- MGS MOC Narrow Angle IsisLabelNaifSpice driver, tests, and test data [#517](https://github.com/DOI-USGS/ale/pull/517)
- Hayabusa NIRS IsisLabelNaifSpice driver, tests and test data [#532](https://github.com/DOI-USGS/ale/pull/532)
- Hayabusa NIRS IsisLabelNaifSpice driver, tests and test data [#532](https://github.com/DOI-USGS/ale/pull/532)


+59 −15
Original line number Original line Diff line number Diff line
@@ -373,9 +373,8 @@ class RollingShutter():


class Cahvor():
class Cahvor():
    """
    """
    Mixin for largely ground based sensors to add an
    Mixin for ground-based sensors to add to the position and rotation
    extra step in the frame chain to go from ground camera to
    the components going from rover frame to camera frame.
    the Camera
    """
    """


    @property
    @property
@@ -396,17 +395,50 @@ class Cahvor():


    @property
    @property
    def sensor_position(self):
    def sensor_position(self):
        """
        Find the rover position, then add the camera position relative to the
        rover. The returned position is in ECEF.
        
        Returns
        -------
        : (positions, velocities, times)
          a tuple containing a list of positions, a list of velocities, and a
          list of times.
        """
        
        # Rover position in ECEF
        positions, velocities, times = super().sensor_position
        positions, velocities, times = super().sensor_position
      positions += self.cahvor_camera_dict["C"]
        
        nadir = self._props.get("nadir", False)
        if nadir:
          # For nadir applying the rover-to-camera offset runs into 
          # problems, so return early. TBD 
          return positions, velocities, times

        # Rover-to-camera offset in rover frame
        cam_ctr = self.cahvor_center
        
        # Rover-to-camera offset in ECEF
        ecef_frame  = self.target_frame_id        
        rover_frame = self.final_inst_frame
        frame_chain = self.frame_chain
        rover2ecef_rotation = \
          frame_chain.compute_rotation(rover_frame, ecef_frame)
        cam_ctr = rover2ecef_rotation.apply_at([cam_ctr], times)[0]

        # Go from rover position to camera position
        positions[0] += cam_ctr

        if self._props.get("landed", False):
        if self._props.get("landed", False):
          positions = np.array([[0, 0, 0]] * len(times))
          positions = np.array([[0, 0, 0]] * len(times))
          velocities = np.array([[0, 0, 0]] * len(times))
          velocities = np.array([[0, 0, 0]] * len(times))
        
        return positions, velocities, times
        return positions, velocities, times


    def compute_h_c(self):
    def compute_h_c(self):
        """
        """
        Computes the h_c element of a cahvor model for the conversion
        Computes the h_c element of a cahvor model for the conversion
        to a photogrametric model
        to a photogrammetric model


        Returns
        Returns
        -------
        -------
@@ -418,7 +450,7 @@ class Cahvor():
    def compute_h_s(self):
    def compute_h_s(self):
        """
        """
        Computes the h_s element of a cahvor model for the conversion
        Computes the h_s element of a cahvor model for the conversion
        to a photogrametric model
        to a photogrammetric model


        Returns
        Returns
        -------
        -------
@@ -430,7 +462,7 @@ class Cahvor():
    def compute_v_c(self):
    def compute_v_c(self):
        """
        """
        Computes the v_c element of a cahvor model for the conversion
        Computes the v_c element of a cahvor model for the conversion
        to a photogrametric model
        to a photogrammetric model


        Returns
        Returns
        -------
        -------
@@ -442,7 +474,7 @@ class Cahvor():
    def compute_v_s(self):
    def compute_v_s(self):
        """
        """
        Computes the v_s element of a cahvor model for the conversion
        Computes the v_s element of a cahvor model for the conversion
        to a photogrametric model
        to a photogrammetric model


        Returns
        Returns
        -------
        -------
@@ -474,6 +506,18 @@ class Cahvor():
              self._cahvor_rotation_matrix = np.array([H_prime, V_prime, self.cahvor_camera_dict['A']])
              self._cahvor_rotation_matrix = np.array([H_prime, V_prime, self.cahvor_camera_dict['A']])
        return self._cahvor_rotation_matrix
        return self._cahvor_rotation_matrix


    @property
    def cahvor_center(self):
        """
        Computes the cahvor center for the sensor relative to the rover frame

        Returns
        -------
        : array
          Cahvor center as a 1D numpy array
        """
        return self.cahvor_camera_dict['C']  
    
    @property
    @property
    def frame_chain(self):
    def frame_chain(self):
        """
        """
@@ -566,6 +610,6 @@ class Cahvor():
        Returns
        Returns
        -------
        -------
        : float
        : float
          Focal length of a cahvor model instrument
          Pixel size of a cahvor model instrument
        """
        """
        return self.focal_length/self.compute_h_s()
        return -self.focal_length/self.compute_h_s()
+1 −1
Original line number Original line Diff line number Diff line
@@ -205,7 +205,7 @@ class CassiniIssIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, RadialDis
        """
        """
        NAC uses multiple filter pairs, each filter combination has a different focal length.
        NAC uses multiple filter pairs, each filter combination has a different focal length.
        NAIF's Cassini kernels do not contain focal lengths for NAC filters and
        NAIF's Cassini kernels do not contain focal lengths for NAC filters and
        so we aquired updated NAC filter data from ISIS's IAK kernel.
        so we acquired updated NAC filter data from ISIS's IAK kernel.


        """
        """
        # default focal defined by IAK kernel
        # default focal defined by IAK kernel
+2 −2
Original line number Original line Diff line number Diff line
@@ -102,7 +102,7 @@ class LroLrocNacPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driv
    @property
    @property
    def light_time_correction(self):
    def light_time_correction(self):
        """
        """
        Returns the type of light time correction and abberation correction to
        Returns the type of light time correction and aberration correction to
        use in NAIF calls.
        use in NAIF calls.


        LROC is specifically set to not use light time correction because it is
        LROC is specifically set to not use light time correction because it is
@@ -112,7 +112,7 @@ class LroLrocNacPds3LabelNaifSpiceDriver(LineScanner, NaifSpice, Pds3Label, Driv
        Returns
        Returns
        -------
        -------
        : str
        : str
          The light time and abberation correction string for use in NAIF calls.
          The light time and aberration correction string for use in NAIF calls.
          See https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/abcorr.html
          See https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/abcorr.html
          for the different options available.
          for the different options available.
        """
        """
+77 −12
Original line number Original line Diff line number Diff line
@@ -42,10 +42,28 @@ class MslMastcamPds3NaifSpiceDriver(Cahvor, Framer, Pds3Label, NaifSpice, Cahvor
        """
        """
        lookup = {
        lookup = {
          "MAST_RIGHT": 'MASTCAM_RIGHT',
          "MAST_RIGHT": 'MASTCAM_RIGHT',
          "MAST_LEFT": 'MASTCAM_LEFT'
          "MAST_LEFT": 'MASTCAM_LEFT',
          "NAV_RIGHT_B": 'NAVCAM_RIGHT_B',
          "NAV_LEFT_B": 'NAVCAM_LEFT_B'
        }
        }
        return self.instrument_host_id + "_" + lookup[super().instrument_id]
        return self.instrument_host_id + "_" + lookup[super().instrument_id]


    @property
    def is_navcam(self):
        """
        Returns True if the camera is a nav cam, False otherwise.
        Need to handle nav cam differently as its focal length
        cannot be looked up in the spice data. Use instead
        a focal length in pixels computed from the CAHVOR model, 
        and a pixel size of 1.
        
        Returns
        -------
        : bool
          True if the camera is a nav cam, False otherwise
        """
        return 'NAVCAM' in self.instrument_id
        
    @property
    @property
    def cahvor_camera_dict(self):
    def cahvor_camera_dict(self):
        """
        """
@@ -72,14 +90,14 @@ class MslMastcamPds3NaifSpiceDriver(Cahvor, Framer, Pds3Label, NaifSpice, Cahvor
    @property
    @property
    def final_inst_frame(self):
    def final_inst_frame(self):
        """
        """
        Defines MSLs last naif frame before the cahvor model frame
        Defines the rover frame, relative to which the MSL cahvor camera is defined


        Returns
        Returns
        -------
        -------
        : int
        : int
          Naif frame code for MSL_RSM_HEAD
          Naif frame code for MSL_ROVER
        """
        """
        return spice.bods2c("MSL_RSM_HEAD")
        return spice.bods2c("MSL_ROVER")


    @property
    @property
    def sensor_frame_id(self):
    def sensor_frame_id(self):
@@ -108,10 +126,7 @@ class MslMastcamPds3NaifSpiceDriver(Cahvor, Framer, Pds3Label, NaifSpice, Cahvor
        : list<double>
        : list<double>
          focal plane to detector lines
          focal plane to detector lines
        """
        """
        if self._props.get("landed", False):
        return [0, 0, -1/self.pixel_size]
        return [0, 0, -1/self.pixel_size]
        else:
            return [0, 0, 1/self.pixel_size]
    
    
    @property
    @property
    def focal2pixel_samples(self):
    def focal2pixel_samples(self):
@@ -123,9 +138,6 @@ class MslMastcamPds3NaifSpiceDriver(Cahvor, Framer, Pds3Label, NaifSpice, Cahvor
        : list<double>
        : list<double>
          focal plane to detector samples
          focal plane to detector samples
        """
        """
        if (self._props.get("nadir", False)):
            return [0, 1/self.pixel_size, 0]
        else:
        return [0, -1/self.pixel_size, 0]
        return [0, -1/self.pixel_size, 0]


    @property
    @property
@@ -137,3 +149,56 @@ class MslMastcamPds3NaifSpiceDriver(Cahvor, Framer, Pds3Label, NaifSpice, Cahvor
          ISIS sensor model version
          ISIS sensor model version
        """
        """
        return 1
        return 1

    @property
    def light_time_correction(self):
        """
        Returns the type of light time correction and aberration correction to
        use in NAIF calls.

        For MSL using such a correction returns wrong results, so turn it off.
        
        Returns
        -------
        : str
          The light time and aberration correction string for use in NAIF calls.
          See https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/abcorr.html
          for the different options available.
        """
        return 'NONE'
        
    @property
    def focal_length(self):
        """
        Returns the focal length of the sensor with a negative sign.
        This was tested to work with MSL mast and nav cams. 

        Returns
        -------
        : float
          focal length
        """
        if self.is_navcam:
            # Focal length in pixel as computed for a cahvor model.
            # See is_navcam() for an explanation.
            return -(self.compute_h_s() + self.compute_v_s())/2.0
        
        # For mast cam    
        return -super().focal_length 

    @property
    def pixel_size(self):
        """
        Returns the pixel size. 

        Returns
        -------
        : float
          pixel size
        """
        if self.is_navcam:
            # See is_navcam() for an explanation.
            return 1.0
            
        # For mast cam    
        return super().pixel_size 
Loading