diff --git a/include/usgscsm/Distortion.h b/include/usgscsm/Distortion.h
index b324d4cc0c1445c0649a325669fb1e5b057ffc5b..c27eb39d3fb87118c1cc616acd0831177bd77510 100644
--- a/include/usgscsm/Distortion.h
+++ b/include/usgscsm/Distortion.h
@@ -10,9 +10,11 @@ enum DistortionType {
   RADIAL,
   TRANSVERSE,
   KAGUYATC,
-  DAWNFC
+  DAWNFC,
+  LROLROCNAC
 };
 
+
 // Transverse Distortion
 void distortionJacobian(double x, double y, double *jacobian,
                         const std::vector<double> opticalDistCoeffs);
diff --git a/src/Distortion.cpp b/src/Distortion.cpp
index 36ba65ef1384aa66c9c92e7637017615924c6cee..d39fe07c1cbcbeff3091741c120b4f2ea092d783 100644
--- a/src/Distortion.cpp
+++ b/src/Distortion.cpp
@@ -43,6 +43,7 @@ void distortionJacobian(double x, double y, double *jacobian,
   }
 }
 
+
 /**
  * @description Compute distorted focal plane (dx,dy) coordinate  given an undistorted focal
  * plane (ux,uy) coordinate. This uses the third order Taylor approximation to the
@@ -81,6 +82,7 @@ void computeTransverseDistortion(double ux, double uy, double &dx, double &dy,
   }
 }
 
+
 void removeDistortion(double dx, double dy, double &ux, double &uy,
                       const std::vector<double> opticalDistCoeffs,
                       DistortionType distortionType,
@@ -89,6 +91,7 @@ void removeDistortion(double dx, double dy, double &ux, double &uy,
   uy = dy;
 
   switch (distortionType) {
+
     // Compute undistorted focal plane coordinate given a distorted
     // coordinate set and the distortion coefficients
     case RADIAL: {
@@ -102,6 +105,7 @@ void removeDistortion(double dx, double dy, double &ux, double &uy,
       }
     }
     break;
+
     // Computes undistorted focal plane (x,y) coordinates given a distorted focal plane (x,y)
     // coordinate. The undistorted coordinates are solved for using the Newton-Raphson
     // method for root-finding if the distortionFunction method is invoked.
@@ -159,6 +163,8 @@ void removeDistortion(double dx, double dy, double &ux, double &uy,
       // number of iterations
     }
     break;
+
+    // KaguyaTC
     case KAGUYATC: {
       // Apply distortion correction
       // see: SEL_TC_V01.TI
@@ -201,6 +207,7 @@ void removeDistortion(double dx, double dy, double &ux, double &uy,
       uy = dy + dr_y;
     }
     break;
+
     // The dawn distortion model is "reversed" from other distortion models so
     // the remove function iteratively computes undistorted coordinates based on
     // the distorted coordinates, rather than iteratively computing distorted coordinates
@@ -243,7 +250,7 @@ void removeDistortion(double dx, double dy, double &ux, double &uy,
           return;
         }
       }
-      while(!done);
+      while(!done); 
 
       /****************************************************************************
       * Sucess ...
@@ -252,18 +259,41 @@ void removeDistortion(double dx, double dy, double &ux, double &uy,
       ux = guess_ux;
       uy = guess_uy;
     }
+    break;
+
+    // LROLROCNAC
+    case LROLROCNAC: {
+
+      if (opticalDistCoeffs.size() != 1) {
+        throw "Distortion coefficients for LRO LROC NAC must be of size 1, current size: " +  std::to_string(opticalDistCoeffs.size());
+      }
+
+      double dk1 = opticalDistCoeffs[0];
+
+      double den = 1 + dk1 * dy * dy;     // r = dy*dy = distance from the focal plane center
+      if (den == 0.0) {
+        throw "Unable to remove distortion for LRO LROC NAC. Focal plane position " + std::to_string(dy);
+      }
+
+      ux = dx;
+      uy = dy / den;
+
+      return;
+    }
+    break;
   }
 }
 
+
 void applyDistortion(double ux, double uy, double &dx, double &dy,
                      const std::vector<double> opticalDistCoeffs,
                      DistortionType distortionType,
-                     const double desiredPrecision, const double tolerance)
-{
+                     const double desiredPrecision, const double tolerance) {
   dx = ux;
   dy = uy;
 
   switch (distortionType) {
+
     // 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
@@ -312,6 +342,8 @@ void applyDistortion(double ux, double uy, double &dx, double &dy,
       computeTransverseDistortion(ux, uy, dx, dy, opticalDistCoeffs);
     }
     break;
+
+    // KaguyaTC
     case KAGUYATC: {
       if (opticalDistCoeffs.size() != 8) {
         throw "Distortion coefficients for Kaguya TC must be of size 8, got: " +  std::to_string(opticalDistCoeffs.size());
@@ -377,6 +409,7 @@ void applyDistortion(double ux, double uy, double &dx, double &dy,
       }
     }
     break;
+
     // The dawn distortion model is "reversed" from other distortion models so
     // the apply function computes distorted coordinates as a
     // fn(undistorted coordinates)
@@ -388,5 +421,73 @@ void applyDistortion(double ux, double uy, double &dx, double &dy,
       dx = ux * (1.0 + opticalDistCoeffs[0] * r2);
       dy = uy * (1.0 + opticalDistCoeffs[0] * r2);
     }
+    break;
+
+    // The LRO LROC NAC distortion model uses an iterative approach to go from 
+    // undistorted x,y to distorted x,y
+    // Algorithum adapted from ISIS3 LRONarrowAngleDistortionMap.cpp
+    case LROLROCNAC: {
+
+      double yt = uy;
+
+      double rr, dr;
+      double ydistorted;
+      double yprevious = 1000000.0;
+      double tolerance = 1.0e-10;
+
+      bool bConverged = false;
+
+      if (opticalDistCoeffs.size() != 1) {
+        throw "Distortion coefficients for LRO LROC NAC must be of size 1, current size: " +  std::to_string(opticalDistCoeffs.size());
+      }
+
+      double dk1 = opticalDistCoeffs[0];
+
+      // Owing to the odd distotion model employed in this senser if |y| is > 116.881145553046
+      // then there is no root to find.  Further, the greatest y that any measure on the sensor
+      // will acutally distort to is less than 20.  Thus, if any distorted measure is greater
+      // that that skip the iterations.  The points isn't in the cube, and exactly how far outside
+      // the cube is irrelevant.  Just let the camera model know its not in the cube....
+      if (fabs(uy) > 40) {  //if the point is way off the image.....
+        dx = ux;
+        dy = uy;
+        return;
+      }
+
+      // iterating to introduce distortion (in sample only)...
+      // we stop when the difference between distorted coordinate
+      // in successive iterations is at or below the given tolerance
+      for(int i = 0; i < 50; i++) {
+        rr = yt * yt;
+
+        //  dr is the radial distortion contribution
+        dr = 1.0 + dk1 * rr;
+
+        // distortion at the current sample location
+        yt = uy * dr;
+
+        // distorted sample
+        ydistorted = yt;
+
+        if (yt < -1e121)  //debug
+          break;  //debug
+
+        // check for convergence
+        if(fabs(yt - yprevious) <= tolerance) {
+          bConverged = true;
+          break;
+        }
+
+        yprevious = yt;
+      }
+      
+      if(bConverged) {
+        dx = ux;
+        dy = ydistorted;
+      }
+
+      return;
+    }
+    break;
   }
 }
diff --git a/src/Utilities.cpp b/src/Utilities.cpp
index c59103828d75c377218d650d897deba501031795..50d892f42b92569b7f785e1b79dfee461bfa0956 100644
--- a/src/Utilities.cpp
+++ b/src/Utilities.cpp
@@ -727,6 +727,7 @@ double getSemiMajorRadius(json isd, csm::WarningList *list) {
   return radius;
 }
 
+
 double getSemiMinorRadius(json isd, csm::WarningList *list) {
   double radius = 0.0;
   try {
@@ -747,8 +748,9 @@ double getSemiMinorRadius(json isd, csm::WarningList *list) {
   return radius;
 }
 
-// Gets the type of distortion model from the isd. If none is specified defaults
-// to transverse
+
+// Converts the distortion model name from the ISD (string) to the enumeration
+// type. Defaults to transverse
 DistortionType getDistortionModel(json isd, csm::WarningList *list) {
   try {
     json distoriton_subset = isd.at("optical_distortion");
@@ -769,6 +771,9 @@ DistortionType getDistortionModel(json isd, csm::WarningList *list) {
     else if (distortion.compare("dawnfc") == 0) {
       return DistortionType::DAWNFC;
     }
+    else if (distortion.compare("lrolrocnac") == 0) {
+      return DistortionType::LROLROCNAC;
+    }
   }
   catch (...) {
     if (list) {
@@ -877,6 +882,23 @@ std::vector<double> getDistortionCoeffs(json isd, csm::WarningList *list) {
       }
     }
     break;
+    case DistortionType::LROLROCNAC: {
+      try {
+        coefficients = isd.at("optical_distortion").at("lrolrocnac").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 lrolrocnac distortion model coefficients.",
+              "Utilities::getDistortion()"));
+        }
+        coefficients = std::vector<double>(1, 0.0);
+      }
+    }
+    break;
   }
   if (list) {
     list->push_back(
diff --git a/tests/DistortionTests.cpp b/tests/DistortionTests.cpp
index 299fd1591a0bb9bfcf5b56ec9d44995229f52a2b..3aa73c50dfc90747f6414bdbaf1c7b3adde45b77 100644
--- a/tests/DistortionTests.cpp
+++ b/tests/DistortionTests.cpp
@@ -214,6 +214,7 @@ TEST(KaguyaTc, testRemoveCoeffs) {
   EXPECT_NEAR(uy, 1 + 1 + 2.828427125 + 6 + 11.313708499, 1e-8);
 }
 
+
 TEST(KaguyaTc, testCoeffs) {
   csm::ImageCoord imagePt(1.0, 1.0);
 
@@ -235,6 +236,7 @@ TEST(KaguyaTc, testCoeffs) {
   EXPECT_NEAR(uy, 1.0, 1e-8);
 }
 
+
 TEST(KaguyaTc, testZeroCoeffs) {
   csm::ImageCoord imagePt(1.0, 1.0);
 
@@ -254,3 +256,62 @@ TEST(KaguyaTc, testZeroCoeffs) {
   ASSERT_DOUBLE_EQ(ux, 1.0);
   ASSERT_DOUBLE_EQ(uy, 1.0);
 }
+
+
+// Test for LRO LROC NAC
+TEST(LroLrocNac, testLastDetectorSample) {
+  double ux, uy, dx, dy;
+  double desiredPrecision = 0.0000001;
+  // Coeffs obtained from file: lro_lroc_v18.ti
+  std::vector<double> coeffs = {1.81E-5};
+
+  removeDistortion(0.0, 5064.0 / 2.0 * 0.007, ux, uy, coeffs,
+                  DistortionType::LROLROCNAC, desiredPrecision);
+
+  applyDistortion(ux, uy, dx, dy, coeffs,
+                  DistortionType::LROLROCNAC, desiredPrecision);
+
+  EXPECT_NEAR(dx, 0.0, 1e-8);
+  EXPECT_NEAR(dy, 17.724, 1e-8);
+  EXPECT_NEAR(ux, 0.0, 1e-8);
+  EXPECT_NEAR(uy, 17.6237922244, 1e-8);
+}
+
+
+TEST(LroLrocNac, testCoeffs) {
+  double ux, uy, dx, dy;
+  double desiredPrecision = 0.0000001;
+  // Coeff obtained from file: lro_lroc_v18.ti
+  std::vector<double> coeffs = {1.81E-5};
+
+  applyDistortion(0.0, 0.0, dx, dy, coeffs,
+                  DistortionType::LROLROCNAC, desiredPrecision);
+
+  removeDistortion(dx, dy, ux, uy, coeffs,
+                  DistortionType::LROLROCNAC, desiredPrecision);
+
+  EXPECT_NEAR(dx, 0.0, 1e-8);
+  EXPECT_NEAR(dy, 0.0, 1e-8);
+  EXPECT_NEAR(ux, 0.0, 1e-8);
+  EXPECT_NEAR(uy, 0.0, 1e-8);
+}
+
+
+TEST(LroLrocNac, testZeroCoeffs) {
+
+  double ux, uy, dx, dy;
+  double desiredPrecision = 0.0000001;
+  std::vector<double> coeffs = {0};
+
+  applyDistortion(0.0, 0.0, dx, dy, coeffs,
+                  DistortionType::LROLROCNAC, desiredPrecision);
+
+  removeDistortion(dx, dy, ux, uy, coeffs,
+                  DistortionType::LROLROCNAC, desiredPrecision);
+
+  ASSERT_DOUBLE_EQ(dx, 0.0);
+  ASSERT_DOUBLE_EQ(dy, 0.0);
+  ASSERT_DOUBLE_EQ(ux, 0.0);
+  ASSERT_DOUBLE_EQ(uy, 0.0);
+}
+