From 009651f60dfa8dbbdb6f9f6d347c6d7c965faf29 Mon Sep 17 00:00:00 2001 From: alterlleo Date: Fri, 22 May 2026 23:40:17 +0200 Subject: [PATCH 1/7] feat: supporting co-simulation An Enum class is implemented in order to get the current type of the selected FMU. Depending on the FMU nature, a different integration is performed: if model exchange, then the default custom explicit integrator is used and, if co-simulation, the exported solver is called --- src/FmuInstance.cpp | 348 ++++++++++++++++++++++++++------------------ src/FmuInstance.hpp | 9 ++ 2 files changed, 215 insertions(+), 142 deletions(-) diff --git a/src/FmuInstance.cpp b/src/FmuInstance.cpp index ebb0b28..53ffbfc 100644 --- a/src/FmuInstance.cpp +++ b/src/FmuInstance.cpp @@ -551,9 +551,36 @@ FmuWrapper::FmuWrapper(const std::string &fmu_path, std::to_string(v)); } - // Instantiate FMI3 CoSimulation component - _instance = - fmi3_instantiateModelExchange(_fmu, false, false, nullptr, nullptr); + _model_description_xml = read_model_description_xml(_fmu_path); + bool cs = _model_description_xml.find(" y(numStates); - std::vector ytemp(numStates); - std::vector k1(numStates), k2(numStates), k3(numStates); - std::vector k4(numStates), k5(numStates), k6(numStates); - std::vector yerr(numStates); + if (terminateSimulation) { + throw std::runtime_error("FMU requested termination during doStep"); + } - // Get initial state - status = fmi3_getContinuousStates(_instance, y.data(), numStates); - check_status(status, "getContinuousStates"); + _current_time += dt; - // Adaptive stepping loop - while (t < tend && h > hmin) { - // Limit step to not overshoot tend - if (t + h > tend) { - h = tend - t; + if (eventHandlingNeeded) { + fmi3_enterEventMode(_instance); + handle_events(); + fmi3_enterStepMode(_instance); } - // RK45 with Dormand-Prince coefficients - // Stage 1: k1 = f(t, y) - status = - fmi3_getContinuousStateDerivatives(_instance, k1.data(), numStates); - check_status(status, "getContinuousStateDerivatives at stage 1"); + } else if(_type == FmuType::ModelExchange){ // MODEL EXCHANGE - // Stage 2: k2 = f(t + (1/5)*h, y + (1/5)*h*k1) - for (size_t i = 0; i < numStates; ++i) { - ytemp[i] = y[i] + (h / 5.0) * k1[i]; - } - status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); - check_status(status, "setContinuousStates at stage 2"); - status = - fmi3_getContinuousStateDerivatives(_instance, k2.data(), numStates); - check_status(status, "getContinuousStateDerivatives at stage 2"); - - // Stage 3: k3 = f(t + (3/10)*h, y + (3/40)*h*k1 + (9/40)*h*k2) - for (size_t i = 0; i < numStates; ++i) { - ytemp[i] = y[i] + (3.0 / 40.0) * h * k1[i] + (9.0 / 40.0) * h * k2[i]; - } - status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); - check_status(status, "setContinuousStates at stage 3"); - status = - fmi3_getContinuousStateDerivatives(_instance, k3.data(), numStates); - check_status(status, "getContinuousStateDerivatives at stage 3"); - - // Stage 4: k4 = f(t + (4/5)*h, y + (44/45)*h*k1 - (56/15)*h*k2 + - // (32/9)*h*k3) - for (size_t i = 0; i < numStates; ++i) { - ytemp[i] = y[i] + (44.0 / 45.0) * h * k1[i] - (56.0 / 15.0) * h * k2[i] + - (32.0 / 9.0) * h * k3[i]; - } - status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); - check_status(status, "setContinuousStates at stage 4"); - status = - fmi3_getContinuousStateDerivatives(_instance, k4.data(), numStates); - check_status(status, "getContinuousStateDerivatives at stage 4"); - - // Stage 5: k5 = f(t + (8/9)*h, y + ...) - for (size_t i = 0; i < numStates; ++i) { - ytemp[i] = y[i] + (19372.0 / 6561.0) * h * k1[i] - - (25360.0 / 2187.0) * h * k2[i] + - (64448.0 / 6561.0) * h * k3[i] - (212.0 / 729.0) * h * k4[i]; - } - status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); - check_status(status, "setContinuousStates at stage 5"); - status = - fmi3_getContinuousStateDerivatives(_instance, k5.data(), numStates); - check_status(status, "getContinuousStateDerivatives at stage 5"); - - // Stage 6: k6 = f(t + h, y + ...) - for (size_t i = 0; i < numStates; ++i) { - ytemp[i] = y[i] + (9017.0 / 3168.0) * h * k1[i] - - (355.0 / 33.0) * h * k2[i] + (46732.0 / 5247.0) * h * k3[i] + - (49.0 / 176.0) * h * k4[i] - (5103.0 / 18656.0) * h * k5[i]; - } - status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); - check_status(status, "setContinuousStates at stage 6"); - status = - fmi3_getContinuousStateDerivatives(_instance, k6.data(), numStates); - check_status(status, "getContinuousStateDerivatives at stage 6"); - - // 5th order solution: y_new = y + h * (35/384*k1 + 500/1113*k3 + 125/192*k4 - // - 2187/6784*k5 + 11/84*k6) 4th order solution for error: y_hat = y + h * - // (5179/57600*k1 + 7571/16695*k3 + 393/640*k4 - 92097/339200*k5 + - // 187/2100*k6) - std::vector ynew(numStates); - for (size_t i = 0; i < numStates; ++i) { - ynew[i] = y[i] + h * (35.0 / 384.0 * k1[i] + 500.0 / 1113.0 * k3[i] + - 125.0 / 192.0 * k4[i] - 2187.0 / 6784.0 * k5[i] + - 11.0 / 84.0 * k6[i]); - - // Error estimate (difference between 5th and 4th order) - double y4th = - y[i] + h * (5179.0 / 57600.0 * k1[i] + 7571.0 / 16695.0 * k3[i] + - 393.0 / 640.0 * k4[i] - 92097.0 / 339200.0 * k5[i] + - 187.0 / 2100.0 * k6[i]); - yerr[i] = std::abs(ynew[i] - y4th); - } + // Get the number of continuous states + size_t numStates = 0; + fmi3Status status = fmi3_getNumberOfContinuousStates(_instance, &numStates); + check_status(status, "getNumberOfContinuousStates"); - // Compute maximum relative error - double maxError = 0.0; - for (size_t i = 0; i < numStates; ++i) { - double scale = absTol + relTol * std::abs(y[i]); - double error = yerr[i] / scale; - maxError = std::max(maxError, error); + if (numStates == 0) { + // No states to integrate, just advance time and handle events + _current_time += dt; + handle_events(); + return; } - // Adaptive step size control - if (maxError <= 1.0) { - // Step accepted: update y and t - y = ynew; - t += h; - _current_time = t; + // Adaptive RK45 integration parameters + const double &relTol = _solver_params._rel_tol; + const double &absTol = _solver_params._abs_tol; + const double &hmin = _solver_params._hmin; + + double t = _current_time; + double tend = _current_time + dt; + double h = dt; // Initial step size + + std::vector y(numStates); + std::vector ytemp(numStates); + std::vector k1(numStates), k2(numStates), k3(numStates); + std::vector k4(numStates), k5(numStates), k6(numStates); + std::vector yerr(numStates); + + // Get initial state + status = fmi3_getContinuousStates(_instance, y.data(), numStates); + check_status(status, "getContinuousStates"); + + // Adaptive stepping loop + while (t < tend && h > hmin) { + // Limit step to not overshoot tend + if (t + h > tend) { + h = tend - t; + } - // Set accepted state into FMU - status = fmi3_setContinuousStates(_instance, y.data(), numStates); - check_status(status, "setContinuousStates (accepted step)"); + // RK45 with Dormand-Prince coefficients + // Stage 1: k1 = f(t, y) + status = + fmi3_getContinuousStateDerivatives(_instance, k1.data(), numStates); + check_status(status, "getContinuousStateDerivatives at stage 1"); - // Increase step size for next iteration (but not too aggressively) - h *= 0.9 * std::pow(1.0 / maxError, 0.2); - h = std::min(h, 10.0 * (tend - t)); // Don't let h grow too much - } else { - // Step rejected: reduce step size - h *= 0.9 * std::pow(1.0 / maxError, 0.25); - } + // Stage 2: k2 = f(t + (1/5)*h, y + (1/5)*h*k1) + for (size_t i = 0; i < numStates; ++i) { + ytemp[i] = y[i] + (h / 5.0) * k1[i]; + } + status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); + check_status(status, "setContinuousStates at stage 2"); + status = + fmi3_getContinuousStateDerivatives(_instance, k2.data(), numStates); + check_status(status, "getContinuousStateDerivatives at stage 2"); + + // Stage 3: k3 = f(t + (3/10)*h, y + (3/40)*h*k1 + (9/40)*h*k2) + for (size_t i = 0; i < numStates; ++i) { + ytemp[i] = y[i] + (3.0 / 40.0) * h * k1[i] + (9.0 / 40.0) * h * k2[i]; + } + status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); + check_status(status, "setContinuousStates at stage 3"); + status = + fmi3_getContinuousStateDerivatives(_instance, k3.data(), numStates); + check_status(status, "getContinuousStateDerivatives at stage 3"); + + // Stage 4: k4 = f(t + (4/5)*h, y + (44/45)*h*k1 - (56/15)*h*k2 + + // (32/9)*h*k3) + for (size_t i = 0; i < numStates; ++i) { + ytemp[i] = y[i] + (44.0 / 45.0) * h * k1[i] - (56.0 / 15.0) * h * k2[i] + + (32.0 / 9.0) * h * k3[i]; + } + status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); + check_status(status, "setContinuousStates at stage 4"); + status = + fmi3_getContinuousStateDerivatives(_instance, k4.data(), numStates); + check_status(status, "getContinuousStateDerivatives at stage 4"); + + // Stage 5: k5 = f(t + (8/9)*h, y + ...) + for (size_t i = 0; i < numStates; ++i) { + ytemp[i] = y[i] + (19372.0 / 6561.0) * h * k1[i] - + (25360.0 / 2187.0) * h * k2[i] + + (64448.0 / 6561.0) * h * k3[i] - (212.0 / 729.0) * h * k4[i]; + } + status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); + check_status(status, "setContinuousStates at stage 5"); + status = + fmi3_getContinuousStateDerivatives(_instance, k5.data(), numStates); + check_status(status, "getContinuousStateDerivatives at stage 5"); + + // Stage 6: k6 = f(t + h, y + ...) + for (size_t i = 0; i < numStates; ++i) { + ytemp[i] = y[i] + (9017.0 / 3168.0) * h * k1[i] - + (355.0 / 33.0) * h * k2[i] + (46732.0 / 5247.0) * h * k3[i] + + (49.0 / 176.0) * h * k4[i] - (5103.0 / 18656.0) * h * k5[i]; + } + status = fmi3_setContinuousStates(_instance, ytemp.data(), numStates); + check_status(status, "setContinuousStates at stage 6"); + status = + fmi3_getContinuousStateDerivatives(_instance, k6.data(), numStates); + check_status(status, "getContinuousStateDerivatives at stage 6"); + + // 5th order solution: y_new = y + h * (35/384*k1 + 500/1113*k3 + 125/192*k4 + // - 2187/6784*k5 + 11/84*k6) 4th order solution for error: y_hat = y + h * + // (5179/57600*k1 + 7571/16695*k3 + 393/640*k4 - 92097/339200*k5 + + // 187/2100*k6) + std::vector ynew(numStates); + for (size_t i = 0; i < numStates; ++i) { + ynew[i] = y[i] + h * (35.0 / 384.0 * k1[i] + 500.0 / 1113.0 * k3[i] + + 125.0 / 192.0 * k4[i] - 2187.0 / 6784.0 * k5[i] + + 11.0 / 84.0 * k6[i]); + + // Error estimate (difference between 5th and 4th order) + double y4th = + y[i] + h * (5179.0 / 57600.0 * k1[i] + 7571.0 / 16695.0 * k3[i] + + 393.0 / 640.0 * k4[i] - 92097.0 / 339200.0 * k5[i] + + 187.0 / 2100.0 * k6[i]); + yerr[i] = std::abs(ynew[i] - y4th); + } + + // Compute maximum relative error + double maxError = 0.0; + for (size_t i = 0; i < numStates; ++i) { + double scale = absTol + relTol * std::abs(y[i]); + double error = yerr[i] / scale; + maxError = std::max(maxError, error); + } + + // Adaptive step size control + if (maxError <= 1.0) { + // Step accepted: update y and t + y = ynew; + t += h; + _current_time = t; + + // Set accepted state into FMU + status = fmi3_setContinuousStates(_instance, y.data(), numStates); + check_status(status, "setContinuousStates (accepted step)"); + + // Increase step size for next iteration (but not too aggressively) + h *= 0.9 * std::pow(1.0 / maxError, 0.2); + h = std::min(h, 10.0 * (tend - t)); // Don't let h grow too much + } else { + // Step rejected: reduce step size + h *= 0.9 * std::pow(1.0 / maxError, 0.25); + } - // Enforce minimum step size to prevent infinite loops - if (h < hmin) { - h = hmin; + // Enforce minimum step size to prevent infinite loops + if (h < hmin) { + h = hmin; + } } - } - // Ensure we're exactly at tend - _current_time = tend; + // Ensure we're exactly at tend + _current_time = tend; + + // Handle events at the end of the step + handle_events(); + } - // Handle events at the end of the step - handle_events(); + } void FmuWrapper::handle_events() { diff --git a/src/FmuInstance.hpp b/src/FmuInstance.hpp index b9dac13..f7a211b 100644 --- a/src/FmuInstance.hpp +++ b/src/FmuInstance.hpp @@ -21,6 +21,12 @@ extern "C" { using json = nlohmann::json; +enum class FmuType{ + Unknown, + ModelExchange, + CoSimulation +}; + class FmuWrapper { public: FmuWrapper() {} @@ -119,6 +125,9 @@ class FmuWrapper { static const std::unordered_map _causality_map; static const std::unordered_map _data_type_map; + // FMU type variable + FmuType _type = FmuType::Unknown; + /// Resolve variable name to value reference fmi3ValueReference resolve_var_ref(const std::string& name) const; size_t resolve_real_array_length(const std::string& name) const; From bb33252dcb78b93d56237fb09b77f9f928de1407 Mon Sep 17 00:00:00 2001 From: alterlleo Date: Fri, 22 May 2026 23:48:52 +0200 Subject: [PATCH 2/7] feat: support discrete dt for not-trigger mode --- src/FmuInstance.cpp | 14 ++++++++++++++ src/FmuInstance.hpp | 4 ++++ src/main/fmu_agent.cpp | 11 ++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/FmuInstance.cpp b/src/FmuInstance.cpp index 53ffbfc..97c3174 100644 --- a/src/FmuInstance.cpp +++ b/src/FmuInstance.cpp @@ -559,6 +559,20 @@ FmuWrapper::FmuWrapper(const std::string &fmu_path, _type = FmuType::CoSimulation; + size_t cs_pos = _model_description_xml.find("", cs_pos); + string cs_tag = _model_description_xml.substr(cs_pos, cs_end - cs_pos + 1); + + string var_step; + if(extract_xml_attribute(cs_tag, "canHandleVariableCommunicationStepSize", var_step)){ + _fixed_step = !(var_step == "true" || var_step == "1"); + } else{ + _fixed_step = false; + } + } + _instance = fmi3_instantiateCoSimulation( _fmu, fmi3False, // visible diff --git a/src/FmuInstance.hpp b/src/FmuInstance.hpp index f7a211b..64b9839 100644 --- a/src/FmuInstance.hpp +++ b/src/FmuInstance.hpp @@ -96,6 +96,9 @@ class FmuWrapper { std::vector get_indep_names() const; std::vector get_binary_dependencies() const; + int get_type() const { return static_cast(_type); } + bool get_fixed_step() const { return _fixed_step; } + struct SolverParams { double _rel_tol = 1e-6; double _abs_tol = 1e-8; @@ -127,6 +130,7 @@ class FmuWrapper { // FMU type variable FmuType _type = FmuType::Unknown; + bool _fixed_step = false; /// Resolve variable name to value reference fmi3ValueReference resolve_var_ref(const std::string& name) const; diff --git a/src/main/fmu_agent.cpp b/src/main/fmu_agent.cpp index 3014e2d..baaf977 100644 --- a/src/main/fmu_agent.cpp +++ b/src/main/fmu_agent.cpp @@ -274,9 +274,14 @@ int main(int argc, char *const *argv) { agent.loop([&]() -> chrono::milliseconds { // timing now = chrono::steady_clock::now(); - dt = chrono::duration_cast(now - last_timestep) - .count() / 1e6; - last_timestep = now; + if(plant.get_fixed_step()){ + dt = static_cast(period.count()) / 1e3; + } else{ + dt = chrono::duration_cast(now - last_timestep) + .count() / 1e6; + + last_timestep = now; + } t += dt; // input if (agent.receive(true) == message_type::json && From b8b9ef32c596828c8080ae92c5bc56334a964b36 Mon Sep 17 00:00:00 2001 From: alterlleo Date: Fri, 22 May 2026 23:50:53 +0200 Subject: [PATCH 3/7] feat: print fmu type at start --- src/main/fmu_agent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/fmu_agent.cpp b/src/main/fmu_agent.cpp index baaf977..fbcb821 100644 --- a/src/main/fmu_agent.cpp +++ b/src/main/fmu_agent.cpp @@ -177,6 +177,7 @@ int main(int argc, char *const *argv) { } cout << " FMU file path: " << style::bold << fmu_path << style::reset << endl + << " FMU type: " << style::bold << ((plant.get_type() == 1) ? "Model Exchange" : "Co-Simulation") << style::reset << endl << " relative tol: " << style::bold << relative_tol << style::reset << endl << " absolutre tol: " << style::bold << absolute_tol << style::reset From 172e626027f3c2a645cc927dbbd0f34bf6cdd764 Mon Sep 17 00:00:00 2001 From: alterlleo Date: Fri, 22 May 2026 23:57:22 +0200 Subject: [PATCH 4/7] feat: runtime error for critical dt still not trigger mode --- src/FmuInstance.cpp | 6 ++++++ src/FmuInstance.hpp | 2 ++ src/main/fmu_agent.cpp | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/FmuInstance.cpp b/src/FmuInstance.cpp index 97c3174..aa4f12b 100644 --- a/src/FmuInstance.cpp +++ b/src/FmuInstance.cpp @@ -568,6 +568,12 @@ FmuWrapper::FmuWrapper(const std::string &fmu_path, string var_step; if(extract_xml_attribute(cs_tag, "canHandleVariableCommunicationStepSize", var_step)){ _fixed_step = !(var_step == "true" || var_step == "1"); + + std::string step_string; + if (extract_xml_attribute(cs_tag, "fixedInternalStepSize", step_string)) { + _step_size = std::stod(step_string); + } + } else{ _fixed_step = false; } diff --git a/src/FmuInstance.hpp b/src/FmuInstance.hpp index 64b9839..9f8ed92 100644 --- a/src/FmuInstance.hpp +++ b/src/FmuInstance.hpp @@ -98,6 +98,7 @@ class FmuWrapper { int get_type() const { return static_cast(_type); } bool get_fixed_step() const { return _fixed_step; } + double get_step_size() const { return _step_size; } struct SolverParams { double _rel_tol = 1e-6; @@ -131,6 +132,7 @@ class FmuWrapper { // FMU type variable FmuType _type = FmuType::Unknown; bool _fixed_step = false; + double _step_size = 0.0; /// Resolve variable name to value reference fmi3ValueReference resolve_var_ref(const std::string& name) const; diff --git a/src/main/fmu_agent.cpp b/src/main/fmu_agent.cpp index fbcb821..675766b 100644 --- a/src/main/fmu_agent.cpp +++ b/src/main/fmu_agent.cpp @@ -213,6 +213,7 @@ int main(int argc, char *const *argv) { auto last_timestep = chrono::steady_clock::now(); chrono::steady_clock::time_point now; double dt = 0, t = 0, t_in = 0, t_msg = 0; + int dtus = 0, stepus = 0; json status; array console_out; @@ -276,10 +277,17 @@ int main(int argc, char *const *argv) { // timing now = chrono::steady_clock::now(); if(plant.get_fixed_step()){ - dt = static_cast(period.count()) / 1e3; - } else{ - dt = chrono::duration_cast(now - last_timestep) - .count() / 1e6; + dt = static_cast(period.count()) / 1e3; + dtus = dt * 1e6; + stepus = plant.get_step_size() * 1e6; + if(dtus % stepus != 0){ // comparison in microseconds + + throw std::runtime_error("The agent period must be a multiple of the model's fixed step"); + } + + } else{ + dt = chrono::duration_cast(now - last_timestep) + .count() / 1e6; last_timestep = now; } From ec5f77f1c3d3c6d74a88cf1439576334c203b34b Mon Sep 17 00:00:00 2001 From: alterlleo Date: Sat, 23 May 2026 14:28:45 +0200 Subject: [PATCH 5/7] feat: trigger support fixed step solver dt measured starting from number of steps, buffer to limit drift --- src/main/fmu_agent.cpp | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/fmu_agent.cpp b/src/main/fmu_agent.cpp index 675766b..986f5d1 100644 --- a/src/main/fmu_agent.cpp +++ b/src/main/fmu_agent.cpp @@ -213,7 +213,8 @@ int main(int argc, char *const *argv) { auto last_timestep = chrono::steady_clock::now(); chrono::steady_clock::time_point now; double dt = 0, t = 0, t_in = 0, t_msg = 0; - int dtus = 0, stepus = 0; + int dtus = 0, step_s = 0; + static double t_buffer = 0.0; json status; array console_out; @@ -251,9 +252,32 @@ int main(int argc, char *const *argv) { agent.loop([&]() -> chrono::milliseconds { if (agent.receive(false) == message_type::json && agent.last_topic() != "control") { now = chrono::steady_clock::now(); + dt = chrono::duration_cast(now - last_timestep) - .count() / 1e6; + .count(); last_timestep = now; + + if(plant.get_fixed_step()){ + + t_buffer += dt; + step_s = plant.get_step_size() * 1e6; // us + + int num_steps = t_buffer / step_s; + if(num_steps > 0){ + dt = num_steps * step_s; // force dt + t_buffer -= dt; // t_buffer will contain the residual + } else{ + console_out[2] = "Skipped step: " + to_string(t_buffer) + "s"; + cout << goback(3) << fg::yellow << "Last message: " << console_out[0] + << fg::reset << endl + << "Received: " << console_out[1] << endl + << "Status update after: " << console_out[2] << endl + << "buffer: " << t_buffer << " dt: " << dt << endl; + return 0ms; + } + } + + dt = dt / 1e6; t += dt; console_out[2] = to_string(t) + " s"; plant.do_step(dt); @@ -279,8 +303,8 @@ int main(int argc, char *const *argv) { if(plant.get_fixed_step()){ dt = static_cast(period.count()) / 1e3; dtus = dt * 1e6; - stepus = plant.get_step_size() * 1e6; - if(dtus % stepus != 0){ // comparison in microseconds + step_s = plant.get_step_size() * 1e6; // us + if(dtus % step_s != 0){ // comparison in microseconds throw std::runtime_error("The agent period must be a multiple of the model's fixed step"); } From b97ab4441f2e2b7e1dac1d538674840a37de2de1 Mon Sep 17 00:00:00 2001 From: alterlleo Date: Sat, 23 May 2026 15:01:39 +0200 Subject: [PATCH 6/7] feat: add buffer and dt prints --- src/main/fmu_agent.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/fmu_agent.cpp b/src/main/fmu_agent.cpp index 986f5d1..9f0a4e1 100644 --- a/src/main/fmu_agent.cpp +++ b/src/main/fmu_agent.cpp @@ -290,10 +290,23 @@ int main(int argc, char *const *argv) { auto in = json::parse(get<1>(msg)); process_input(in); } - cout << goback(3) << fg::yellow << "Last message: " << console_out[0] - << fg::reset << endl - << "Received: " << console_out[1] << endl - << "Status update after: " << console_out[2] << endl; + + if(plant.get_fixed_step()){ + cout << goback(5) << fg::yellow << "Last message: " << console_out[0] + << fg::reset << endl + << "Received: " << console_out[1] << endl + << "Status update after: " << console_out[2] << endl + << "Buffer: " << t_buffer << "us" << endl + << "Simulation dt: " << dt << "s" << endl; + + } else{ + cout << goback(4) << fg::yellow << "Last message: " << console_out[0] + << fg::reset << endl + << "Received: " << console_out[1] << endl + << "Status update after: " << console_out[2] << endl + << "Simulation dt: " << dt << "s" << endl; + } + return 0ms; }); } else { From c919a8de971dfc7dbe9da2e278d0736afd284ae1 Mon Sep 17 00:00:00 2001 From: alterlleo Date: Sat, 23 May 2026 15:51:20 +0200 Subject: [PATCH 7/7] fix: remove buffer print --- src/main/fmu_agent.cpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/main/fmu_agent.cpp b/src/main/fmu_agent.cpp index 9f0a4e1..8a0ff24 100644 --- a/src/main/fmu_agent.cpp +++ b/src/main/fmu_agent.cpp @@ -291,21 +291,11 @@ int main(int argc, char *const *argv) { process_input(in); } - if(plant.get_fixed_step()){ - cout << goback(5) << fg::yellow << "Last message: " << console_out[0] - << fg::reset << endl - << "Received: " << console_out[1] << endl - << "Status update after: " << console_out[2] << endl - << "Buffer: " << t_buffer << "us" << endl - << "Simulation dt: " << dt << "s" << endl; - - } else{ - cout << goback(4) << fg::yellow << "Last message: " << console_out[0] - << fg::reset << endl - << "Received: " << console_out[1] << endl - << "Status update after: " << console_out[2] << endl - << "Simulation dt: " << dt << "s" << endl; - } + cout << goback(4) << fg::yellow << "Last message: " << console_out[0] + << fg::reset << endl + << "Received: " << console_out[1] << endl + << "Status update after: " << console_out[2] << endl + << "Simulation dt: " << dt << "s" << endl; return 0ms; });