/*virtual*/ void Marker::updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber) { if (versionNumber < XMLDocument::getLatestVersion()){ if (versionNumber < 30501) { // Parse name of Body under <body>node SimTK::Xml::element_iterator bIter = aNode.element_begin("body"); SimTK::String bName = bIter->getValue(); // Create nodes for new layout SimTK::Xml::Element connectorsElement("connectors"); SimTK::Xml::Element frameElement("Connector_PhysicalFrame_"); connectorsElement.insertNodeAfter(connectorsElement.node_end(), frameElement); frameElement.setAttributeValue("name", "parent_frame"); SimTK::Xml::Element connecteeElement("connectee_name"); // Markers in pre-4.0 models are necessarily 1 level deep // (model, markers), and Bodies were necessarily 1 level deep; // here we create the correct relative path (accounting for sets // being components). bName = XMLDocument::updateConnecteePath30517("bodyset", bName); connecteeElement.setValue(bName); frameElement.insertNodeAfter(frameElement.node_end(), connecteeElement); aNode.insertNodeAfter(bIter, connectorsElement); aNode.eraseNode(bIter); } } // Call base class now assuming _node has been corrected for current version Super::updateFromXMLNode(aNode, versionNumber); }
void ModelComponent::updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber) { if (versionNumber < XMLDocument::getLatestVersion()) { if (versionNumber < 30506) { // geometry list property removed. Everything that was in this list // should be moved to the components list property. SimTK::Xml::element_iterator geometry = aNode.element_begin("geometry"); if (geometry != aNode.element_end()) { // We found a list property of geometry. SimTK::Xml::Element componentsNode; SimTK::Xml::element_iterator componentsIt = aNode.element_begin("components"); if (componentsIt == aNode.element_end()) { // This component does not yet have a list property of // components, so we'll create one. componentsNode = SimTK::Xml::Element("components"); aNode.insertNodeBefore(aNode.element_begin(), componentsNode); } else { componentsNode = *componentsIt; } // Copy each node under <geometry> into <components>. for (auto geomIt = geometry->element_begin(); geomIt != geometry->element_end(); ++geomIt) { componentsNode.appendNode(geomIt->clone()); } // Now that we moved over the geometry, we can delete the // <geometry> element. aNode.eraseNode(geometry); } } } Super::updateFromXMLNode(aNode, versionNumber); }
/*virtual*/ void Marker::updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber) { if (versionNumber < XMLDocument::getLatestVersion()){ if (versionNumber < 30501) { // Parse name of Body under <body>node SimTK::Xml::element_iterator bIter = aNode.element_begin("body"); SimTK::String bName = bIter->getValue(); // Create nodes for new layout SimTK::Xml::Element connectorsElement("connectors"); SimTK::Xml::Element frameElement("Connector_PhysicalFrame_"); connectorsElement.insertNodeAfter(connectorsElement.node_end(), frameElement); frameElement.setAttributeValue("name", "reference_frame"); SimTK::Xml::Element connecteeElement("connectee_name"); connecteeElement.setValue(bName); frameElement.insertNodeAfter(frameElement.node_end(), connecteeElement); aNode.insertNodeAfter(bIter, connectorsElement); aNode.eraseNode(bIter); } } // Call base class now assuming _node has been corrected for current version Object::updateFromXMLNode(aNode, versionNumber); }
/** Override of the default implementation to account for versioning. */ void CustomJoint:: updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber) { int documentVersion = versionNumber; if ( documentVersion < XMLDocument::getLatestVersion()){ if (Object::getDebugLevel()>=1) cout << "Updating CustomJoint to latest format..." << endl; // Version before refactoring spatialTransform if (documentVersion<10901){ // replace TransformAxisSet with SpatialTransform /////renameChildNode("TransformAxisSet", "SpatialTransform"); // Check how many TransformAxes are defined SimTK::Xml::element_iterator spatialTransformNode = aNode.element_begin("TransformAxisSet"); if (spatialTransformNode == aNode.element_end()) return; SimTK::Xml::element_iterator axesSetNode = spatialTransformNode->element_begin("objects"); /////if (axesSetNode != NULL) ///// spatialTransformNode->removeChild(axesSetNode); /////DOMElement*grpNode = XMLNode::GetFirstChildElementByTagName(spatialTransformNode,"groups"); /////if (grpNode != NULL) ///// spatialTransformNode->removeChild(grpNode); // (0, 1, 2 rotations & 3, 4, 5 translations then remove the is_rotation node) SimTK::Array_<SimTK::Xml::Element> list = axesSetNode->getAllElements(); unsigned int listLength = list.size(); int objectsFound = 0; Array<int> translationIndices(-1, 0); Array<int> rotationIndices(-1, 0); int nextAxis = 0; std::vector<TransformAxis *> axes; // Add children for all six axes here //////_node->removeChild(SpatialTransformNode); // Create a blank Spatial Transform and use it to populate the // XML structure for(int i=0; i<6; i++) updSpatialTransform()[i].setFunction(new OpenSim::Constant(0)); Array<OpenSim::TransformAxis*> oldAxes; for(unsigned int j=0;j<listLength;j++) { // getChildNodes() returns all types of DOMNodes including // comments, text, etc., but we only want // to process element nodes SimTK::Xml::Element objElmt = list[j]; string objectType = objElmt.getElementTag(); // (sherm) this is cleaning up old TransformAxis here but // that should really be done in TransformAxis instead. if (objectType == "TransformAxis"){ OpenSim::TransformAxis* readAxis = new OpenSim::TransformAxis(objElmt); assert(nextAxis <=5); bool isRotation = false; SimTK::Xml::element_iterator rotationNode = objElmt.element_begin("is_rotation"); if (rotationNode != objElmt.element_end()){ SimTK::String sValue = rotationNode->getValueAs<SimTK::String>(); bool value = (sValue.toLower() == "true"); isRotation = value; objElmt.eraseNode(rotationNode); } SimTK::Xml::element_iterator coordinateNode = objElmt.element_begin("coordinate"); SimTK::String coordinateName = coordinateNode->getValueAs<SimTK::String>(); Array<std::string> names(""); names.append(coordinateName); readAxis->setCoordinateNames(names); SimTK::Xml::element_iterator axisNode = objElmt.element_begin("axis"); SimTK::Vec3 axisVec= axisNode->getValueAs<SimTK::Vec3>(); readAxis->setAxis(axisVec); if (isRotation){ rotationIndices.append(nextAxis); } else { translationIndices.append(nextAxis); } axes.push_back(readAxis); nextAxis++; } } assert(rotationIndices.getSize() <=3); assert(translationIndices.getSize() <=3); //XMLNode::RemoveChildren(SpatialTransformAxesNode); int nRotations = rotationIndices.getSize(); int nTranslations = translationIndices.getSize(); // Now copy coordinateName, Axis, Function into proper slot for (int i=0; i<nRotations; i++){ updSpatialTransform()[i] = *axes[rotationIndices[i]]; } updSpatialTransform().constructIndependentAxes(nRotations, 0); // Add Translations from old list then pad with default ones, // make sure no singularity. for (int i=0; i<nTranslations; i++){ updSpatialTransform()[i+3] = *axes[translationIndices[i]]; } updSpatialTransform().constructIndependentAxes(nTranslations, 3); } } // Delegate to superclass now. Super::updateFromXMLNode(aNode, versionNumber); const CoordinateSet& coordinateSet = get_CoordinateSet(); // Fix coordinate type post deserialization // Fix coordinate type post deserialization for (int i=0; i<coordinateSet.getSize(); i++){ OpenSim::Coordinate& nextCoord = coordinateSet.get(i); // Find TransformAxis for the coordinate and use it to set Coordinate's motionType for(int axisIndex=0; axisIndex<6; axisIndex++){ const TransformAxis& nextAxis = getSpatialTransform()[axisIndex]; const Property<std::string>& coordNames = nextAxis.getCoordinateNames(); if (coordNames.findIndex(nextCoord.getName())!=-1){ coordinateSet.get(i).setMotionType((axisIndex>2)? Coordinate::Translational : Coordinate::Rotational); break; } } } // Axes should be independent otherwise Simbody throws an exception in addToSystem double tol = 1e-5; // Verify that none of the rotation axes are colinear const std::vector<SimTK::Vec3> axes=getSpatialTransform().getAxes(); for(int startIndex=0; startIndex<=3; startIndex+=3){ if(((axes[startIndex+0]%axes[startIndex+1]).norm() < tol)|| ((axes[startIndex+0]%axes[startIndex+2]).norm() < tol)|| ((axes[startIndex+1]%axes[startIndex+2]).norm() < tol)){ throw(Exception("CustomJoint " + getName() + " has colinear axes and so is not well-defined." " Please fix and retry loading..")); } } updProperty_SpatialTransform().setValueIsDefault(false); }
void Joint::updateFromXMLNode(SimTK::Xml::Element& aNode, int versionNumber) { int documentVersion = versionNumber; //bool converting = false; if (documentVersion < XMLDocument::getLatestVersion()){ if (documentVersion<30500){ XMLDocument::renameChildNode(aNode, "location", "location_in_child"); XMLDocument::renameChildNode(aNode, "orientation", "orientation_in_child"); } // Version 30501 converted Connector_Body_ to Connector_PhysicalFrame_ if (documentVersion < 30501) { // Handle any models that have the Joint connecting to Bodies instead // of PhyscialFrames XMLDocument::renameChildNode(aNode, "Connector_Body_", "Connector_PhysicalFrame_"); } // Version 30505 changed "parent_body" connector name to "parent_frame" // Convert location and orientation into PhysicalOffsetFrames owned by the Joint if (documentVersion < 30505) { // Elements for the parent and child names the joint connects SimTK::Xml::element_iterator parentNameElt; SimTK::Xml::element_iterator childNameElt; // The names of the two PhysicalFrames this joint connects std::string parentFrameName(""); std::string childFrameName(""); SimTK::Xml::element_iterator connectors_node = aNode.element_begin("connectors"); SimTK::Xml::element_iterator connectorElement = connectors_node->element_begin("Connector_PhysicalFrame_"); while (connectorElement != aNode.element_end()) { // If connector name is "parent_body" rename it to "parent_frame" if (connectorElement->getRequiredAttributeValue("name") == "parent_body") { connectorElement->setAttributeValue("name", "parent_frame"); } // If connector name is "parent_frame" get the name of the connectee if (connectorElement->getRequiredAttributeValue("name") == "parent_frame"){ parentNameElt = connectorElement->element_begin("connectee_name"); parentNameElt->getValueAs<std::string>(parentFrameName); const auto slashLoc = parentFrameName.rfind('/'); if (slashLoc != std::string::npos) parentFrameName = parentFrameName.substr(slashLoc + 1); } if (connectorElement->getRequiredAttributeValue("name") == "child_body") { connectorElement->setAttributeValue("name", "child_frame"); } if (connectorElement->getRequiredAttributeValue("name") == "child_frame") { childNameElt = connectorElement->element_begin("connectee_name"); childNameElt->getValueAs<std::string>(childFrameName); const auto slashLoc = childFrameName.rfind('/'); if (slashLoc != std::string::npos) childFrameName = childFrameName.substr(slashLoc + 1); } ++connectorElement; } SimTK::Xml::element_iterator locParentElt = aNode.element_begin("location_in_parent"); SimTK::Xml::element_iterator orientParentElt = aNode.element_begin("orientation_in_parent"); SimTK::Xml::element_iterator locChildElt = aNode.element_begin("location_in_child"); SimTK::Xml::element_iterator orientChildElt = aNode.element_begin("orientation_in_child"); Vec3 location_in_parent(0); Vec3 orientation_in_parent(0); Vec3 location_in_child(0); Vec3 orientation_in_child(0); if (locParentElt != aNode.element_end()){ locParentElt->getValueAs<Vec3>(location_in_parent); } if (orientParentElt != aNode.element_end()){ orientParentElt->getValueAs<Vec3>(orientation_in_parent); } if (locChildElt != aNode.element_end()){ locChildElt->getValueAs<Vec3>(location_in_child); } if (orientChildElt != aNode.element_end()){ orientChildElt->getValueAs<Vec3>(orientation_in_child); } // now append updated frames to the property list for // both parent and child XMLDocument::addPhysicalOffsetFrame30505_30517(aNode, parentFrameName+"_offset", parentFrameName, location_in_parent, orientation_in_parent); parentNameElt->setValue(parentFrameName + "_offset"); XMLDocument::addPhysicalOffsetFrame30505_30517(aNode, childFrameName + "_offset", childFrameName, location_in_child, orientation_in_child); childNameElt->setValue(childFrameName + "_offset"); } // Version 30507 replaced Joint's CoordinateSet with a "coordinates" // list property. if (documentVersion < 30507) { if (aNode.hasElement("CoordinateSet")) { auto coordSetIter = aNode.element_begin("CoordinateSet"); if (coordSetIter->hasElement("objects")) { auto coordIter = coordSetIter->getRequiredElement("objects") .element_begin("Coordinate"); if (coordIter != aNode.element_end()) { // A "CoordinateSet" element exists, it contains an // "objects" element, and the "objects" element contains // at least one "Coordinate" element. // Create an element for the new layout. Xml::Element coordinatesElement("coordinates"); // Copy all "Coordinate" elements from the old layout. while (coordIter != aNode.element_end()) { coordinatesElement.appendNode(coordIter->clone()); ++coordIter; } // Insert new "coordinates" element. aNode.insertNodeAfter(coordSetIter, coordinatesElement); } } // Remove old "CoordinateSet" element. aNode.eraseNode(coordSetIter); } } // Version 30514 removed the user-facing "reverse" property from Joint. // The parent and child frames are swapped if a "reverse" element is // found and its value is "true". if (documentVersion < 30514) { auto reverseElt = aNode.element_begin("reverse"); if (reverseElt != aNode.element_end()) { bool swapFrames = false; reverseElt->getValue().tryConvertToBool(swapFrames); if (swapFrames) { std::string oldParentFrameName = ""; std::string oldChildFrameName = ""; // Find names of parent and child frames. If more than one // "parent_frame" or "child_frame" element exists, keep the // first one. The "parent_frame" and "child_frame" elements // may be listed in either order. SimTK::Xml::element_iterator connectorsNode = aNode.element_begin("connectors"); SimTK::Xml::element_iterator connectorElt = connectorsNode-> element_begin("Connector_PhysicalFrame_"); SimTK::Xml::element_iterator connecteeNameElt; while (connectorElt != connectorsNode->element_end()) { if (connectorElt->getRequiredAttributeValue("name") == "parent_frame" && oldParentFrameName.empty()) { connecteeNameElt = connectorElt-> element_begin("connectee_name"); connecteeNameElt->getValueAs<std::string>( oldParentFrameName); } else if (connectorElt->getRequiredAttributeValue("name") == "child_frame" && oldChildFrameName.empty()) { connecteeNameElt = connectorElt-> element_begin("connectee_name"); connecteeNameElt->getValueAs<std::string>( oldChildFrameName); } ++connectorElt; } // Swap parent and child frame names. If more than one // "parent_frame" or "child_frame" element exists, assign // the same value to all such elements. connectorsNode = aNode.element_begin("connectors"); connectorElt = connectorsNode->element_begin( "Connector_PhysicalFrame_"); while (connectorElt != connectorsNode->element_end()) { if (connectorElt->getRequiredAttributeValue("name") == "parent_frame") { connecteeNameElt = connectorElt-> element_begin("connectee_name"); connecteeNameElt->setValue(oldChildFrameName); } else if (connectorElt->getRequiredAttributeValue("name") == "child_frame") { connecteeNameElt = connectorElt-> element_begin("connectee_name"); connecteeNameElt->setValue(oldParentFrameName); } ++connectorElt; } } // Remove "reverse" element regardless of its value (it is no // longer a property of Joint). aNode.eraseNode(reverseElt); } } } Super::updateFromXMLNode(aNode, versionNumber); }