How can I pass variable-sized structured inputs to s-function blocks from C or C++ s-functions so the data can be easily accessed in Simulink blocks?

I would like to receive data in Simulink as a Simulink bus, where I am sending data to my block from some structures, which the bus is composed from; several of these buses have variable length nested buses in them (see the illustrative example below). While I would like to use Simulink buses since they provide a pretty straight-forward way of providing access to data in a well-organized hierarchy, they do appear to have limitations. In fact it appears to me that there is no good way to have variable-sized arrays of buses where the sizes are known at runtime other than the terrible workaround of specifying maximum sizes (which works but is wasteful and not scalable).
Does anyone have suggestions on what I could try to do to support variable-sized buses as inputs and/or outputs for Simulink s-functions?
I have some data that my Level 2 s-function is receiving as a set of protobufs. Some of these protos have elements with variable lengths. As an example:
// Illustration of a simple structure that we want to pass to Simulink (SimulinkInput) that has some
// hierarchical encoding of contents.
// Note how we do not have any restriction on the number of these collections (there is an array of arrays of elements)
// grouped together within the message that we want to send to Simulink.
// It is important that blocks in Simulink can then easily make use of this data appropriately.
message PolarPoint {
double r = 1;
double theta = 2;
double value = 3;
}
message PolarData {
repeated PolarPoint points = 1;
}
message SimulinkInput {
repeated PolarData polar_state = 1;
// In my own system, I have many such collections, several of which might have unspecified
// lengths prior to starting the simulation. i.e. we only know the length of these internal
// arrays of structures at runtime, not apriori.
}
My initial thought was to use C-structs and the legacy_code tool to pass in data to Simulink like this example: Using buses with legacy functions having structure arguments. But it appears that I can't use buses with pointers to an element such that Simulink can easily work with this.
Trying to create a bus with a variable number of inputs does not appear to work - Matlab crashes on me if the structure has a pointer to a structure during generation itself.
typedef struct PolarPoint {
double r, theta, value;
} PolarPoint_t;
typedef struct PolarData {
int num_points; // Number of points in polar_points
PolarPoint_t *polar_points; // Would ideally point to a buffer that might be in a PWork vector
} PolarData_t;
typedef struct SimulinkInput {
int num_polar_states; // Number of polar states
PolarData_t **polar_states; // Would ideally point to a different buffer in the PWork vector that points to other vectors.
} SimulinkInput_t;
Instead if I define the structure like so, legacy_code produces a bus that I can use in a fairly straight-forward way.
#define MAX_NUM_POINTS 1024
#define MAX_POLAR_STATES 10
typedef struct PolarData {
int num_points;
PolarPoint_t polar_points[MAX_NUM_POINTS];
} PolarData_t;
typedef struct SimulinkInput {
int num_polar_states;
PolarData_t polar_states[MAX_POLAR_STATES];
} SimulinkInput_t;
Unfortunately, this obviously results in a major waste of space since I have to always over-allocate space for everything even if we are unlikely to get that much data to begin with.
The ideal situation would be for me to be able to use variable-length nested structures (hand-coding parts of this for now are fine by me), so that I can work with Simulink buses without needing to hard-code the sizes of these buses before starting the simulation.

Answers (0)

Products

Release

R2020a

Asked:

on 10 Aug 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!