mirror of
https://github.com/eclipse-openvehicle-api/openvehicle-api.git
synced 2026-02-05 07:18:44 +00:00
292 lines
8.2 KiB
C++
292 lines
8.2 KiB
C++
/**
|
|
* @file model.cpp
|
|
* @date 2025-09-12 15:01:57
|
|
* This file defines the data link object between CAN and the V-API devices.
|
|
* This file was generated by the DBC utility from:
|
|
* datalink_autoheadlight_example.dbc
|
|
* DBC file version: 1.0.0.1
|
|
*/
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <support/timer.h>
|
|
#include "signal_identifier.h"
|
|
#include <support/signal_support.h>
|
|
#include <support/app_control.h>
|
|
|
|
sdv::core::CSignal g_signalCurrent_Longitude;
|
|
sdv::core::CSignal g_signalCurrent_Latitude;
|
|
sdv::core::CSignal g_signalHeadLight_LowBeam;
|
|
|
|
// in case the simulation timer should be used
|
|
sdv::core::ITimerSimulationStep* g_pTimerSimulationStep;
|
|
|
|
std::unique_ptr<sdv::app::CAppControl> g_appcontrol;
|
|
|
|
bool InitializeAppControl(const std::string& resource, const std::string& configFileName)
|
|
{
|
|
auto bResult = g_appcontrol->AddModuleSearchDir( resource );
|
|
bResult &= g_appcontrol->Startup("");
|
|
g_appcontrol->SetConfigMode();
|
|
bResult &= g_appcontrol->AddConfigSearchDir( resource );
|
|
|
|
if (!configFileName.empty())
|
|
{
|
|
bResult &= g_appcontrol->LoadConfig(configFileName.c_str()) == sdv::core::EConfigProcessResult::successful;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
sdv::core::EConfigProcessResult RegisterAllSignals()
|
|
{
|
|
std::string msg = "register all signals: ";
|
|
sdv::core::CDispatchService dispatch;
|
|
|
|
g_signalCurrent_Longitude = dispatch.RegisterRxSignal("CAN_Input.Current_Longitude");
|
|
g_signalCurrent_Latitude = dispatch.RegisterRxSignal("CAN_Input.Current_Latitude");
|
|
g_signalHeadLight_LowBeam = dispatch.RegisterTxSignal("CAN_Output.HeadLight_LowBeam",0);
|
|
|
|
if (g_signalCurrent_Longitude && g_signalCurrent_Latitude && g_signalHeadLight_LowBeam)
|
|
{
|
|
return sdv::core::EConfigProcessResult::successful;
|
|
}
|
|
|
|
return sdv::core::EConfigProcessResult::failed;
|
|
}
|
|
|
|
bool ResetAllSignals()
|
|
{
|
|
sdv::core::CDispatchService dispatch;
|
|
|
|
if (g_signalCurrent_Longitude)
|
|
{
|
|
g_signalCurrent_Longitude.Reset();
|
|
}
|
|
if (g_signalCurrent_Latitude)
|
|
{
|
|
g_signalCurrent_Latitude.Reset();
|
|
}
|
|
if (g_signalHeadLight_LowBeam)
|
|
{
|
|
g_signalHeadLight_LowBeam.Reset();
|
|
}
|
|
|
|
SDV_LOG_INFO("Reset signals");
|
|
return true;
|
|
}
|
|
|
|
|
|
bool CreateCoreServiceTomlFile(const std::string& resources)
|
|
{
|
|
std::ofstream tomlFile("sdv_core_reloc.toml");
|
|
if (tomlFile.is_open())
|
|
{
|
|
tomlFile << "# Location of the SDV binaries and configuration files\ndirectory = \"";
|
|
tomlFile << resources;
|
|
tomlFile << "\"\n";
|
|
tomlFile.close();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool OpenAPILoad(const std::string& resources)
|
|
{
|
|
bool success = CreateCoreServiceTomlFile(resources);
|
|
g_appcontrol = std::make_unique<sdv::app::CAppControl> ();
|
|
|
|
//
|
|
// TODO: Dispatch service must be loaded first, adjust the correct toml file
|
|
//
|
|
success &= InitializeAppControl(resources, "data_dispatch_config_file.toml");
|
|
if (!success)
|
|
{
|
|
std::cout << "Error: InitializeAppControl() failed" << std::endl;
|
|
SDV_LOG_ERROR("Failed InitializeAppControl");
|
|
return false;
|
|
}
|
|
success &= RegisterAllSignals() == sdv::core::EConfigProcessResult::successful;
|
|
if (!success)
|
|
{
|
|
SDV_LOG_ERROR("Signals could not be registered");
|
|
}
|
|
|
|
//
|
|
//
|
|
// TODO: Load all configurations files
|
|
//
|
|
//
|
|
// Get the simulation task timer service if the simulation timer should be used
|
|
success &= g_appcontrol->LoadConfig("simulation_task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
|
|
g_pTimerSimulationStep = sdv::core::GetObject<sdv::core::ITimerSimulationStep>("SimulationTaskTimerService");
|
|
if (!g_pTimerSimulationStep)
|
|
{
|
|
SDV_LOG_WARNING("Simulation timer step not available, use normal task timer ");
|
|
success &= g_appcontrol->LoadConfig("task_timer_config_file.toml") == sdv::core::EConfigProcessResult::successful;
|
|
}
|
|
|
|
success &= g_appcontrol->LoadConfig("fmu_autoheadlight_vd_bs.toml") == sdv::core::EConfigProcessResult::successful;
|
|
success &= g_appcontrol->LoadConfig("fmu_autoheadlight_cs.toml") == sdv::core::EConfigProcessResult::successful;
|
|
|
|
g_appcontrol->SetRunningMode();
|
|
|
|
return success;
|
|
}
|
|
|
|
void OpenAPIShutdown()
|
|
{
|
|
ResetAllSignals();
|
|
}
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <float.h> // for DBL_EPSILON
|
|
#include <math.h> // for fabs()
|
|
#include "config.h"
|
|
#include "model.h"
|
|
|
|
Status cleanup(ModelInstance*)
|
|
{
|
|
SDV_LOG_INFO("Shutting down...");
|
|
OpenAPIShutdown();
|
|
return OK;
|
|
}
|
|
|
|
|
|
bool setStartValues(ModelInstance* comp)
|
|
{
|
|
std::string path(comp->resourceLocation);
|
|
std::string resourcePath = path.substr(8);
|
|
std::replace(resourcePath.begin(), resourcePath.end(), '\\', '/');
|
|
if (!OpenAPILoad(resourcePath))
|
|
{
|
|
std::cout << "Error: OpenAPILoad() failed." << std::endl;
|
|
comp->terminateSimulation = true;
|
|
return false;
|
|
}
|
|
|
|
// TODO: move this to initialize()?
|
|
comp->nextEventTime = 0;
|
|
comp->nextEventTimeDefined = true;
|
|
return true;
|
|
}
|
|
|
|
Status calculateValues(ModelInstance* comp)
|
|
{
|
|
UNUSED(comp);
|
|
// nothing to do
|
|
return OK;
|
|
}
|
|
|
|
Status getFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
|
|
{
|
|
ASSERT_NVALUES(1);
|
|
|
|
switch (vr)
|
|
{
|
|
case vr_Current_Longitude:
|
|
values[(*index)++] = M(Current_Longitude);
|
|
break;
|
|
case vr_Current_Latitude:
|
|
values[(*index)++] = M(Current_Latitude);
|
|
break;
|
|
|
|
default:
|
|
logError(comp, "Get Float64 is not allowed for value reference u.", vr);
|
|
return Error;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
Status getInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
|
|
{
|
|
ASSERT_NVALUES(1);
|
|
|
|
switch (vr)
|
|
{
|
|
case vr_HeadLight_LowBeam:
|
|
values[(*index)++] = M(HeadLight_LowBeam);
|
|
break;
|
|
|
|
default:
|
|
logError(comp, "Get Int32 is not allowed for value reference u.", vr);
|
|
return Error;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
Status setFloat64(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const double values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
|
|
{
|
|
ASSERT_NVALUES(1);
|
|
|
|
switch (vr)
|
|
{
|
|
case vr_Current_Longitude:
|
|
M(Current_Longitude) = values[(*index)++];
|
|
break;
|
|
case vr_Current_Latitude:
|
|
M(Current_Latitude) = values[(*index)++];
|
|
break;
|
|
|
|
default:
|
|
logError(comp, "Set Float64 is not allowed for value reference u.", vr);
|
|
return Error;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
Status setInt32(ModelInstance* comp, [[maybe_unused]] ValueReference vr, [[maybe_unused]] const int32_t values[], [[maybe_unused]] size_t nValues, [[maybe_unused]] size_t* index)
|
|
{
|
|
ASSERT_NVALUES(1);
|
|
|
|
switch (vr)
|
|
{
|
|
case vr_HeadLight_LowBeam:
|
|
M(HeadLight_LowBeam) = values[(*index)++];
|
|
break;
|
|
|
|
default:
|
|
logError(comp, "Set Int32 is not allowed for value reference u.", vr);
|
|
return Error;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
void eventUpdate(ModelInstance* comp)
|
|
{
|
|
|
|
if (g_pTimerSimulationStep) // in case the simulation timer was used, maybe the step size has to be adjusted
|
|
{
|
|
g_pTimerSimulationStep->SimulationStep(1000);
|
|
}
|
|
|
|
g_signalCurrent_Longitude.Write( M(Current_Longitude));
|
|
g_signalCurrent_Latitude.Write( M(Current_Latitude));
|
|
M(HeadLight_LowBeam) = g_signalHeadLight_LowBeam.Read().get<uint32_t>();
|
|
|
|
double epsilon = (1.0 + fabs(comp->time)) * DBL_EPSILON;
|
|
|
|
if (comp->nextEventTimeDefined && comp->time + epsilon >= comp->nextEventTime) {
|
|
comp->nextEventTime += FIXED_SOLVER_STEP;
|
|
}
|
|
|
|
comp->valuesOfContinuousStatesChanged = false;
|
|
comp->nominalsOfContinuousStatesChanged = false;
|
|
comp->terminateSimulation = false;
|
|
comp->nextEventTimeDefined = true;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
} // end of extern "C"
|
|
#endif
|
|
|