From 80aa1ea6b91c781f75f987ee0c014e46b7976142 Mon Sep 17 00:00:00 2001
From: Oleg Alexandrov <oleg.alexandrov@gmail.com>
Date: Thu, 21 Apr 2022 12:41:29 -0700
Subject: [PATCH] Add the tool usgscsm_cam_test (#373)

* Add usgscsm_cam_test tool

* .gitignore: Do not ignore bin as there will be an executable there

* Flesh out a bit the proposed test tool

* usgscsm_cam_test: Finish loading functionality

* usgscsm_cam_test: Print note of failure if could not load a model.

* usgscsm_cam_test: Use the more generic CSM approach

* Add a test for the test program

* Move test
---
 .gitignore              |  3 --
 CMakeLists.txt          |  6 ++-
 bin/usgscsm_cam_test.cc | 86 +++++++++++++++++++++++++++++++++++++++++
 tests/CMakeLists.txt    |  5 +++
 4 files changed, 96 insertions(+), 4 deletions(-)
 create mode 100644 bin/usgscsm_cam_test.cc

diff --git a/.gitignore b/.gitignore
index e9e8e08..0018c18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,9 +6,6 @@ include/csm/*
 # iPython checkpoint items
 .ipynb_checkpoints
 
-# Ignore any executables
-bin/*
-
 # Ignore any Mac stuff
 .DS_Store
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9e2a841..f8bf4c7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -80,10 +80,13 @@ target_link_libraries(usgscsm
                       ${ALE_TARGET}
                       nlohmann_json::nlohmann_json)
 
+add_executable(usgscsm_cam_test bin/usgscsm_cam_test.cc)
+target_link_libraries(usgscsm_cam_test
+    usgscsm)
 
 install(TARGETS usgscsm LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
 install(DIRECTORY ${USGSCSM_INCLUDE_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-
+install(TARGETS usgscsm_cam_test RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
 
 # Optional build tests
 option (USGSCSM_BUILD_TESTS "Build tests" ON)
@@ -100,4 +103,5 @@ if(USGSCSM_BUILD_TESTS)
   include(CTest)
   enable_testing()
   add_subdirectory(tests)
+
 endif()
diff --git a/bin/usgscsm_cam_test.cc b/bin/usgscsm_cam_test.cc
new file mode 100644
index 0000000..c624a52
--- /dev/null
+++ b/bin/usgscsm_cam_test.cc
@@ -0,0 +1,86 @@
+// A tool to perform some basic tests and operations on a CSM camera model.
+// 
+// Functionality:
+//
+// - Load a CSM model in ISD format.
+//
+// Future functionality:
+// 
+// - Test projecting rays from the camera to ground and vice-versa.
+// - Load a CSM model state (stored in a .json file, just like
+//   an ISD model).
+// - Ability to export a CSM model in ISD format to a CSM model state file. 
+
+#include <usgscsm/UsgsAstroPlugin.h>
+#include <csm/RasterGM.h>
+#include <UsgsAstroLsSensorModel.h>
+
+#include <iostream>
+int main(int argc, char **argv) {
+
+  if (argc != 2) {
+    std::cerr << "Usage: " << argv[0] << " <model file>" << std::endl;
+    return 1;
+  }
+
+  // This is needed to trigger loading libusgscsm.so. Otherwise 0
+  // plugins are detected.
+  UsgsAstroLsSensorModel lsModel;
+
+  // Load the isd
+  std::string model_file = argv[1];
+  csm::Isd isd(model_file);
+  std::cout << "Loading model: " << model_file << std::endl;
+  
+  // Check if loading the model worked
+  bool success = false;
+
+  std::shared_ptr<csm::RasterGM> model;
+  
+  // Try all detected plugins and models for each plugin
+  csm::PluginList plugins = csm::Plugin::getList();
+  for (auto iter = plugins.begin(); iter != plugins.end(); iter++) {
+    
+    const csm::Plugin* csm_plugin = (*iter);
+
+    std::cout << "Detected CSM plugin: " << csm_plugin->getPluginName()  << "\n";
+    // For each plugin, loop through the available models.
+    size_t num_models = csm_plugin->getNumModels();
+    std::cout << "Number of models for this plugin: " << num_models << "\n";
+    for (size_t i = 0; i < num_models; i++) {
+
+      std::string model_name = (*iter)->getModelName(i);
+
+      csm::WarningList* warnings = NULL;
+
+      if (csm_plugin->canModelBeConstructedFromISD(isd, model_name)) {
+
+        csm::Model *csm = csm_plugin->constructModelFromISD(isd, model_name, warnings);
+        csm::RasterGM *modelPtr = dynamic_cast<csm::RasterGM*>(csm);
+
+        if (modelPtr == NULL) {
+          std::cerr << "Could not load correctly a CSM model of type: "
+                    << model_name << "\n";
+          return 1;
+        } else {
+          // Assign it to a smart pointer which will handle its deallocation
+          model = std::shared_ptr<csm::RasterGM>(modelPtr);
+          success = true;
+          std::cout << "Loaded CSM model of type " << model_name
+                    << " from " << model_file << ".\n";
+        }
+      }
+    }
+  }
+  
+  if (!success) {
+    std::cerr << "Failed to load a CSM model from: " << model_file << ".\n";
+    return 1;
+  }
+
+  csm::ImageVector image_size = model->getImageSize();
+  std::cout << "Camera image rows and columns: "
+            << image_size.samp << ' ' << image_size.line << "\n";
+
+  return 0;
+}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index c107704..f28fd1c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -17,4 +17,9 @@ else()
     target_link_libraries(runCSMCameraModelTests usgscsm ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)
 endif()
 
+# Test the test_usgscsm_cam_test program
+add_test(NAME test_usgscsm_cam_test_linescan
+    COMMAND usgscsm_cam_test data/orbitalLineScan.json
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests)
+      
 gtest_discover_tests(runCSMCameraModelTests WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests)
-- 
GitLab