diff --git a/include/usgscsm/Distortion.h b/include/usgscsm/Distortion.h
index b70859b9d24d7278bc88e75674b7dc7415d9a499..990f513617f0beda9ebd431719e9e02ce164477d 100644
--- a/include/usgscsm/Distortion.h
+++ b/include/usgscsm/Distortion.h
@@ -6,7 +6,7 @@
 #include <tuple>
 #include <vector>
 
-enum DistortionType { RADIAL, TRANSVERSE, KAGUYALISM, DAWNFC, LROLROCNAC };
+enum DistortionType { RADIAL, TRANSVERSE, KAGUYALISM, DAWNFC, LROLROCNAC, CAHVOR };
 
 // Transverse Distortion
 void distortionJacobian(double x, double y, double *jacobian,
diff --git a/src/Distortion.cpp b/src/Distortion.cpp
index 15803b672ea423267508625d4e71a42eea531671..5c08ed6b6ee1da0b264d689d91b5087b7591967f 100644
--- a/src/Distortion.cpp
+++ b/src/Distortion.cpp
@@ -297,6 +297,28 @@ void removeDistortion(double dx, double dy, double &ux, double &uy,
 
       return;
     } break;
+
+    // Compute undistorted focal plane coordinate given a distorted
+    // coordinate set and the distortion coefficients along with an
+    // x, and y offset as the fourth and fifth element
+    case CAHVOR:
+    {
+      double shiftedDx = dx - opticalDistCoeffs[3];
+      double shiftedDy = dy - opticalDistCoeffs[4];
+      double rr = shiftedDx * shiftedDx + shiftedDy * shiftedDy;
+
+      if (rr > tolerance)
+      {
+        double dr = opticalDistCoeffs[0] +
+                    (rr * (opticalDistCoeffs[1] + rr * opticalDistCoeffs[2]));
+
+        ux = shiftedDx * (1.0 - dr);
+        uy = shiftedDy * (1.0 - dr);
+        ux += opticalDistCoeffs[3];
+        uy += opticalDistCoeffs[4];
+      }
+    }
+    break;
   }
 }
 
@@ -519,5 +541,64 @@ void applyDistortion(double ux, double uy, double &dx, double &dy,
 
       return;
     } break;
+
+    // Compute undistorted focal plane coordinate given a distorted
+    // focal plane coordinate. This case works by iteratively adding distortion
+    // until the new distorted point, r, undistorts to within a tolerance of the
+    // original point, rp. Also applies an initial offset with an
+    // x, and y offset as the fourth and fifth element
+    // This is untested manually
+    case CAHVOR:
+    {
+      double shiftedUx = ux - opticalDistCoeffs[3];
+      double shiftedUy = uy - opticalDistCoeffs[4];
+      double rp2 = (ux * ux) + (uy * uy);
+
+      if (rp2 > tolerance)
+      {
+        double rp = sqrt(rp2);
+        // Compute first fractional distortion using rp
+        double drOverR =
+            opticalDistCoeffs[0] +
+            (rp2 * (opticalDistCoeffs[1] + (rp2 * opticalDistCoeffs[2])));
+
+        // Compute first distorted point estimate, r
+        double r = rp + (drOverR * rp);
+        double r_prev, r2_prev;
+        int iteration = 0;
+
+        do
+        {
+          // Don't get in an end-less loop.  This algorithm should
+          // converge quickly.  If not then we are probably way outside
+          // of the focal plane.  Just set the distorted position to the
+          // undistorted position. Also, make sure the focal plane is less
+          // than 1km, it is unreasonable for it to grow larger than that.
+          if (iteration >= 20 || r > 1E9)
+          {
+            drOverR = 0.0;
+            break;
+          }
+
+          r_prev = r;
+          r2_prev = r * r;
+
+          // Compute new fractional distortion:
+          drOverR = opticalDistCoeffs[0] +
+                    (r2_prev *
+                     (opticalDistCoeffs[1] + (r2_prev * opticalDistCoeffs[2])));
+
+          // Compute new estimate of r
+          r = rp + (drOverR * r_prev);
+          iteration++;
+        } while (fabs(r - r_prev) > desiredPrecision);
+
+        dx = ux / (1.0 - drOverR);
+        dy = uy / (1.0 - drOverR);
+        dx += opticalDistCoeffs[3];
+        dy += opticalDistCoeffs[4];
+      }
+    }
+    break;
   }
 }
