Skip to content

Commit 6d64e00

Browse files
authored
C/Python scenario rework (#77)
1 parent 3e29fc2 commit 6d64e00

3 files changed

Lines changed: 155 additions & 30 deletions

File tree

ecospy/EcosSimulation.py

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,72 @@ def remove_listener(self, name: str):
173173
"""
174174
self._remove_listener(self.sim, name.encode())
175175

176+
def add_scenario(self, scenario_config: str = None, real_actions: list[tuple] = None, integer_actions: list[tuple] = None,
177+
boolean_actions: list[tuple] = None,
178+
string_actions: list[tuple] =None):
179+
"""
180+
Add a scenario to the simulation.
181+
Args:
182+
scenario_config (str, optional): Optional scenario configuration XML file.
183+
real_actions (list of tuples): List of real actions as (time_point, identifier, value).
184+
integer_actions (list of tuples): List of integer actions as (time_point, identifier, value).
185+
boolean_actions (list of tuples): List of boolean actions as (time_point, identifier, value).
186+
string_actions (list of tuples): List of string actions as (time_point, identifier, value).
187+
"""
188+
189+
listener = None
190+
if scenario_config is not None:
191+
load_scenario = dll.ecos_scenario_load
192+
load_scenario.argtypes = [c_char_p]
193+
load_scenario.restype = c_void_p
194+
listener = load_scenario(str.encode("utf-8"))
195+
196+
else:
197+
create_scenario = dll.ecos_scenario_create
198+
create_scenario.restype = c_void_p
199+
listener = create_scenario()
200+
201+
if listener is None:
202+
raise ValueError("Unable to create/load scenario: " + EcosLib.get_last_error())
203+
204+
if real_actions is not None:
205+
for action in real_actions:
206+
scenario_add_real_action = dll.ecos_scenario_add_real_action
207+
scenario_add_real_action.argtypes = [c_void_p, c_double, c_char_p, c_double]
208+
scenario_add_real_action.restype = c_bool
209+
210+
time_point, identifier, value = action
211+
scenario_add_real_action(listener, time_point, identifier.encode("utf-8"), value)
212+
213+
if integer_actions is not None:
214+
for action in integer_actions:
215+
scenario_add_integer_action = dll.ecos_scenario_add_real_action
216+
scenario_add_integer_action.argtypes = [c_void_p, c_double, c_char_p, c_int]
217+
scenario_add_integer_action.restype = c_bool
218+
219+
time_point, identifier, value = action
220+
scenario_add_integer_action(listener, time_point, identifier.encode("utf-8"), value)
221+
222+
if boolean_actions is not None:
223+
for action in boolean_actions:
224+
scenario_add_boolean_action = dll.ecos_scenario_add_real_action
225+
scenario_add_boolean_action.argtypes = [c_void_p, c_double, c_char_p, c_bool]
226+
scenario_add_boolean_action.restype = c_bool
227+
228+
time_point, identifier, value = action
229+
scenario_add_boolean_action(listener, time_point, identifier.encode("utf-8"), value)
230+
231+
if string_actions is not None:
232+
for action in string_actions:
233+
scenario_add_string_action = dll.ecos_scenario_add_real_action
234+
scenario_add_string_action.argtypes = [c_void_p, c_double, c_char_p, c_char_p]
235+
scenario_add_string_action.restype = c_bool
236+
237+
time_point, identifier, value = action
238+
scenario_add_string_action(listener, time_point, identifier.encode("utf-8"), value.encode("utf-8"))
239+
240+
self._add_listener(self.sim, b'scenario', listener)
241+
176242
def add_csv_writer(self, result_file: str, csv_config: str = None, identifiers: list[str] = None,
177243
decimation_factor: int = None):
178244
"""
@@ -208,21 +274,6 @@ def add_csv_writer(self, result_file: str, csv_config: str = None, identifiers:
208274

209275
self._add_listener(self.sim, b'csv_writer', listener)
210276

211-
def load_scenario(self, scenario_file: str):
212-
"""
213-
Load a scenario file into the simulation.
214-
Args:
215-
scenario_file (str): Path to the scenario file to load.
216-
Raises:
217-
Exception: If loading the scenario fails in the underlying library.
218-
"""
219-
_load_scenario = dll.ecos_simulation_load_scenario
220-
_load_scenario.argtypes = [c_void_p, c_char_p]
221-
_load_scenario.restype = c_bool
222-
223-
if not _load_scenario(self.sim, scenario_file.encode()):
224-
raise Exception(EcosLib.get_last_error())
225-
226277
def get_integer(self, identifier: str):
227278
val = c_int()
228279
if not self._get_integer(self.sim, identifier.encode(), byref(val)):

include/ecos/ecos.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66

77
/* Visibility macros */
88
#if defined(_WIN32) || defined(__CYGWIN__)
9-
#define LIBECOS_API __declspec(dllexport)
9+
# define LIBECOS_API __declspec(dllexport)
1010
#else
11-
#define LIBECOS_API __attribute__((visibility("default")))
11+
# define LIBECOS_API __attribute__((visibility("default")))
1212
#endif
1313

1414
#ifdef __cplusplus
@@ -75,7 +75,6 @@ LIBECOS_API bool ecos_simulation_terminate(ecos_simulation_t* sim);
7575
LIBECOS_API bool ecos_simulation_reset(ecos_simulation_t* sim);
7676
LIBECOS_API void ecos_simulation_destroy(ecos_simulation_t* sim);
7777

78-
LIBECOS_API bool ecos_simulation_load_scenario(ecos_simulation_t* sim, const char* scenario_file);
7978
// -------------
8079

8180
// simulation_runner
@@ -101,12 +100,21 @@ typedef struct ecos_simulation_listener_config
101100

102101
LIBECOS_API ecos_simulation_listener_t* ecos_simulation_listener_create(ecos_simulation_listener_config config);
103102

103+
//Note: this function transfers ownership of listener to simulation
104104
LIBECOS_API void ecos_simulation_add_listener(ecos_simulation_t* sim, const char* name, ecos_simulation_listener_t* listener);
105105
LIBECOS_API void ecos_simulation_remove_listener(ecos_simulation_t* sim, const char* name);
106+
106107
LIBECOS_API ecos_simulation_listener_t* ecos_csv_writer_create(const char* resultFile, const char* csvConfig = nullptr);
107108
LIBECOS_API bool ecos_csv_writer_set_decimation_factor(ecos_simulation_listener_t* writer, int decimationFactor);
108109
LIBECOS_API bool ecos_csv_writer_register_variable(ecos_simulation_listener_t* writer, const char* identifier);
109110

111+
LIBECOS_API ecos_simulation_listener_t* ecos_scenario_create();
112+
LIBECOS_API ecos_simulation_listener_t* ecos_scenario_load(const char* scenario_file);
113+
LIBECOS_API bool ecos_scenario_add_int_action(ecos_simulation_listener_t* s, double timePoint, const char* identifier, int value, double eps = 1e-9);
114+
LIBECOS_API bool ecos_scenario_add_real_action(ecos_simulation_listener_t* s, double timePoint, const char* identifier, double value, double eps = 1e-9);
115+
LIBECOS_API bool ecos_scenario_add_bool_action(ecos_simulation_listener_t* s, double timePoint, const char* identifier, bool value, double eps = 1e-9);
116+
LIBECOS_API bool ecos_scenario_add_string_action(ecos_simulation_listener_t* s, double timePoint, const char* identifier, const char* value, double eps = 1e-9);
117+
110118
LIBECOS_API void ecos_plot_csv(const char* csvFile, const char* chartConfig);
111119
// -------------
112120

src/ecos/ecos.cpp

Lines changed: 78 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct ecos_parameter_set
5252
ecos::parameter_set cpp_parameter_set;
5353
};
5454

55+
5556
void handle_current_exception()
5657
{
5758
try {
@@ -565,18 +566,6 @@ ecos_simulation_listener_t* ecos_simulation_listener_create(ecos_simulation_list
565566
return l.release();
566567
}
567568

568-
bool ecos_simulation_load_scenario(ecos_simulation_t* sim, const char* scenario_file)
569-
{
570-
try {
571-
auto scenario = ecos::scenario::load(scenario_file);
572-
sim->cpp_sim->add_listener("scenario", std::move(scenario));
573-
return true;
574-
} catch (...) {
575-
handle_current_exception();
576-
return false;
577-
}
578-
}
579-
580569
ecos_simulation_runner_t* ecos_simulation_runner_create(ecos_simulation_t* sim)
581570
{
582571
auto runner = std::make_unique<ecos_simulation_runner_t>(sim);
@@ -606,3 +595,80 @@ void ecos_simulation_runner_destroy(const ecos_simulation_runner_t* runner)
606595
runner = nullptr;
607596
}
608597
}
598+
599+
ecos_simulation_listener_t* ecos_scenario_create()
600+
{
601+
try {
602+
auto scenario = std::make_unique<ecos_simulation_listener_t>();
603+
scenario->cpp_listener = std::make_unique<ecos::scenario>();
604+
return scenario.release();
605+
} catch (...) {
606+
handle_current_exception();
607+
return nullptr;
608+
}
609+
}
610+
611+
612+
ecos_simulation_listener* ecos_scenario_load(const char* scenario_file)
613+
{
614+
try {
615+
auto scenario = std::make_unique<ecos_simulation_listener>();
616+
scenario->cpp_listener = ecos::scenario::load(scenario_file);
617+
return scenario.release();
618+
} catch (...) {
619+
handle_current_exception();
620+
return nullptr;
621+
}
622+
}
623+
624+
bool ecos_scenario_add_int_action(ecos_simulation_listener* s, double timePoint, const char* identifier, int value, double eps)
625+
{
626+
try {
627+
auto scenario = dynamic_cast<ecos::scenario*>(s->cpp_listener.get());
628+
scenario->add_action<int>(timePoint, identifier, value, eps);
629+
return true;
630+
631+
} catch (...) {
632+
handle_current_exception();
633+
return false;
634+
}
635+
}
636+
637+
bool ecos_scenario_add_real_action(ecos_simulation_listener* s, double timePoint, const char* identifier, double value, double eps)
638+
{
639+
try {
640+
auto scenario = dynamic_cast<ecos::scenario*>(s->cpp_listener.get());
641+
scenario->add_action<double>(timePoint, identifier, value, eps);
642+
return true;
643+
644+
} catch (...) {
645+
handle_current_exception();
646+
return false;
647+
}
648+
}
649+
650+
bool ecos_scenario_add_bool_action(ecos_simulation_listener* s, double timePoint, const char* identifier, bool value, double eps)
651+
{
652+
try {
653+
auto scenario = dynamic_cast<ecos::scenario*>(s->cpp_listener.get());
654+
scenario->add_action<bool>(timePoint, identifier, value, eps);
655+
return true;
656+
657+
} catch (...) {
658+
handle_current_exception();
659+
return false;
660+
}
661+
}
662+
663+
bool ecos_scenario_add_string_action(ecos_simulation_listener* s, double timePoint, const char* identifier, const char* value, double eps)
664+
{
665+
try {
666+
auto scenario = dynamic_cast<ecos::scenario*>(s->cpp_listener.get());
667+
scenario->add_action<std::string>(timePoint, identifier, value, eps);
668+
return true;
669+
670+
} catch (...) {
671+
handle_current_exception();
672+
return false;
673+
}
674+
}

0 commit comments

Comments
 (0)