Bug #412
closedSimulink error: "[...] variable-size signal with a non-discrete sample time"
Description
Hello,
I have encountered an error when using matlab-genomix
and the genomix request block of the related Simulink library.
Here, the list of steps to reproduce the error.
- Take the genomix request
block.
- Set the timings
parameter value to either triggered(level)
or triggered(rising edge)
.
- Select a request
which takes at least one input argument.
- Add at least one of those input arguments to the list of signals
. In this way, suitable input ports are added to the block.
- Feed a continuous-time signal to at least one of those input arguments.
The produced error is as follows:
The signal at 'port Output <N>' of '<block>' is a variable-size signal with a non-discrete sample time. The sample time for any variable-size signal must be discrete.
where
<N>
is the number of the output port associated to the port errmsg
, and <block>
the genomix request block raising that error.
The issue seems to be connected to the fact that the port errmsg
has a variable size (see line 175 in genomix-mex.c) and the block sampling time is continuous, when the previous settings are used.
Reading line 205 of genomix-mex.c, the sample time is either set to INHERITED_SAMPLE_TIME
, if the timings
value is not periodic, or to a precise value (the one taken from the argument of the mask) if the timings
is periodic.
In the first case (INHERITED_SAMPLE_TIME
), Simulink takes as sampling time the one of the driving signals, ie those of the input ports. As at least one of them contains a continuous-time signal, then the sampling time is set internally to continuous.
In fact, if we replace the continuous-time signal with a discrete or infinite-time one, any problem arises.
Alternatively, to solve the issue, you can set the timings
to periodic. This enforces Simulink to use a specific sampling time (see line 211 of genomix-mex.c), which is most likely treated as discrete.
Of course, this issue does not occur when using a port
block because there are usually no input ports from which inheriting the sampling time.
This could cause a problem, if in future releases there would be the possibility to open and write to a port.
In attachment, you can find 3 Simulink files I realized for testing. Two show two working scenarios, while the third one shows the problem with the conditions listed above.
Here, a list of possible ideas I have to possibly fix this issue.- Set the output port
errmsg
to be fixed-size. Being the output signal no more variable-size, Simulink can then use any sample time without problems. However, it requires to write every time 255 bytes in the output port, which is less performant than writing just the actual length of the error message of the genomix request. - Use a discrete sampling time also in
triggered
mode. However, I think that this may create issues if the sampling time is not large enough to detect the triggers (high values) in the enabling signal. For instance, if the sampling time is 1s and in 1s the enabling signal transitions from low to high and then back to low, the block may not detect the trigger. So, this solution is not the best as the user should be aware of this aspect. - Simply let the user be aware of this problem, and feed to the genomix blocks only discrete-time signals. In this case, Simulink provides a ZOH block that works well in discretizing continuous-time signals.
I have currently fixed this issue adopting solution no.1. If you like this strategy, you can find my fix at https://redmine.laas.fr/projects/matlab-genomix/repository/matlab-genomix/revisions/efe207a6a6b279636f114bdc7ccdb4b2367ebdbc
Files
Updated by Gianluca Corsini 7 months ago
- Status changed from New to Closed
Applied in changeset matlab-genomix|f5fc03ba79e05a95ce0ad98ee1e65b339eb8509b.
Updated by Anthony Mallet 7 months ago
- Status changed from Closed to Feedback
Thanks!
I updated slightly your commit because it does not seem necessary to
reset all elements of the error message to 0. Only resetting the first
element in the error-free path is sufficient, as simulink treats
strings as NUL-terminated arrays, as in C.
If that's fine with you, I'll do a release soon.
Checked with 2023b.
Updated by Gianluca Corsini 7 months ago
Hi Anthony,
thanks a lot for integrating my fix.
Regarding your changes, I totally see. Actually, I was thinking to do the same, but then I changed only because I considered the following case.
In Simulink, it is possible to use the Display
block to visualize the content of any signal. In the case of the port errmsg
, it will display all the bytes. Thus, in the case of an error, it will display the message stored in that signal. Then, I thought what happens if the error disappear or changes? The current fix will only "reset" the first byte (if the error disappear) or copy the new error message (if the error changes), while the other bytes will remain the same. This, of course, it is not a problem if you display the errmsg
as a string into the matlab command window, as a null character will be found immediately, thus leading to an empty string. Instead, in Simulink, there will be a zero as first element, or new bytes in the first part, then the rest of the old message in the remaining part of the buffer. However, until now, I cannot figure out an example where this could occur at runtime :P
On the contrary, this will be not visible when running multiple times the Simulink scheme while fixing the issue, as the buffer will be re-initialized at every new run.
I am not sure whether I explained accurately this possible scenario. If so, what do you think about it? Shall we care about it?
Updated by Anthony Mallet 7 months ago
Ideally, this output port should directly be a string, but this is not
supported by simulink in S-functions.
But I would personnaly display the errmsg as a string (`ASCII ->
string` block), rather than the raw bytes array that is barely
human-readable. In this case the port is correctly interpreted as the
empty string iff the first byte is NUL.
Also, the 'request' block is currently hardcoded to not read the
replies (using 'oneway' genomix parameter) for performance reasons, so
you're right that during runtime the errmsg is unlikely to report any
error, unless something really wrong happens (e.g. shutting down
genomixd).
So all in all, I think saving 255 bytes copies for nearly every single
period of all blocks is worth the slight inconvenience of trailing
garbage that will like never happen :)
Updated by Anthony Mallet 7 months ago
Additionnaly, the previous error state of a block could be cached and
the errmsg port updated only if changed from the previous state (then
resetting all the 256 bytes could be an option).
Updated by Gianluca Corsini 7 months ago
I totally agree with everything :)
It was only to mention this possibility and have it noted somewhere ;)
I think we can close this issue.