diff --git a/src/UsgsAstroFrameSensorModel.cpp b/src/UsgsAstroFrameSensorModel.cpp
index f2548ae8430cf5841ee919b1345934c87823e8a4..03bb386826bc2043fd99126c29788b5994f77082 100644
--- a/src/UsgsAstroFrameSensorModel.cpp
+++ b/src/UsgsAstroFrameSensorModel.cpp
@@ -321,7 +321,7 @@ csm::EcefLocus UsgsAstroFrameSensorModel::imageToProximateImagingLocus(
     csm::WarningList *warnings) const {
   MESSAGE_LOG(
       spdlog::level::info,
-      "Computing imageToProximateImagingLocus(No ground) for point {}, {}, {}, "
+      "Computing imageToProximateImagingLocus(No ground) for point {}, {}, "
       "with desired precision {}",
       imagePt.line, imagePt.samp, desiredPrecision);
 
@@ -362,7 +362,7 @@ csm::EcefLocus UsgsAstroFrameSensorModel::imageToRemoteImagingLocus(
     double *achievedPrecision, csm::WarningList *warnings) const {
   MESSAGE_LOG(
       spdlog::level::info,
-      "Computing imageToProximateImagingLocus for {}, {}, {}, with desired "
+      "Computing imageToRemoteImagingLocus for {}, {} with desired "
       "precision {}",
       imagePt.line, imagePt.samp, desiredPrecision);
   // Find the line,sample on the focal plane (mm)
@@ -373,15 +373,30 @@ csm::EcefLocus UsgsAstroFrameSensorModel::imageToRemoteImagingLocus(
       m_startingDetectorLine, &m_iTransS[0], &m_iTransL[0], focalPlaneX,
       focalPlaneY);
 
+  MESSAGE_LOG(
+      spdlog::level::trace,
+      "Found focalPlaneX: {}, and focalPlaneY: {}",
+      focalPlaneX, focalPlaneY);
+      
   // Distort
   double undistortedFocalPlaneX, undistortedFocalPlaneY;
   removeDistortion(focalPlaneX, focalPlaneY, undistortedFocalPlaneX,
                    undistortedFocalPlaneY, m_opticalDistCoeffs,
                    m_distortionType);
 
+  MESSAGE_LOG(
+      spdlog::level::trace,
+      "Found undistortedFocalPlaneX: {}, and undistortedFocalPlaneY: {}",
+      undistortedFocalPlaneX, undistortedFocalPlaneY);
+
   // Get rotation matrix and transform to a body-fixed frame
   double m[3][3];
   calcRotationMatrix(m);
+  MESSAGE_LOG(
+      spdlog::level::trace,
+      "Calculated rotation matrix [{}, {}, {}], [{}, {}, {}], [{}, {}, {}]",
+      m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1],
+      m[2][2]);
   std::vector<double> lookC{undistortedFocalPlaneX, undistortedFocalPlaneY,
                             m_focalLength};
   std::vector<double> lookB{
@@ -1250,6 +1265,7 @@ std::string UsgsAstroFrameSensorModel::constructStateFromIsd(
   // We don't pass the pixel to focal plane transformation so invert the
   // focal plane to pixel transformation
   try {
+    // "focal2pixel_lines":[0,136.4988453771169,0],"focal2pixel_samples":[136.4988453771169,0,0]
     double determinant = state["m_iTransL"][1].get<double>() *
                              state["m_iTransS"][2].get<double>() -
                          state["m_iTransL"][2].get<double>() *
diff --git a/src/Utilities.cpp b/src/Utilities.cpp
index 5391b2d340946bb49b12135e2f3864f26a46b0a2..14ed72ee316e19b8583db27d2de3826557616ce2 100644
--- a/src/Utilities.cpp
+++ b/src/Utilities.cpp
@@ -1053,6 +1053,8 @@ DistortionType getDistortionModel(int aleDistortionModel,
       return DistortionType::DAWNFC;
     } else if (aleDistortionType == ale::DistortionType::LROLROCNAC) {
       return DistortionType::LROLROCNAC;
+    }else if (aleDistortionType == ale::DistortionType::CAHVOR) {
+      return DistortionType::CAHVOR;
     }
   } catch (...) {
     if (list) {
@@ -1193,6 +1195,24 @@ std::vector<double> getDistortionCoeffs(json isd, csm::WarningList *list) {
         coefficients = std::vector<double>(1, 0.0);
       }
     } break;
+    case DistortionType::CAHVOR: {
+      try {
+        coefficients = isd.at("optical_distortion")
+                           .at("cahvor")
+                           .at("coefficients")
+                           .get<std::vector<double>>();
+
+        return coefficients;
+      } catch (...) {
+        if (list) {
+          list->push_back(csm::Warning(
+              csm::Warning::DATA_NOT_AVAILABLE,
+              "Could not parse the radial distortion model coefficients.",
+              "Utilities::getDistortion()"));
+        }
+        coefficients = std::vector<double>(6, 0.0);
+      }
+    } break;
   }
   if (list) {
     list->push_back(