Fix three ECCO power-bond bugs and add regression tests#803
Open
joakimono wants to merge 1 commit into
Open
Conversation
Bug 1 (ecco_algorithm.cpp): add_power_bond() stored all four bond variable IDs but never called expose_for_getting() on them. adjust_step_size() then called get_real() on all four, which throws 'Variable with reference N not found in exposed variables' for any FMU-input variable not previously exposed. The default file_observer accidentally masked this by exposing all variables; a LogConfig-restricted observer omitting bond input variables (force, in_vel) triggered the crash. Fix: call expose_for_getting() for all four variables at the top of add_power_bond(). Bug 2 (osp_config_parser.cpp): the uniqueCount != numPowerBonds validation in add_power_bonds() was placed inside the per-bond loop. With two bonds configured it fired after the first iteration with numPowerBonds==1 and uniqueCount==2, throwing a spurious error. Fix: move the check outside the loop so it runs after all bonds have been registered. Bug 3 (ecco_algorithm_multi_bond_test.cpp): the test called add_power_bond() manually after inject_system_structure() had already registered the bond from the XML (double registration), and used wrong hardcoded value references (19/22/26/24 are ECCO step-size parameters, not bond variables). Fix: remove the duplicate add_power_bond() call and correct the variable refs to chassis.velocity=23, chassis.force=4, wheel.out_spring_damper_f=15, wheel.in_vel=7. New tests: - ecco_algorithm_powerbond_logconfig_test: loads quarter-truck via inject_system_structure with a file_observer_config that deliberately omits the FMU-input bond variables; verifies no crash (regresses Bug 1). - ecco_algorithm_two_bond_test: loads OspSystemStructure_MultiBond.xml (two independent chassis+wheel pairs, two bonds) and simulates 0.1 s; verifies no spurious throw (regresses Bug 2). - OspSystemStructure_MultiBond.xml: new test data for the two-bond scenario.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fix three ECCO power-bond bugs
Background
Three bugs were present in the ECCO algorithm's power-bond support.
Two caused crashes or spurious errors at runtime; one caused a silent
double-registration in a test that happened to pass only by accident.
Bug 1 —
add_power_bond()never exposes bond variables for gettingFile:
src/cosim/algorithm/ecco_algorithm.cppWhat went wrong
ecco_algorithm::impl::add_power_bond()stores fourvariable_idvalues(the two force/velocity pairs that make up the bond) but never calls
expose_for_getting()on any of them.adjust_step_size()later callssim->get_real(ref)on all four variablesevery step.
get_real()reads from the simulator's get-cache, which onlycontains variables that were previously registered via
expose_for_getting().For FMU output variables that also appear in a
connect_variables()connection, this registration happened to occur as a side-effect. For FMU
input variables (
chassis.force,wheel.in_vel) it never did, becauseconnect_variables()registers inputs only for setting, not for getting.The crash was therefore latent for the two bond-input variables:
Why it was masked
The default
file_observer(constructed without a config) callsinitialize_default()which exposes all non-local variables for getting,accidentally making the bond inputs readable. Any test or application using
the unconfigured observer never saw the crash.
How it is triggered
A
file_observerconstructed from aLogConfig.xmlthat omits the bondinput variables (
force,in_vel) exposes only the listed variables. Whenadjust_step_size()then tries to read the unlisted inputs, the get-cachelookup throws.
Fix
Call
expose_for_getting()for all four bond variables at the top ofadd_power_bond(), before storing them. The call is idempotent — if anobserver already exposed the variable, the second registration is a no-op.
Regression test
tests/ecco_algorithm_powerbond_logconfig_test.cpp— loads the quarter-truckvia
inject_system_structure, then attaches afile_observer_configthatdeliberately omits
chassis.forceandwheel.in_velfrom the logged variablelist, and runs a short simulation. Before the fix this test crashes; after the
fix it completes cleanly.
Bug 2 —
add_power_bonds()validation check fires inside the per-bond loopFile:
src/cosim/osp_config_parser.cppWhat went wrong
After each call to
systemStructure.add_power_bond(), the function checked:uniqueCountwas computed up front from all connection entries acrossall bonds, so with two bonds it always equalled 2. But
numPowerBondswas queried from
systemStructureinside the loop, so after the firstiteration it was only 1. The check
2 != 1fired immediately, making anysystem with two or more power bonds impossible to load.
Fix
Move the sort + uniqueCount + validation block outside the loop so it runs
once, after all bonds have been registered:
Regression test
tests/ecco_algorithm_two_bond_test.cpp— loadsOspSystemStructure_MultiBond.xml, which defines two independentchassis+wheel pairs (
chassis1/wheel1andchassis2/wheel2) eachconnected by a separate power bond (
bond1,bond2). Before the fix,load_osp_config()throws on this file; after the fix the config loads andthe simulation runs for 0.1 s without error.
tests/data/fmi2/quarter_truck/OspSystemStructure_MultiBond.xmlis the newtest data file. Each pair is physically independent; the same Chassis.fmu and
Wheel.fmu are used for both, so no new FMUs are required.
Bug 3 —
ecco_algorithm_multi_bond_testuses wrong variable refs and double-registers the bondFile:
tests/ecco_algorithm_multi_bond_test.cppWhat went wrong
Two mistakes in the test:
Duplicate bond registration.
inject_system_structure()already parsesthe power bond from
OspSystemStructure.xmland callsadd_power_bond()internally. The test then called
add_power_bond()a second time manually,producing two energy-residual accounting entries for the same bond and
doubling the power-residual calculation.
Wrong hardcoded value references. The manually constructed
variable_idobjects used refs 19, 22, 26, 24. Inspection of the FMU model descriptions
shows these are ECCO step-size tuning parameters
(
stepSizeCtrlSafetyFactor,timeStepSlowStart, etc.), not the bondvariables. The correct refs are:
chassis.velocitychassis.forcewheel.out_spring_damper_fwheel.in_velThe test passed despite the wrong refs only because the default
csv_observerexposed all variables for getting, masking Bug 1 forthe bond-input refs, and the wrong parameter refs happened not to crash
the simulation.
Fix
Remove the duplicate
add_power_bond()call. Correct thevariable_idrefs used for the
time_series_observerobservations. Remove the two deadoutput vectors (
wheelGVels,groundVels) that were allocated but neverfilled.