Source code for syssimx.components.opensim
from typing import Any
import opensim as osim
from ..core.base import CoSimComponent
[docs]
class OpenSimComponent(CoSimComponent):
"""
Wrapper around an OpenSim model to implement the CoSimComponent interface.
"""
model: osim.Model
manager: osim.Manager
state: osim.State
parameters: dict[str, Any] = {}
[docs]
def __init__(self, name: str, osim_model_path: str, group: str | None = None):
"""
Constructor for the OpenSimComponent class.
"""
CoSimComponent.__init__(self, name=name, group=group)
self.path = osim_model_path
# Populated by subclass
self.model: osim.Model | None = None
self.state: osim.State | None = None
self.manager: osim.Manager | None = None
# Default Solver Parameters
self.integrator_method = osim.Manager.IntegratorMethod_RungeKuttaMerson
self.integrator_accuracy = 1e-6
self.internal_dt = 1e-4
[docs]
def _finalize_model(self, t0: float) -> None:
"""
Complete OpenSim initialization after model is built/loaded.
Call this at the end of subclass _initialize_component().
"""
# Realize to ensure model is ready
self.realize()
# Create and initialize manager
self.manager = osim.Manager(self.model)
self.manager.setIntegratorMethod(self.integrator_method)
self.manager.setIntegratorAccuracy(self.integrator_accuracy)
self.manager.initialize(self.state)
self.state.setTime(t0)
[docs]
def realize(self) -> None:
"""
Realizes the stage: Position, Velocity, Dynamics, Acceleration
"""
if self.state is None:
raise RuntimeError(f"{self.name}: state not initialized")
self.model.realizeAcceleration(self.state)
# ---- Reset ----
[docs]
def reset(self) -> None:
"""
Reset the component to a clean state before (before initialization).
"""
super().reset()
self.state = self.model.initSystem()
self.manager = osim.Manager(self.model)
# ---- Coordinate Helpers ----
[docs]
def get_coordinate_value(self, coord_name: str) -> float:
"""Get current value of named coordinate (generalized position)."""
coord = self._find_coordinate(coord_name)
return float(coord.getValue(self.state))
[docs]
def get_coordinate_speed(self, coord_name: str) -> float:
"""Get current speed of named coordinate (generalized velocity)."""
coord = self._find_coordinate(coord_name)
return float(coord.getSpeedValue(self.state))
[docs]
def get_coordinate_acceleration(self, coord_name: str) -> float:
"""Get current acceleration of named coordinate."""
coord = self._find_coordinate(coord_name)
return float(coord.getAccelerationValue(self.state))
[docs]
def set_coordinate_value(self, coord_name: str, value: float) -> None:
"""Set value of named coordinate."""
coord = self._find_coordinate(coord_name)
coord.setValue(self.state, float(value))
[docs]
def set_coordinate_speed(self, coord_name: str, value: float) -> None:
"""Set speed of named coordinate."""
coord = self._find_coordinate(coord_name)
coord.setSpeedValue(self.state, float(value))
[docs]
def _find_coordinate(self, name: str) -> osim.Coordinate:
"""Find coordinate by name in model."""
coord_set = self.model.getCoordinateSet()
for i in range(coord_set.getSize()):
coord = coord_set.get(i)
if coord.getName() == name:
return coord
raise KeyError(f"Coordinate '{name}' not found in model '{self.name}'")