Unverified Commit 005f5c48 authored by Jesse Mapel's avatar Jesse Mapel Committed by GitHub
Browse files

New Sensor Wrappers and Sensor/Camera Vector Math (#4980)



* Initial SensorUtils hooks

* Initial SensorUtils

* SensorUtil wrappers

* Illuminator wrapper test

* Initial replacement

* Added IsisShape tests

* Changed Sensor to use new functions internally

* Moved functions in camera to SensorUtils math

* CsmSensor tests

* Missing CSM wrapper

* Final wrapper tests

* Updated tests for new angles

* Docs

* Wrapper docs

* Modified so each band has its own histogram

* Fixed local ground to sensor vec

* Reverted test changes

* removed cout

Co-authored-by: default avatarssides <ssides@usgs.gov>
parent 7dc7472e
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
cmake_minimum_required(VERSION 3.10)
project(sensorutilities VERSION 0.0.1 DESCRIPTION "SensorUtilities library")

set(CMAKE_CXX_STANDARD 11)

include(GNUInstallDirs)

set(default_build_type "Release")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
  set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
      STRING "Choose the type of build." FORCE)
endif()

set(SENSOR_UTILITIES_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
set(SENSOR_UTILITIES_INSTALL_INCLUDE_DIR "include/sensorutilities")
set(SENSOR_UTILITIES_HEADER_FILES "${SENSOR_UTILITIES_INCLUDE_DIR}/SensorUtilities.h"
                                  "${SENSOR_UTILITIES_INCLUDE_DIR}/MathUtils.h")

add_library(sensorutilities SHARED
            "${CMAKE_CURRENT_SOURCE_DIR}/src/MathUtils.cpp"
            "${CMAKE_CURRENT_SOURCE_DIR}/src/SensorUtilities.cpp")

target_include_directories(sensorutilities
                           PUBLIC
                           $<BUILD_INTERFACE:${SENSOR_UTILITIES_INCLUDE_DIR}>
                           $<INSTALL_INTERFACE:include>)

install(FILES ${SENSOR_UTILITIES_HEADER_FILES} DESTINATION ${SENSOR_UTILITIES_INSTALL_INCLUDE_DIR})
install(TARGETS sensorutilities
        EXPORT sensorutilitiesConfig
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        INCLUDES DESTINATION include)
export(TARGETS sensorutilities
       NAMESPACE sensorutilities::
       FILE "${CMAKE_CURRENT_BINARY_DIR}/sensorutilitiesConfig.cmake")
install(EXPORT sensorutilitiesConfig
        NAMESPACE sensorutilities::
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME})


option (SENSOR_UTILITIES_BUILD_TESTS "Build the tests for the SensorUtilities Library" ON)

if(SENSOR_UTILITIES_BUILD_TESTS)

  enable_testing()

  add_executable(SensorUtilitiesTests
                 "${CMAKE_CURRENT_SOURCE_DIR}/tests/MathUtilsTests.cpp"
                 "${CMAKE_CURRENT_SOURCE_DIR}/tests/SensorUtilitiesTests.cpp")

  target_link_libraries(SensorUtilitiesTests
                        gmock_main
                        sensorutilities)

  include(GoogleTest)
  gtest_discover_tests(SensorUtilitiesTests
                       TEST_PREFIX SensorUtilities.)
else()
  message(STATUS "Skipping Tests")
endif()
 No newline at end of file
+155 −0
Original line number Diff line number Diff line
#ifndef MathUtils_H
#define MathUtils_H

#include <vector>

namespace SensorUtilities {

  /**
   * Structure for a 2-dimensional spherical ground point.
   * Latitude and longitude are in radians.
   * Longitude is planeto-centric, positive east, and in [-pi, pi].
   */
  struct GroundPt2D {
    double lat;
    double lon;
  };


  /**
   * Structure for a 3-dimensional spherical ground point.
   * Latitude and longitude are in radians.
   * Longitude is planeto-centric, positive east, and in [-pi, pi].
   * Radius is in meters.
   */
  struct GroundPt3D {
    double lat;
    double lon;
    double radius;
  };


