Page 1 of 1

Iterating over the model elements

Posted: Sun Mar 15, 2020 11:41 am
by idhamari
Dear all,

I am trying to add an xml node to the model .osim file similar to this viewtopicPhpbb.php?f=91&t=11447&p=31986&start=0&view=
. RapidXML introduced NULL characters to the .osim file in windowa :evil: . I decided to try the built-in opensim XMLDocument class but I could not iterate over the model correctly and I could not find a clear example of how to do this. Here is my try

Code: Select all

              #include "SimTKcommon/internal/Xml.h"
                       //read model file from a string variable
		        XMLDocument doc(inputFilePath);
			SimTK::Xml::Element myModelNode, myCurrentNode;
			SimTK::Xml::Attribute nodeAtt;
			myModelNode = doc.getRootDataElement();

			// this gives only the first body and stops
			SimTK::Xml::element_iterator nodeItr1 = myModelNode.element_begin("BodySet");
			nodeItr1 = nodeItr1->element_begin();
			while (nodeItr1 != myModelNode.element_end()) {
				myCurrentNode = nodeItr1->getRequiredElement("Body");
				nodeAtt = myCurrentNode.getRequiredAttribute("name");
				std::cout << "BodyName            : " << nodeAtt.getValue() << std::endl;
			    nodeItr1++;
			}

Re: Iterating over the model elements

Posted: Tue Mar 17, 2020 12:12 pm
by idhamari
I couldn't find a function for this so I wrote this function:

Code: Select all

SimTK::Xml::Element  findNode(SimTK::Xml::Element rootNd, std::string nodeName) {
  	    SimTK::Xml::node_iterator pnI;
		SimTK::Xml::Element cEl;
		pnI = rootNd.element_begin();
		int j = 0;
		while (  (pnI != rootNd.element_end()) ) {
			  cEl = pnI->getParentElement().getAllElements()[j];
			  if (noName == cEl.getNodeText()) {
				cout << cEl.getNodeText() << "  " << cEl.getRequiredAttribute("name").getValue() << endl;
			  }else
				cEl = findNode(cEl, nodeName);		
			pnI++; j++;
		}//while1	
	return cEl;
}
then in the main function we can find all the bodies using

Code: Select all

SimTK::Xml::Document doc(modelPath); // read model from some path variable
SimTK::Xml::Element rootNd,  bodyNd; 

rootNd = doc.getRootElement(); // get the root node
bodyNd= findNode(rootNd, "Body");

Re: Iterating over the model elements

Posted: Tue Mar 17, 2020 12:45 pm
by tkuchida
What is it you are trying to do with this code (find a Body in a Model, add a Body, etc.)? Is it possible to use the OpenSim API rather than stepping through the XML?

Re: Iterating over the model elements

Posted: Wed Mar 18, 2020 3:16 am
by idhamari
As I mentioned, I ma trying to add a pluginforce to the model in the cpp code as in viewtopicPhpbb.php?f=91&t=11447&p=31986&start=0&view=

I already did this using rapidXML library but there was an error in windows. Now I am using the SimTK:::Xml class so no need to use external library.

The code I post here is just an example how to iterate over all bodies.

Here is how I added the plugin force:

Code: Select all

 SimTK::Xml::Element GlobalForceSetEl;
SimTK::Xml::Element  findNode(SimTK::Xml::Element rootNd, std::string nodName) {
  	    SimTK::Xml::node_iterator pnI;
		SimTK::Xml::Element cEl;
		pnI = rootNd.element_begin();
		int j = 0; int Stp = 0; 
		while (  pnI != rootNd.element_end() ) {
			  cEl = pnI->getParentElement().getAllElements()[j];
			  if (nodName == cEl.getNodeText()) {
				  GlobalForceSetEl = cEl;
				  break;
			  }else
				cEl = findNode(cEl, nodName);		
			pnI++; j++;
		}//while1	
	return cEl;
}

void addForcePlugin(SimTK::Xml::Element forceNode, std::string modelPath) {
	try {
		SimTK::Xml::Document modelDoc(modelPath);
		SimTK::Xml::Element rootNd = modelDoc.getRootElement();
		cout << " model file is oppened: " <<modelPath<< endl;
		try {
			SimTK::Xml::Element ForceSetElem = findNode(rootNd, "ForceSet");
			cout << " ForceSet is found ......." << endl;
			SimTK::Xml::Element ObjectsElem = GlobalForceSetEl.getAllElements()[0];
			cout << "ok" << endl;
			cout << ObjectsElem.getNodeText() << endl;
			ObjectsElem.appendNode(forceNode);
		}
		catch (Exception ee) {
			cout << " ForceSet Not found ......." << endl;
			SimTK::Xml::Element ForceSetElem("ForceSet");
			ForceSetElem.setAttributeValue("name", "ForceSet");
			SimTK::Xml::Element ObjectsElem("Objects");
			ForceSetElem.appendNode(ObjectsElem);
			ObjectsElem.appendNode(forceNode);
		}
		modelDoc.writeToFile(modelPath);
		cout << " Plug-in force is added ......." << endl;
	}
	catch(Exception e){
		cout << " ERROR: plug-in force is not added ......"<< endl;
	}
in the main function:


1. we create the plugin force XML:

Code: Select all

SimTK::Xml::Element nElem("somePluginForce"); 	   nElem.setAttributeValue("name", "myPluginForce");
std::string modelPath = "somePath/myModel.osim";
SimTK::Xml::Element par1("par1");	   par1.setValue(to_string(par1));    nElem.appendNode(par1);
SimTK::Xml::Element par1("par2");	   par1.setValue(to_string(par2));    nElem.appendNode(par2);

2. after printing the model we call the addForcePlugin function:

Code: Select all

osimModel.print(modelPath);
addForcePlugin(nElem, modelPath);