diff --git a/include/usgscsm/UsgsAstroFrameSensorModel.h b/include/usgscsm/UsgsAstroFrameSensorModel.h
index 575cc11ad511a5270ff5344e96bb30722e5ac493..b24d4ea62d15e67d57a03869450565d5eb76c4f8 100644
--- a/include/usgscsm/UsgsAstroFrameSensorModel.h
+++ b/include/usgscsm/UsgsAstroFrameSensorModel.h
@@ -34,8 +34,16 @@ class UsgsAstroFrameSensorModel : public csm::RasterGM,
       double *achievedPrecision = NULL,
       csm::WarningList *warnings = NULL) const;
 
+  static std::string getModelNameFromModelState(const std::string& model_state);
+
   std::string constructStateFromIsd(const std::string &jsonIsd,
                                     csm::WarningList *warnings);
+  
+  // Apply a rotation and translation to a state string. The effect is
+  // to transform the position and orientation of the camera in ECEF
+  // coordinates.
+  static void applyTransformToState(ale::Rotation const& r, ale::Vec3d const& t,
+                                    std::string& stateString);
   void reset();
 
   virtual csm::ImageCoordCovar groundToImage(
diff --git a/include/usgscsm/UsgsAstroSarSensorModel.h b/include/usgscsm/UsgsAstroSarSensorModel.h
index d5dac3f5620bba4c53f8255543e88b0733efd397..31d29bfe70e6b80fbfbf86d47a2c6e7e45e286ef 100644
--- a/include/usgscsm/UsgsAstroSarSensorModel.h
+++ b/include/usgscsm/UsgsAstroSarSensorModel.h
@@ -5,6 +5,8 @@
 #include <RasterGM.h>
 #include <SettableEllipsoid.h>
 
+#include "ale/Rotation.h"
+
 #include "spdlog/spdlog.h"
 
 class UsgsAstroSarSensorModel : public csm::RasterGM,
@@ -24,8 +26,14 @@ class UsgsAstroSarSensorModel : public csm::RasterGM,
   std::string constructStateFromIsd(const std::string imageSupportData,
                                     csm::WarningList* list);
 
-  std::string getModelNameFromModelState(const std::string& model_state);
+  static std::string getModelNameFromModelState(const std::string& model_state);
 
+  // Apply a rotation and translation to a state string. The effect is
+  // to transform the position and orientation of the camera in ECEF
+  // coordinates.
+  static void applyTransformToState(ale::Rotation const& r, ale::Vec3d const& t,
+                                    std::string& stateString);
+  
   virtual csm::ImageCoord groundToImage(
       const csm::EcefCoord& groundPt, double desiredPrecision = 0.001,
       double* achievedPrecision = NULL,
diff --git a/src/UsgsAstroFrameSensorModel.cpp b/src/UsgsAstroFrameSensorModel.cpp
index eb1fdbf8f399106d3b2f3f64309f4ccbe8787d7b..763af338ca1a9d792fee9fc3d7aa430042b72691 100644
--- a/src/UsgsAstroFrameSensorModel.cpp
+++ b/src/UsgsAstroFrameSensorModel.cpp
@@ -697,6 +697,32 @@ std::string UsgsAstroFrameSensorModel::getReferenceDateAndTime() const {
   return ephemTimeToCalendarTime(ephemTime);
 }
 
+std::string UsgsAstroFrameSensorModel::getModelNameFromModelState(
+    const std::string& model_state) {
+  // Parse the string to JSON
+  auto j = stateAsJson(model_state);
+  // If model name cannot be determined, return a blank string
+  std::string model_name;
+
+  if (j.find("m_modelName") != j.end()) {
+    model_name = j["m_modelName"];
+  } else {
+    csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
+    std::string aMessage = "No 'm_modelName' key in the model state object.";
+    std::string aFunction = "UsgsAstroFramePlugin::getModelNameFromModelState";
+    csm::Error csmErr(aErrorType, aMessage, aFunction);
+    throw(csmErr);
+  }
+  if (model_name != _SENSOR_MODEL_NAME) {
+    csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED;
+    std::string aMessage = "Sensor model not supported.";
+    std::string aFunction = "UsgsAstroFramePlugin::getModelNameFromModelState()";
+    csm::Error csmErr(aErrorType, aMessage, aFunction);
+    throw(csmErr);
+  }
+  return model_name;
+}
+
 std::string UsgsAstroFrameSensorModel::getModelState() const {
   MESSAGE_LOG("Dumping model state");
   json state = {
@@ -749,6 +775,56 @@ std::string UsgsAstroFrameSensorModel::getModelState() const {
   return stateString;
 }
 
+void UsgsAstroFrameSensorModel::applyTransformToState(ale::Rotation const& r, ale::Vec3d const& t,
+                                                      std::string& stateString) {
+
+  nlohmann::json j = stateAsJson(stateString);
+
+  // The vector having the rotation and translation from camera to
+  // ECEF
+  std::vector<double> currentParameterValue = j["m_currentParameterValue"];
+  
+  // Extract the quaternions from the frame camera, apply the
+  // rotation, and put them back.
+  std::vector<double> quaternions;
+  for (size_t it = 0; it < 4; it++)
+    quaternions.push_back(currentParameterValue[it + 3]);
+  applyRotationToQuatVec(r, quaternions);
+  for (size_t it = 0; it < 4; it++)
+    currentParameterValue[it + 3] = quaternions[it];
+  
+  // Extract the positions from the frame camera, apply to them the
+  // rotation and translation, and put them back.
+  std::vector<double> positions;
+  for (size_t it = 0; it < 3; it++)
+    positions.push_back(currentParameterValue[it]);
+  applyRotationTranslationToXyzVec(r, t, positions);
+  for (size_t it = 0; it < 3; it++)
+    currentParameterValue[it] = positions[it];
+
+  // Put the transformed vector back in the json state.
+  j["m_currentParameterValue"] = currentParameterValue;
+
+  // Apply rotation to velocities. The translation does not get
+  // applied.
+  std::vector<double> velocities = j["m_spacecraftVelocity"];
+  ale::Vec3d zero_t(0, 0, 0);
+  applyRotationTranslationToXyzVec(r, zero_t, velocities);
+  j["m_spacecraftVelocity"] = velocities;
+
+  // Apply the transform to the reference point.
+  std::vector<double> refPt = j["m_referencePointXyz"];
+  applyRotationTranslationToXyzVec(r, t, refPt);
+  j["m_referencePointXyz"] = refPt;
+
+  // We do not change the Sun position or velocity. The idea is that
+  // the Sun is so far, that minor camera adjustments won't affect
+  // where the Sun is.
+
+  // Update the state string
+  stateString = getModelNameFromModelState(stateString) + "\n" + j.dump(2);
+}
+
 bool UsgsAstroFrameSensorModel::isValidModelState(
     const std::string &stringState, csm::WarningList *warnings) {
   MESSAGE_LOG("Checking if model has valid state");
@@ -871,6 +947,19 @@ void UsgsAstroFrameSensorModel::replaceModelState(
         imageToGround(csm::ImageCoord(m_nLines / 2.0, m_nSamples / 2.0));
     m_currentParameterCovariance =
         state.at("m_currentParameterCovariance").get<std::vector<double>>();
+
+    // These are optional and may not exist in all state files
+    if (state.find("m_maxElevation") != state.end()) 
+      m_maxElevation = state.at("m_maxElevation").get<double>();
+    if (state.find("m_minElevation") != state.end()) 
+      m_minElevation = state.at("m_minElevation").get<double>();
+    if (state.find("m_originalHalfLines") != state.end()) 
+      m_originalHalfLines = state.at("m_originalHalfLines").get<double>();
+    if (state.find("m_originalHalfSamples") != state.end()) 
+      m_originalHalfSamples = state.at("m_originalHalfSamples").get<double>();
+    if (state.find("m_pixelPitch") != state.end()) 
+      m_pixelPitch = state.at("m_pixelPitch").get<double>();
+    
   } catch (std::out_of_range &e) {
     MESSAGE_LOG("State keywords required to generate sensor model missing: " +
                 std::string(e.what()) + "\nUsing model string: " + stringState +
@@ -1348,7 +1437,7 @@ void UsgsAstroFrameSensorModel::losEllipsoidIntersect(
   // If quadTerm is negative, the image ray does not
   // intersect the ellipsoid. Setting the quadTerm to
   // zero means solving for a point on the ray nearest
-  // the surface of the ellisoid.
+  // the surface of the ellipsoid.
 
   if (0.0 > quadTerm) {
     quadTerm = 0.0;
diff --git a/src/UsgsAstroLsSensorModel.cpp b/src/UsgsAstroLsSensorModel.cpp
index 208e47ba98cd7956bd2d4b6adbca3867f5036b59..bd1a7fb33eb7a26adf75a937072ab8fa76177c82 100644
--- a/src/UsgsAstroLsSensorModel.cpp
+++ b/src/UsgsAstroLsSensorModel.cpp
@@ -468,6 +468,11 @@ void UsgsAstroLsSensorModel::applyTransformToState(ale::Rotation const& r, ale::
   applyRotationTranslationToXyzVec(r, zero_t, velocities);
   j["m_velocities"] = velocities;
 
+  // Apply the transform to the reference point
+  std::vector<double> refPt = j["m_referencePointXyz"];
+  applyRotationTranslationToXyzVec(r, t, refPt);
+  j["m_referencePointXyz"] = refPt;
+
   // We do not change the Sun position or velocity. The idea is that
   // the Sun is so far, that minor camera adjustments won't affect
   // where the Sun is.
@@ -475,6 +480,7 @@ void UsgsAstroLsSensorModel::applyTransformToState(ale::Rotation const& r, ale::
   // Update the state string
   stateString = getModelNameFromModelState(stateString) + "\n" + j.dump(2);
 }
+
 //***************************************************************************
 // UsgsAstroLineScannerSensorModel::reset
 //***************************************************************************
diff --git a/src/UsgsAstroSarSensorModel.cpp b/src/UsgsAstroSarSensorModel.cpp
index fe1017fa5b8c97786bb72c93fa405f0801abcaa8..93b29d10107284e4e95f2a09e128c68d4231908d 100644
--- a/src/UsgsAstroSarSensorModel.cpp
+++ b/src/UsgsAstroSarSensorModel.cpp
@@ -208,7 +208,6 @@ string UsgsAstroSarSensorModel::constructStateFromIsd(
 
 string UsgsAstroSarSensorModel::getModelNameFromModelState(
     const string& model_state) {
-  MESSAGE_LOG("Getting model name from model state: {}", model_state);
   // Parse the string to JSON
   auto j = stateAsJson(model_state);
   // If model name cannot be determined, return a blank string
@@ -220,7 +219,6 @@ string UsgsAstroSarSensorModel::getModelNameFromModelState(
     csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE;
     string aMessage = "No 'm_modelName' key in the model state object.";
     string aFunction = "UsgsAstroSarSensorModel::getModelNameFromModelState";
-    MESSAGE_LOG(aMessage);
     csm::Error csmErr(aErrorType, aMessage, aFunction);
     throw(csmErr);
   }
@@ -228,7 +226,6 @@ string UsgsAstroSarSensorModel::getModelNameFromModelState(
     csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED;
     string aMessage = "Sensor model not supported.";
     string aFunction = "UsgsAstroSarSensorModel::getModelNameFromModelState()";
-    MESSAGE_LOG(aMessage);
     csm::Error csmErr(aErrorType, aMessage, aFunction);
     throw(csmErr);
   }
@@ -399,6 +396,40 @@ string UsgsAstroSarSensorModel::getModelState() const {
   return stateString;
 }
 
+//***************************************************************************
+// UsgsAstroSarSensorModel::applyTransformToState
+//***************************************************************************
+void UsgsAstroSarSensorModel::applyTransformToState(ale::Rotation const& r, ale::Vec3d const& t,
+                                                   std::string& stateString) {
+
+  nlohmann::json j = stateAsJson(stateString);
+
+  // Apply rotation and translation to positions
+  std::vector<double> positions = j["m_positions"].get<std::vector<double>>();
+  applyRotationTranslationToXyzVec(r, t, positions);
+  j["m_positions"] = positions;
+  
+  // Note that the SAR sensor does not have quaternions
+
+  // Apply rotation to velocities. The translation does not get applied.
+  ale::Vec3d zero_t(0, 0, 0);
+  std::vector<double> velocities = j["m_velocities"].get<std::vector<double>>();
+  applyRotationTranslationToXyzVec(r, zero_t, velocities);
+  j["m_velocities"] = velocities;
+
+  // Apply the transform to the reference point
+  std::vector<double> refPt = j["m_referencePointXyz"];
+  applyRotationTranslationToXyzVec(r, t, refPt);
+  j["m_referencePointXyz"] = refPt;
+
+  // We do not change the Sun position or velocity. The idea is that
+  // the Sun is so far, that minor camera adjustments won't affect
+  // where the Sun is.
+
+  // Update the state string
+  stateString = getModelNameFromModelState(stateString) + "\n" + j.dump(2);
+}
+
 csm::ImageCoord UsgsAstroSarSensorModel::groundToImage(
     const csm::EcefCoord& groundPt, double desiredPrecision,
     double* achievedPrecision, csm::WarningList* warnings) const {
diff --git a/src/Utilities.cpp b/src/Utilities.cpp
index 030e19a8cac6d10093d4e02313ed1be12bf62d1d..e0c552e8f1215baca337737e24c7a87579798c5f 100644
--- a/src/Utilities.cpp
+++ b/src/Utilities.cpp
@@ -55,7 +55,7 @@ void calculateRotationMatrixFromQuaternions(double q[4],
   rotationMatrix[8] = -q[0] * q[0] - q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
 }
 
-// Compue the distorted focal plane coordinate for a given image pixel
+// Compute the distorted focal plane coordinate for a given image pixel
 // in - line
 // in - sample
 // in - sampleOrigin - the origin of the ccd coordinate system relative to the
@@ -88,7 +88,7 @@ void computeDistortedFocalPlaneCoordinates(
   distortedY = p21 * t1 + p22 * t2;
 }
 
-// Compue the image pixel for a distorted focal plane coordinate
+// Compute the image pixel for a distorted focal plane coordinate
 // in - line
 // in - sample
 // in - sampleOrigin - the origin of the ccd coordinate system relative to the
diff --git a/tests/FrameCameraTests.cpp b/tests/FrameCameraTests.cpp
index 663a406e79f55bcf5f0f44dbdb920b0829f26381..535ff30aced20521f394612a9eb806852d630058 100644
--- a/tests/FrameCameraTests.cpp
+++ b/tests/FrameCameraTests.cpp
@@ -19,6 +19,19 @@ TEST_F(FrameSensorModel, State) {
   EXPECT_EQ(sensorModel->getModelState(), modelState);
 }
 
+// Apply the identity transform to a state
+TEST_F(FrameSensorModel, ApplyTransformToState) {
+  std::string modelState = sensorModel->getModelState();
+
+  ale::Rotation r; // identity rotation
+  ale::Vec3d t;    // zero translation
+
+  std::string modelState_out = modelState;
+  UsgsAstroFrameSensorModel::applyTransformToState(r, t, modelState_out);
+
+  EXPECT_EQ(modelState, modelState_out);
+}
+
 // centered and slightly off-center:
 TEST_F(FrameSensorModel, Center) {
   csm::ImageCoord imagePt(7.5, 7.5);
diff --git a/tests/SarTests.cpp b/tests/SarTests.cpp
index 71b0a0e087243b96b0620e4ca48d1b47e22f21ee..a7cf8bf8644f0946cfb3ebd9d00cc5907e08bc58 100644
--- a/tests/SarTests.cpp
+++ b/tests/SarTests.cpp
@@ -78,6 +78,29 @@ TEST_F(SarSensorModel, State) {
   EXPECT_TRUE(differences.empty());
 }
 
+// Apply the identity transform to a state
+TEST_F(SarSensorModel, ApplyTransformToState) {
+  std::string modelState = sensorModel->getModelState();
+
+  ale::Rotation r; // identity rotation
+  ale::Vec3d t;    // zero translation
+
+  // The input state has some "-0" values which get transformed by
+  // applying the identity transform into "0", which results in the
+  // state string changing. Hence, for this test, compare the results
+  // of applying the identity transform once vs twice, which are the
+  // same.
+
+  // First application
+  UsgsAstroSarSensorModel::applyTransformToState(r, t, modelState);
+
+  // Second application
+  std::string modelState2 = modelState;
+  UsgsAstroSarSensorModel::applyTransformToState(r, t, modelState2);
+
+  EXPECT_EQ(modelState, modelState2);
+}
+
 TEST_F(SarSensorModel, Center) {
   csm::ImageCoord imagePt(500.0, 500.0);
   csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);