  /**
   * Structure for a point in an image.
   * The line and sample origin is the upper-left corner at (0, 0).
   * The first band in the image is 0.
   */
  struct ImagePt {
    double line;
    double sample;
    int band;
  };


  /**
   * Structure for a 3-dimensional rectangular point or vector.
   * Distances are in meters.
   */
  struct Vec {
    double x;
    double y;
    double z;

    /**
     * Construct a vector from 3 values
     */
    Vec(double a, double b, double c);

    /**
     * Construct a vector from an array with at least 3 values.
     * The data is copied into the structure.
     */
    Vec(const double data[3]);

    /**
     * Create a std::vector from the structure.
     * The data in the std:vector is a copy.
     */
    operator std::vector<double>() const;
  };


  bool operator==(const GroundPt2D& lhs, const GroundPt2D& rhs);


  bool operator==(const GroundPt3D& lhs, const GroundPt3D& rhs);


  bool operator==(const ImagePt& lhs, const ImagePt& rhs);


  bool operator==(const Vec& lhs, const Vec& rhs);


  Vec operator+(const Vec& lhs, const Vec& rhs);


  Vec operator-(const Vec& lhs, const Vec& rhs);


  /**
   * Compute the separation angle between the vectors defined by three points.
   * The separation angle is the angle inscribed by the points
   * A, B, and C as follows:
   *
   *    A
   *   /
   *  /
   * B - - - C
   *
   * @param aPt The first point
   * @param bPt The middle point
   * @param cPt The second point
   *
   * @return The separation angle in radians between 0 and pi
   */
  double sepAngle(Vec aPt, Vec bPt, Vec cPt);


  /**
   * Compute the separation angle between two vectors
   *
   * @param aVec The first vector
   * @param bVec The second vector
   *
   * @return The separation angle in radians between 0 and pi
   */
  double sepAngle(Vec aVec, Vec bVec);


  /**
   * Compute the magnitude of a vector
   */
  double magnitude(Vec vec);


  /**
   * Compute the distance between two points in 3d space
   */
  double distance(Vec start, Vec stop);


  /**
   * Convert spherical coordinates to rectangular coordinates
   *
   * @param spherical The spherical coordinate as geocentric latitude, longitude, radius
   *
   * @return The rectangular coordinate as x, y, z
   */
   Vec sphericalToRect(GroundPt3D spherical);


  /**
   * Convert rectangular coordinates to spherical coordinates.
   * Returns 0, 0, 0 if the input is the zero vector.
   *
   * @param rectangular The rectangular coordinate as x, y, z
   *
   * @return The spherical coordinate as geocentric latitude, longitude, radius
   */
   GroundPt3D rectToSpherical(Vec rectangular);

}

#endif
+179 −0
Original line number Diff line number Diff line
#ifndef SensorUtilities_H
#define SensorUtilities_H


#include <vector>

#include "MathUtils.h"


namespace SensorUtilities {


  /**
   * Structure for storing the state of an observer at a specific image coordinate
   * and time.
   */
  struct ObserverState {
    // The look vector for the image coordinate in object space
    Vec lookVec;
    // The look vector for the image coordinate in the universal reference frame
    Vec j2000LookVec;
    // The position of the observer in object space
    Vec sensorPos;
    // The time that the observer state exists at in ephemeris seconds
    double time;
    // The image coordinate that was captured at the time
    ImagePt imagePoint;
  };


  /**
   * Structure for storing an intersection with a surface.
   */
  struct Intersection {
    Vec groundPt;
    Vec normal;
  };


  /**
   * Interface for sensors.
   * Implementaions of this interface are responsible for operating in both object
   * space and the universal reference frame.
   */
  class Sensor {
    public:
      /**
       * Get the observer state at a given image coordinate.
       */
      virtual ObserverState getState(const ImagePt &imagePoint) = 0;

      /**
       * Get the observer state that observers a given ground point.
       */
      virtual ObserverState getState(const GroundPt3D &groundPt) = 0;
  };


