Source code for myoconverter.xml.forces.Ligament

""" Contains the `Ligament` parser.

@author: Aleksi Ikkala
"""

from lxml import etree

from myoconverter.xml.parsers import IParser
from myoconverter.xml.utils import str2bool, element_txt2num, val2str, filter_nan_values, filter_keys
from myoconverter.xml import config as cfg


[docs]class Ligament(IParser): """ This class parses and converts the OpenSim `Ligament` XML element to MuJoCo. """
[docs] def parse(self, xml): """ This function handles the actual parsing and converting. :param xml: OpenSim `Ligament` XML element :return: None """ # If this actuator is not enabled, return if xml.find("appliesForce") is not None and not str2bool(xml.find("appliesForce").text): return # Collect attributes in a dict params = {"name": f"{xml.attrib['name']}_ligament" } # Get resting length resting_length = element_txt2num(xml, "resting_length") params["springlength"] = resting_length # TODO PCSA force probably has something to do with stiffness and damping? pcsa_force = element_txt2num(xml, "pcsa_force") # Add the tendon to MuJoCo model tendon = etree.SubElement(cfg.M_TENDON, "spatial", attrib=val2str(filter_nan_values(filter_keys(params)))) # Parse path points cfg.PATH_POINT_PARSER.parse_all(xml.find("GeometryPath/PathPointSet/objects"), tendon=tendon, force_name=xml.attrib['name']) # Parse path wrap set. Note: PathWrapSetParser parses the whole PathWrapSet at once instead of individual objects # found in the PathWrapSet. Input muscle name as well, since we want to create muscle-specific wrapping objects for # ellipsoids which we can optimize separately later cfg.PATH_WRAP_SET_PARSER.parse(xml.find("GeometryPath/PathWrapSet"), tendon=tendon, force_name=xml.attrib["name"])