接入test_mql机械质量状态闭包

This commit is contained in:
huojiarong committed 2026-07-20 08:54:04 +00:00
1 parent 7cb050d235
commit 3d1de6d5d0
4 files changed
+180 -1

No files matched your search

+70 -1
View File
@@ -63,6 +63,8 @@ class TestMqlMassEndstopSpec:
stribeck_constant_m_s: float
use_friction: bool
stop_type: int
initial_velocity_m_s: float
initial_displacement_m: float
data_paths: tuple[str, ...]
def endstop(self) -> AmesimMassFrictionEndstops:
@@ -141,6 +143,64 @@ class TestMqlMechanicalAssembly:
)
@dataclass(frozen=True)
class TestMqlMechanicalMassState:
alias: str
velocity_m_s: float
displacement_m: float
def as_vector(self) -> list[float]:
return [self.velocity_m_s, self.displacement_m]
@dataclass(frozen=True)
class TestMqlMechanicalMassSnapshot:
states: tuple[TestMqlMechanicalMassState, ...]
@property
def state_count(self) -> int:
return 2 * len(self.states)
class TestMqlMechanicalMassClosure:
def __init__(self, assembly: TestMqlMechanicalAssembly) -> None:
self.assembly = assembly
self.mass_aliases = tuple(assembly.masses)
def initial_state_vector(self) -> list[float]:
state: list[float] = []
for alias in self.mass_aliases:
spec = self.assembly.masses[alias]
state.extend([spec.initial_velocity_m_s, spec.initial_displacement_m])
return state
def snapshot(self, state_vector: list[float] | None = None) -> TestMqlMechanicalMassSnapshot:
values = self.initial_state_vector() if state_vector is None else list(state_vector)
if len(values) != 2 * len(self.mass_aliases):
raise ValueError("mechanical mass state vector requires two values per mass")
states = tuple(
TestMqlMechanicalMassState(
alias=alias,
velocity_m_s=values[2 * index],
displacement_m=values[2 * index + 1],
)
for index, alias in enumerate(self.mass_aliases)
)
return TestMqlMechanicalMassSnapshot(states=states)
def rhs(self, state_vector: list[float]) -> list[float]:
snapshot = self.snapshot(state_vector)
derivatives: list[float] = []
for state in snapshot.states:
mass = self.assembly.masses[state.alias].endstop()
acceleration, velocity = mass.derivatives(
velocity_m_s=state.velocity_m_s,
displacement_m=state.displacement_m,
)
derivatives.extend([acceleration, velocity])
return derivatives
def build_test_mql_mechanical_assembly(
config: TestMqlConfig | None = None,
amesim_results: AmesimResults | None = None,
@@ -155,7 +215,7 @@ def build_test_mql_mechanical_assembly(
for component in config.components_by_submodel("PNRP17")
}
masses = {
component.alias: _build_mass(component, variable_catalog)
component.alias: _build_mass(component, variable_catalog, amesim_results)
for component in config.components_by_submodel("MECMAS21")
}
elastic_endstops = {
@@ -202,6 +262,7 @@ def _build_piston(
def _build_mass(
component: TestMqlResolvedComponent,
variable_catalog: TestMqlVariableCatalog | None,
amesim_results: AmesimResults | None,
) -> TestMqlMassEndstopSpec:
return TestMqlMassEndstopSpec(
alias=component.alias,
@@ -224,6 +285,8 @@ def _build_mass(
stribeck_constant_m_s=component.parameter_value("astrib"),
use_friction=bool(int(component.parameter_value("useFriction"))),
stop_type=int(component.parameter_value("stoptype")),
initial_velocity_m_s=_initial_value(amesim_results, f"v1@{component.alias}"),
initial_displacement_m=_initial_value(amesim_results, f"x1@{component.alias}"),
data_paths=_data_paths(variable_catalog, component.alias),
)
@@ -263,6 +326,12 @@ def n_per_mm_per_s_to_n_per_m_per_s(value: float) -> float:
return value * N_PER_MM_PER_S_TO_N_PER_M_PER_S
def _initial_value(amesim_results: AmesimResults | None, data_path: str) -> float:
if amesim_results is None:
return 0.0
return float(amesim_results.series(data_path)[0])
def _data_paths(
variable_catalog: TestMqlVariableCatalog | None,
alias: str,