  /**
   * Interface for surface models.
   * Implementations of this interface operate in object space.
   */
  class Shape {
    public:
      /**
       * Intersect a vector with the surface model.
       *
       * @param sensorPos The starting point of the vector to intersect
       * @param lookVec The direction component of the vector. This may or may not be normalized.
       * @param computeLocalNormal If the more accurate local normal should be computed instead of the
       *                           potentially faster ellipsoid normal.
       */
      virtual Intersection intersect(const Vec &sensorPos, const Vec &lookVec, bool computeLocalNormal=true) = 0;
  };


  /**
   * Interface for the location of the illumination source.
   * Primarily this will be the location of the sun.
   * Implementations of this interface operate in object space.
   */
  class Illuminator {
    public:
      /**
       * Get the position for the illumination source at a given time.
       */
      virtual Vec position(double time) = 0;
  };


  /**
   * Compute the phase angle at an image point.
   * The phase angle is the separation angle between the vector from the ground point to the
   * illuminator and the vector from the ground point to the sensor.
   *
   * @return The phase angle in radians
   */
  double phaseAngle(const ImagePt &imagePoint, Sensor *sensor, Shape *shape, Illuminator *illuminator);


  /**
   * Compute the emission angle at an image point.
   * The emission angle is the separation angle between the surface normal and the vector from
   * the ground point to the sensor.
   *
   * @return The emission angle in radians
   */
  double emissionAngle(const ImagePt &imagePoint, Sensor *sensor, Shape *shape);


  /**
   * Compute the emission angle at an image point using the ellipsoid surface normal.
   * Computing an ellipsoid surface normal is much faster than computing a local
   * surface normal but less precise. The exact differences will depend upon what type
   * of shape you use.
   *
   * @return The emission angle in radians
   */
  double ellipsoidEmissionAngle(const ImagePt &imagePoint, Sensor *sensor, Shape *shape);


  /**
   * Compute the distance from a ground point to an illuminator.
   *
   * @return The distance to the illuminator in meters
   */
  double illuminationDistance(const ImagePt &imagePoint, Sensor *sensor, Shape *shape, Illuminator *illuminator);


  /**
   * Compute the latitude and longitude on the body below the sensor
   * when an image coordinate was observed.
   */
  GroundPt2D subSpacecraftPoint(const ImagePt &imagePoint, Sensor *sensor);


  /**
   * Compute the point on the body below the sensor when an image coordinate was observed.
   */
  Vec subSpacecraftPoint(const ImagePt &imagePoint, Sensor *sensor, Shape *shape);


  /**
   * Compute the latitude and longitude on the body below the illuminator
   * when an image coordinate was observed.
   */
  GroundPt2D subSolarPoint(const ImagePt &imagePoint, Sensor *sensor, Illuminator *illuminator);


  /**
   * Compute the point on the body below the illuminator when an image coordinate was observed.
   */
  Vec subSolarPoint(const ImagePt &imagePoint, Sensor *sensor, Illuminator *illuminator, Shape *shape);


  /**
   * Compute the local radius of the ground point observed at an image coordinate.
   *
   * @return The local radius in meters
   */
  double localRadius(const ImagePt &imagePoint, Sensor *sensor, Shape *shape);


  /**
   * Compute the local radius of a shape at a latitude and longitude
   *
   * @param groundPt The latitude and longitude
   * @param shape The shape to compute the local radius of
   * @param maxRadius The maximum radius of the shape. This only needs to be greater than the true
   *                  maximum radius, but results may be more precise if it's closer to the
   *                  true maximum radius.
   *
   * @return The local radius in meters
   */
  double localRadius(const GroundPt2D &groundPt, Shape *shape, double maxRadius=1e9);
}

#endif
+11 −0
Original line number Diff line number Diff line
cmake_minimum_required(VERSION 3.10)
project(installtest VERSION 1.0.0 DESCRIPTION "Installation test for SensorUtilities library")

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE Release)

find_package(sensorutilities REQUIRED)

add_executable(installtest main.cpp)

target_link_libraries(installtest PUBLIC sensorutilities::sensorutilities)
 No newline at end of file
+8 −0
Original line number Diff line number Diff line
#include <vector>

#include "sensorutilities/MathUtils.h"

int main() {
  double magnitude = SensorUtilities::magnitude({1.0, 0.0, 0.0});
  return 0;
}
 No newline at end of file
Loading