Skip to content

Commit f112c18

Browse files
pmaijdsika
authored andcommitted
Add auto-configuration to OSMPDummySensor example (#38)
* Remove cruft from spec for release, cleanup * Minor code cleanup for dummy source * Add auto configuration to OSMPDummySensor example
1 parent 14852f5 commit f112c18

File tree

7 files changed

+194
-54
lines changed

7 files changed

+194
-54
lines changed

.markdownlint.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"default": true,
3+
"MD003": { "style": "atx" },
4+
"MD007": { "indent": 4 },
5+
"MD013": false,
6+
"MD030": { "ol_multi": 3, "ul_multi": 3 }
7+
}

README.md

+17-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
OSI Sensor Model Packaging
2-
==========================
1+
# OSI Sensor Model Packaging
32

43
[![Build Status](https://travis-ci.org/OpenSimulationInterface/osi-sensor-model-packaging.svg?branch=master)](https://travis-ci.org/OpenSimulationInterface/osi-sensor-model-packaging)
54

@@ -362,26 +361,21 @@ model FMU with one input and output and no additional features:
362361
</fmiModelDescription>
363362
```
364363

365-
## TODOs
366-
367-
- Support various raw data streams, like e.g. video streams, or raw
368-
reflection lists, in the same vein as the current object list
369-
sensor data. This is likely to be achieved using the same
370-
basic mechanism, but including a string constant per input/output
371-
indicating the MIME type of the transported data (or some other
372-
naming scheme for the type), so that the variables can be
373-
identified properly. Can be merged with the above mechanism for
374-
auto configuration, if employed.
375-
376364
## Future Evolution
377365

378-
In the future an extension to the FMI standard that directly
379-
supported opaque binary data (e.g. a binary data type that
380-
is defined in the same way as the current string data type,
381-
but length terminated instead of zero-terminated) would allow
382-
migration of sensor models using the current convention to
383-
one where the sensor data input and output variables could be
384-
mapped into just one such input and output variable each, of
385-
the relevant binary type. The object lifetimes might need to
386-
be adjusted in such a case to match the FMI standard extension,
387-
depending on the form that is going to take.
366+
For FMI 3.0, which is currently in development, an opaque
367+
binary data type (a binary data type that is defined in the
368+
same way as the current string data type, but length terminated
369+
instead of zero-terminated) is planned to be added. This will
370+
allow migration of sensor models using the current convention to
371+
one where the relevant OSMP binary variables will be directly
372+
mapped to such new binary variables, instead of relying on the
373+
annotated trio of integer variables for each notional binary
374+
variable as is currently specified. The life-time of the new
375+
FMI 3.0 variables will be the standard life-time of all FMI
376+
variables, and thus shorter than is currently specified, so
377+
copying on input and output is going to be required. Other
378+
than that the current specification can be mapped 1:1 onto this
379+
new mechanism, and once FMI 3.0 is released, an updated OSMP
380+
specification including this option and mapping will be
381+
released.

examples/OSMPDummySensor/OSMPDummySensor.cpp

+92-18
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,34 @@ void encode_pointer_to_integer(const void* ptr,fmi2Integer& hi,fmi2Integer& lo)
100100
#endif
101101
}
102102

103+
bool COSMPDummySensor::get_fmi_sensor_view_config(osi3::SensorViewConfiguration& data)
104+
{
105+
if (integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_SIZE_IDX] > 0) {
106+
void* buffer = decode_integer_to_pointer(integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_BASELO_IDX]);
107+
normal_log("OSMP","Got %08X %08X, reading from %p ...",integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_BASELO_IDX],buffer);
108+
data.ParseFromArray(buffer,integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_SIZE_IDX]);
109+
return true;
110+
} else {
111+
return false;
112+
}
113+
}
114+
115+
void COSMPDummySensor::set_fmi_sensor_view_config_request(const osi3::SensorViewConfiguration& data)
116+
{
117+
data.SerializeToString(&currentConfigRequestBuffer);
118+
encode_pointer_to_integer(currentConfigRequestBuffer.data(),integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASELO_IDX]);
119+
integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_SIZE_IDX]=(fmi2Integer)currentConfigRequestBuffer.length();
120+
normal_log("OSMP","Providing %08X %08X, writing from %p ...",integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASELO_IDX],currentConfigRequestBuffer.data());
121+
swap(currentConfigRequestBuffer,lastConfigRequestBuffer);
122+
}
123+
124+
void COSMPDummySensor::reset_fmi_sensor_view_config_request()
125+
{
126+
integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_SIZE_IDX]=0;
127+
integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASEHI_IDX]=0;
128+
integer_vars[FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASELO_IDX]=0;
129+
}
130+
103131
bool COSMPDummySensor::get_fmi_sensor_view_in(osi3::SensorView& data)
104132
{
105133
if (integer_vars[FMI_INTEGER_SENSORVIEW_IN_SIZE_IDX] > 0) {
@@ -114,11 +142,11 @@ bool COSMPDummySensor::get_fmi_sensor_view_in(osi3::SensorView& data)
114142

115143
void COSMPDummySensor::set_fmi_sensor_data_out(const osi3::SensorData& data)
116144
{
117-
data.SerializeToString(&currentBuffer);
118-
encode_pointer_to_integer(currentBuffer.data(),integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX]);
119-
integer_vars[FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX]=(fmi2Integer)currentBuffer.length();
120-
normal_log("OSMP","Providing %08X %08X, writing from %p ...",integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX],currentBuffer.data());
121-
swap(currentBuffer,lastBuffer);
145+
data.SerializeToString(&currentOutputBuffer);
146+
encode_pointer_to_integer(currentOutputBuffer.data(),integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX]);
147+
integer_vars[FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX]=(fmi2Integer)currentOutputBuffer.length();
148+
normal_log("OSMP","Providing %08X %08X, writing from %p ...",integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX],integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX],currentOutputBuffer.data());
149+
swap(currentOutputBuffer,lastOutputBuffer);
122150
}
123151

124152
void COSMPDummySensor::reset_fmi_sensor_data_out()
@@ -128,6 +156,27 @@ void COSMPDummySensor::reset_fmi_sensor_data_out()
128156
integer_vars[FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX]=0;
129157
}
130158

159+
void COSMPDummySensor::refresh_fmi_sensor_view_config_request()
160+
{
161+
osi3::SensorViewConfiguration config;
162+
if (get_fmi_sensor_view_config(config))
163+
set_fmi_sensor_view_config_request(config);
164+
else {
165+
config.Clear();
166+
config.mutable_version()->CopyFrom(osi3::InterfaceVersion::descriptor()->file()->options().GetExtension(osi3::current_interface_version));
167+
config.set_field_of_view_horizontal(3.14);
168+
config.set_field_of_view_vertical(3.14);
169+
config.set_range(fmi_nominal_range()*1.1);
170+
config.mutable_update_cycle_time()->set_seconds(0);
171+
config.mutable_update_cycle_time()->set_nanos(20000000);
172+
config.mutable_update_cycle_offset()->Clear();
173+
osi3::GenericSensorViewConfiguration* generic = config.add_generic_sensor_view_configuration();
174+
generic->set_field_of_view_horizontal(3.14);
175+
generic->set_field_of_view_vertical(3.14);
176+
set_fmi_sensor_view_config_request(config);
177+
}
178+
}
179+
131180
/*
132181
* Actual Core Content
133182
*/
@@ -152,23 +201,38 @@ fmi2Status COSMPDummySensor::doInit()
152201
for (int i = 0; i<FMI_STRING_VARS; i++)
153202
string_vars[i] = "";
154203

204+
set_fmi_nominal_range(135.0);
155205
return fmi2OK;
156206
}
157207

158208
fmi2Status COSMPDummySensor::doStart(fmi2Boolean toleranceDefined, fmi2Real tolerance, fmi2Real startTime, fmi2Boolean stopTimeDefined, fmi2Real stopTime)
159209
{
160210
DEBUGBREAK();
161-
last_time = startTime;
211+
162212
return fmi2OK;
163213
}
164214

165215
fmi2Status COSMPDummySensor::doEnterInitializationMode()
166216
{
217+
DEBUGBREAK();
218+
167219
return fmi2OK;
168220
}
169221

170222
fmi2Status COSMPDummySensor::doExitInitializationMode()
171223
{
224+
DEBUGBREAK();
225+
226+
osi3::SensorViewConfiguration config;
227+
if (!get_fmi_sensor_view_config(config))
228+
normal_log("OSI","Received no valid SensorViewConfiguration from Simulation Environment, assuming everything checks out.");
229+
else {
230+
normal_log("OSI","Received SensorViewConfiguration for Sensor Id %llu",config.sensor_id().value());
231+
normal_log("OSI","SVC Ground Truth FoV Horizontal %f, FoV Vertical %f, Range %f",config.field_of_view_horizontal(),config.field_of_view_vertical(),config.range());
232+
normal_log("OSI","SVC Mounting Position: (%f, %f, %f)",config.mounting_position().position().x(),config.mounting_position().position().y(),config.mounting_position().position().z());
233+
normal_log("OSI","SVC Mounting Orientation: (%f, %f, %f)",config.mounting_position().orientation().roll(),config.mounting_position().orientation().pitch(),config.mounting_position().orientation().yaw());
234+
}
235+
172236
return fmi2OK;
173237
}
174238

@@ -194,19 +258,20 @@ void rotatePoint(double x, double y, double z,double yaw,double pitch,double rol
194258
fmi2Status COSMPDummySensor::doCalc(fmi2Real currentCommunicationPoint, fmi2Real communicationStepSize, fmi2Boolean noSetFMUStatePriorToCurrentPointfmi2Component)
195259
{
196260
DEBUGBREAK();
261+
197262
osi3::SensorView currentIn;
198263
osi3::SensorData currentOut;
199264
double time = currentCommunicationPoint+communicationStepSize;
200265
normal_log("OSI","Calculating Sensor at %f for %f (step size %f)",currentCommunicationPoint,time,communicationStepSize);
201266
if (get_fmi_sensor_view_in(currentIn)) {
202267
double ego_x=0, ego_y=0, ego_z=0;
203268
osi3::Identifier ego_id = currentIn.global_ground_truth().host_vehicle_id();
204-
normal_log("OSI","Looking for EgoVehicle with ID: %d",ego_id.value());
269+
normal_log("OSI","Looking for EgoVehicle with ID: %llu",ego_id.value());
205270
for_each(currentIn.global_ground_truth().moving_object().begin(),currentIn.global_ground_truth().moving_object().end(),
206271
[this, ego_id, &ego_x, &ego_y, &ego_z](const osi3::MovingObject& obj) {
207-
normal_log("OSI","MovingObject with ID %d is EgoVehicle: %d",obj.id().value(), obj.id().value() == ego_id.value());
272+
normal_log("OSI","MovingObject with ID %llu is EgoVehicle: %d",obj.id().value(), obj.id().value() == ego_id.value());
208273
if (obj.id().value() == ego_id.value()) {
209-
normal_log("OSI","Found EgoVehicle with ID: %d",obj.id().value());
274+
normal_log("OSI","Found EgoVehicle with ID: %llu",obj.id().value());
210275
ego_x = obj.base().position().x();
211276
ego_y = obj.base().position().y();
212277
ego_z = obj.base().position().z();
@@ -224,8 +289,9 @@ fmi2Status COSMPDummySensor::doCalc(fmi2Real currentCommunicationPoint, fmi2Real
224289
currentOut.add_sensor_view()->CopyFrom(currentIn);
225290

226291
int i=0;
292+
double actual_range = fmi_nominal_range()*1.1;
227293
for_each(currentIn.global_ground_truth().moving_object().begin(),currentIn.global_ground_truth().moving_object().end(),
228-
[this,&i,&currentIn,&currentOut,ego_id,ego_x,ego_y,ego_z](const osi3::MovingObject& veh) {
294+
[this,&i,&currentIn,&currentOut,ego_id,ego_x,ego_y,ego_z,actual_range](const osi3::MovingObject& veh) {
229295
if (veh.id().value() != ego_id.value()) {
230296
// NOTE: We currently do not take sensor mounting position into account,
231297
// i.e. sensor-relative coordinates are relative to center of bounding box
@@ -236,11 +302,11 @@ fmi2Status COSMPDummySensor::doCalc(fmi2Real currentCommunicationPoint, fmi2Real
236302
double rel_x,rel_y,rel_z;
237303
rotatePoint(trans_x,trans_y,trans_z,veh.base().orientation().yaw(),veh.base().orientation().pitch(),veh.base().orientation().roll(),rel_x,rel_y,rel_z);
238304
double distance = sqrt(rel_x*rel_x + rel_y*rel_y + rel_z*rel_z);
239-
if ((distance <= 150.0) && (rel_x/distance > 0.866025)) {
305+
if ((distance <= actual_range) && (rel_x/distance > 0.866025)) {
240306
osi3::DetectedMovingObject *obj = currentOut.mutable_moving_object()->Add();
241307
obj->mutable_header()->add_ground_truth_id()->CopyFrom(veh.id());
242308
obj->mutable_header()->mutable_tracking_id()->set_value(i);
243-
obj->mutable_header()->set_existence_probability(cos((distance-75.0)/75.0));
309+
obj->mutable_header()->set_existence_probability(cos((2.0*distance-actual_range)/actual_range));
244310
obj->mutable_header()->set_measurement_state(osi3::DetectedItemHeader_MeasurementState_MEASUREMENT_STATE_MEASURED);
245311
obj->mutable_header()->add_sensor_id()->CopyFrom(currentIn.sensor_id());
246312
obj->mutable_base()->mutable_position()->set_x(veh.base().position().x());
@@ -255,15 +321,15 @@ fmi2Status COSMPDummySensor::doCalc(fmi2Real currentCommunicationPoint, fmi2Real
255321
candidate->mutable_vehicle_classification()->CopyFrom(veh.vehicle_classification());
256322
candidate->set_probability(1);
257323

258-
normal_log("OSI","Output Vehicle %d[%d] Probability %f Relative Position: %f,%f,%f (%f,%f,%f)",i,veh.id().value(),obj->header().existence_probability(),rel_x,rel_y,rel_z,obj->base().position().x(),obj->base().position().y(),obj->base().position().z());
324+
normal_log("OSI","Output Vehicle %d[%llu] Probability %f Relative Position: %f,%f,%f (%f,%f,%f)",i,veh.id().value(),obj->header().existence_probability(),rel_x,rel_y,rel_z,obj->base().position().x(),obj->base().position().y(),obj->base().position().z());
259325
i++;
260326
} else {
261-
normal_log("OSI","Ignoring Vehicle %d[%d] Outside Sensor Scope Relative Position: %f,%f,%f (%f,%f,%f)",i,veh.id().value(),veh.base().position().x()-ego_x,veh.base().position().y()-ego_y,veh.base().position().z()-ego_z,veh.base().position().x(),veh.base().position().y(),veh.base().position().z());
327+
normal_log("OSI","Ignoring Vehicle %d[%llu] Outside Sensor Scope Relative Position: %f,%f,%f (%f,%f,%f)",i,veh.id().value(),veh.base().position().x()-ego_x,veh.base().position().y()-ego_y,veh.base().position().z()-ego_z,veh.base().position().x(),veh.base().position().y(),veh.base().position().z());
262328
}
263329
}
264330
else
265331
{
266-
normal_log("OSI","Ignoring EGO Vehicle %d[%d] Relative Position: %f,%f,%f (%f,%f,%f)",i,veh.id().value(),veh.base().position().x()-ego_x,veh.base().position().y()-ego_y,veh.base().position().z()-ego_z,veh.base().position().x(),veh.base().position().y(),veh.base().position().z());
332+
normal_log("OSI","Ignoring EGO Vehicle %d[%llu] Relative Position: %f,%f,%f (%f,%f,%f)",i,veh.id().value(),veh.base().position().x()-ego_x,veh.base().position().y()-ego_y,veh.base().position().z()-ego_z,veh.base().position().x(),veh.base().position().y(),veh.base().position().z());
267333
}
268334
});
269335
normal_log("OSI","Mapped %d vehicles to output", i);
@@ -284,6 +350,7 @@ fmi2Status COSMPDummySensor::doCalc(fmi2Real currentCommunicationPoint, fmi2Real
284350
fmi2Status COSMPDummySensor::doTerm()
285351
{
286352
DEBUGBREAK();
353+
287354
return fmi2OK;
288355
}
289356

@@ -304,7 +371,7 @@ COSMPDummySensor::COSMPDummySensor(fmi2String theinstanceName, fmi2Type thefmuTy
304371
functions(*thefunctions),
305372
visible(!!thevisible),
306373
loggingOn(!!theloggingOn),
307-
last_time(0.0)
374+
simulation_started(false)
308375
{
309376
loggingCategories.clear();
310377
loggingCategories.insert("FMI");
@@ -385,6 +452,7 @@ fmi2Status COSMPDummySensor::EnterInitializationMode()
385452
fmi2Status COSMPDummySensor::ExitInitializationMode()
386453
{
387454
fmi_verbose_log("fmi2ExitInitializationMode()");
455+
simulation_started = true;
388456
return doExitInitializationMode();
389457
}
390458

@@ -405,6 +473,7 @@ fmi2Status COSMPDummySensor::Reset()
405473
fmi_verbose_log("fmi2Reset()");
406474

407475
doFree();
476+
simulation_started = false;
408477
return doInit();
409478
}
410479

@@ -429,10 +498,15 @@ fmi2Status COSMPDummySensor::GetReal(const fmi2ValueReference vr[], size_t nvr,
429498
fmi2Status COSMPDummySensor::GetInteger(const fmi2ValueReference vr[], size_t nvr, fmi2Integer value[])
430499
{
431500
fmi_verbose_log("fmi2GetInteger(...)");
501+
bool need_refresh = !simulation_started;
432502
for (size_t i = 0; i<nvr; i++) {
433-
if (vr[i]<FMI_INTEGER_VARS)
503+
if (vr[i]<FMI_INTEGER_VARS) {
504+
if (need_refresh && (vr[i] == FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASEHI_IDX || vr[i] == FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASELO_IDX || vr[i] == FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_SIZE_IDX)) {
505+
refresh_fmi_sensor_view_config_request();
506+
need_refresh = false;
507+
}
434508
value[i] = integer_vars[vr[i]];
435-
else
509+
} else
436510
return fmi2Error;
437511
}
438512
return fmi2OK;

examples/OSMPDummySensor/OSMPDummySensor.h

+23-5
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,19 @@ using namespace std;
5353
#define FMI_INTEGER_SENSORDATA_OUT_BASELO_IDX 3
5454
#define FMI_INTEGER_SENSORDATA_OUT_BASEHI_IDX 4
5555
#define FMI_INTEGER_SENSORDATA_OUT_SIZE_IDX 5
56-
#define FMI_INTEGER_COUNT_IDX 6
56+
#define FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASELO_IDX 6
57+
#define FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_BASEHI_IDX 7
58+
#define FMI_INTEGER_SENSORVIEW_CONFIG_REQUEST_SIZE_IDX 8
59+
#define FMI_INTEGER_SENSORVIEW_CONFIG_BASELO_IDX 9
60+
#define FMI_INTEGER_SENSORVIEW_CONFIG_BASEHI_IDX 10
61+
#define FMI_INTEGER_SENSORVIEW_CONFIG_SIZE_IDX 11
62+
#define FMI_INTEGER_COUNT_IDX 12
5763
#define FMI_INTEGER_LAST_IDX FMI_INTEGER_COUNT_IDX
5864
#define FMI_INTEGER_VARS (FMI_INTEGER_LAST_IDX+1)
5965

6066
/* Real Variables */
61-
#define FMI_REAL_LAST_IDX 0
67+
#define FMI_REAL_NOMINAL_RANGE_IDX 0
68+
#define FMI_REAL_LAST_IDX FMI_REAL_NOMINAL_RANGE_IDX
6269
#define FMI_REAL_VARS (FMI_REAL_LAST_IDX+1)
6370

6471
/* String Variables */
@@ -194,18 +201,29 @@ class COSMPDummySensor {
194201
fmi2Integer integer_vars[FMI_INTEGER_VARS];
195202
fmi2Real real_vars[FMI_REAL_VARS];
196203
string string_vars[FMI_STRING_VARS];
197-
double last_time;
198-
string currentBuffer;
199-
string lastBuffer;
204+
bool simulation_started;
205+
string currentOutputBuffer;
206+
string lastOutputBuffer;
207+
string currentConfigRequestBuffer;
208+
string lastConfigRequestBuffer;
200209

201210
/* Simple Accessors */
202211
fmi2Boolean fmi_valid() { return boolean_vars[FMI_BOOLEAN_VALID_IDX]; }
203212
void set_fmi_valid(fmi2Boolean value) { boolean_vars[FMI_BOOLEAN_VALID_IDX]=value; }
204213
fmi2Integer fmi_count() { return integer_vars[FMI_INTEGER_COUNT_IDX]; }
205214
void set_fmi_count(fmi2Integer value) { integer_vars[FMI_INTEGER_COUNT_IDX]=value; }
215+
fmi2Real fmi_nominal_range() { return real_vars[FMI_REAL_NOMINAL_RANGE_IDX]; }
216+
void set_fmi_nominal_range(fmi2Real value) { real_vars[FMI_REAL_NOMINAL_RANGE_IDX]=value; }
206217

218+
207219
/* Protocol Buffer Accessors */
220+
bool get_fmi_sensor_view_config(osi3::SensorViewConfiguration& data);
221+
void set_fmi_sensor_view_config_request(const osi3::SensorViewConfiguration& data);
222+
void reset_fmi_sensor_view_config_request();
208223
bool get_fmi_sensor_view_in(osi3::SensorView& data);
209224
void set_fmi_sensor_data_out(const osi3::SensorData& data);
210225
void reset_fmi_sensor_data_out();
226+
227+
/* Refreshing of Calculated Parameters */
228+
void refresh_fmi_sensor_view_config_request();
211229
};

0 commit comments

Comments
 (0)