/**
 * Add extra joints to the SIMM model to represent the joint location/orientation
 * in the parent body and in the child body.
 *
 * @param aJoint The Simbody joint.
 * @param rParentName The name of the parent body for the "real" joint.
 * @param rChildName The name of the child body for the "real" joint.
 * @return Whether or not a 'parent' joint was added.
 */
bool SimbodySimmModel::addExtraJoints(const OpenSim::Joint& aJoint, string& rParentName, string& rChildName)
{
   SimTK::Vec3 location(0);
   SimTK::Vec3 orientation(0);
    bool parentJointAdded = false;

   if (isParentJointNeeded(aJoint)) {
       const PhysicalOffsetFrame* offset =
           dynamic_cast<const PhysicalOffsetFrame*>(&aJoint.getParentFrame());
       if (offset) {
           location = offset->get_translation();
           orientation = offset->get_orientation();
       }

      string bodyName = aJoint.getChildFrame().getName() + "_pjc";
      SimbodySimmBody* b = new SimbodySimmBody(NULL, bodyName);
      _simmBody.append(b);
      makeSimmJoint(aJoint.getName() + "_pjc", 
          aJoint.getParentFrame().getName(), bodyName, location, orientation);
      rParentName = bodyName;
        parentJointAdded = true;
   } else {
      rParentName = aJoint.getParentFrame().getName();
        parentJointAdded = false;
   }

   location = 0;
   orientation = 0;

   if (isChildJointNeeded(aJoint)) {
       const PhysicalOffsetFrame* offset =
           dynamic_cast<const PhysicalOffsetFrame*>(&aJoint.getChildFrame());
       if (offset) {
           location = offset->get_translation();
           orientation = offset->get_orientation();
       }
       string bodyName = aJoint.getChildFrame().getName() + "_jcc";
      SimbodySimmBody* b = new SimbodySimmBody(NULL, bodyName);
      _simmBody.append(b);
      // This joint is specified in the reverse direction.
      makeSimmJoint(aJoint.getName() + "_jcc",
          aJoint.getChildFrame().getName(), bodyName, location, orientation);
      rChildName = bodyName;
   } else {
       rChildName = aJoint.getChildFrame().getName();
   }

    return parentJointAdded;
}
/**
 * Check to see if a location (in child) and orientation (in child) are all zeros.
 * If they are not, then a separate SIMM joint is needed to hold this transform.
 *
 * @param aJoint The Simbody joint to check.
 * @return Whether or not a separate SIMM joint is needed to represent the location
 *         and orientation in child.
 */
bool SimbodySimmModel::isChildJointNeeded(const OpenSim::Joint& aJoint)
{
    SimTK::Vec3 location(0);
    SimTK::Vec3 orientation(0);
    const PhysicalOffsetFrame* offset =
        dynamic_cast<const PhysicalOffsetFrame*>(&aJoint.getChildFrame());
    if (offset) {
        location = offset->get_translation();
        orientation = offset->get_orientation();
    }
    else {
        return false;
    }

    double sum = location.scalarNormSqr();
   if (NOT_EQUAL_WITHIN_ERROR(sum, 0.0))
      return true;

   sum = orientation.scalarNormSqr();
   if (NOT_EQUAL_WITHIN_ERROR(sum, 0.0))
      return true;

   return false;
}