Generate Code That Preserves RUL Model State for System Restart
This example shows how to generate code for predicting remaining useful life (RUL) that preserves the state of the RUL model when the prediction algorithm is stopped and restarted. This example builds on the workflow shown in Generate Code for Predicting Remaining Useful Life.
The workflow of this example is useful for degradation-based RUL models, linearDegradationModel
and exponentialDegradationModel
. With these models, you can use the update
command to update the RUL model with incoming data during system operation, as described in Update RUL Prediction as Data Arrives. When you perform such an update in a deployed prediction algorithm, on system shutdown, you risk losing any updates you made to the model during operation. This example shows how to write an entry-point function to preserve updates made to the model at run time. To do so, incorporate the readState
and restoreState
commands into the entry-point function.
Fit RUL Model
Before generating code for RUL prediction, you must fit an RUL model using historical data. For this example, load the data in linTrainTables.mat
. This file contains measurements of some condition indicator taken over time, organized into tables with column labels "Time"
and "Condition"
. Use this data to train a linear degradation model. (For more information about configuring and training this type of RUL model, see linearDegradationModel
.)
load('linTrainTables.mat') mdl = linearDegradationModel; fit(mdl,linTrainTables,"Time","Condition")
Prepare Model for Code Generation
As described in Generate Code for Predicting Remaining Useful Life, to prepare the model for code generation, use saveRULModelForCoder
to store the RUL model as a data structure in a MAT file. Later, in the entry-point function, you use loadRULModelForCoder
to load and reconstruct the linearDegradationModel
object.
saveMATfilename = 'savedModel.mat';
saveRULModelForCoder(mdl,saveMATfilename);
Optionally, you can update the model parameters using additional data collected after the training data. For this example, load linTestData1
, which is a 121-row table of times and condition-indicator values. Use the first two entries in this table to update the model.
load('linTestData.mat','linTestData1') updateData = linTestData1(1:2,:); update(mdl,updateData);
Next, read the model state using readState
. This command converts the RUL model object into a structure that you can pass to the entry-point function as an input argument.
savedState = readState(mdl);
Define Entry-Point Function
The entry-point function is the function for which you want to generate code. For this example, create the entry-point function degradationRULPreserveState.m
, as shown here.
type degradationRULPreserveState.m
function [estRULOut,ciOut,newState] = degradationRULPreserveState(data,restoreStateFlag,savedState) %#codegen persistent mdl % Load the model the first time function is called if isempty(mdl) mdl = loadRULModelForCoder('savedModel'); end % Restore the saved model parameters if needed if restoreStateFlag restoreState(mdl,savedState); end % Update model and prediction with new data threshold = 60; update(mdl,data); [estRULOut,ciOut] = predictRUL(mdl,threshold); % Read the updated model parameters newState = readState(mdl); end
This function updates the RUL prediction model using the update
command each time it is called with new input data. Declaring mdl
as a persistent
variable preserves the updated model parameters between calls while the function remains in memory. This function writes the updated model parameters to the output argument newState
. Save this value outside the entry-point function to preserve the updated model state when the function is cleared from memory. Thus, for example, when restarting the prediction algorithm after a system shutdown, you can set restoreStateFlag
to true
and pass in the most recently saved state value as savedState
, ensuring that the system resumes prediction using the most recently updated model parameters.
Generate Code
To generate code, you must provide sample data having the data type and format of each input argument expected by the entry-point function. For this example, use the next row in linTestData1
. Also, set restoreStateFlag
to the logical value true
.
sampleData = linTestData1(3,:); restoreStateFlag = true;
Now you can generate code using the following codegen
(MATLAB Coder) command. The list of variables {sampleData,restoreStateFlag,savedState}
tells the codegen
command that the function takes as arguments a table row consisting of a time and a numerical value, a logical value, and a structure of the form savedState
, as returned by readState
.
codegen degradationRULPreserveState -args {sampleData,restoreStateFlag,savedState} -nargout 3
Code generation successful.
This command generates a MEX file, which is an executable that you can call from within MATLAB®. You can use procedures similar to this example to generate code for any other target that codegen
supports. Alternatively, you can use the MATLAB Coder™ app, as shown in Generate Code for Predicting Remaining Useful Life.
Validate the Generated Code
To validate the generated code, at the MATLAB command prompt, run the entry-point MATLAB function on the sample data. Then, run the generated MEX file on the same data and confirm that the results are the same.
[estRUL,ci,newState] = degradationRULPreserveState(sampleData,restoreStateFlag,savedState); [estRUL_mex,ci_mex,newState_mex] = degradationRULPreserveState_mex(sampleData,restoreStateFlag,savedState);
For example, compare the estimated RUL obtained with the MATLAB function and the generated MEX file.
estRUL,ci
estRUL = 113.8920
ci = 1×2
83.0901 172.5393
estRUL_mex,ci_mex
estRUL_mex = 113.8920
ci_mex = 1×2
83.0901 172.5393
You can now use the generated code as part of your deployed system for predicting remaining useful life. Store the value of newState
to use when you need to restart the system. For example, take the next data point in linTestData1
and use it to update the prediction, starting with newState_mex
, the model state generated in the previous call to the MEX file.
nextData = linTestData1(4,:); [estRUL2_mex,ci2_mex,newState2_mex] = degradationRULPreserveState_mex(nextData,restoreStateFlag,newState_mex); estRUL2_mex,ci2_mex
estRUL2_mex = 104.4336
ci2_mex = 1×2
77.8216 154.1263
Note that the MATLAB function and the MEX file each manage their own persistent variables. Therefore, the MEX file value of mdl
now incorporates the update from nextData
, which the function value of mdl
does not. To reset the values of these persistent variables, explicitly clear the function and the MEX file from memory.
clear degradationRULPreserveState clear degradationRULPreserveState_mex
See Also
loadRULModelForCoder
| saveRULModelForCoder
| readState
| restoreState
| linearDegradationModel
| exponentialDegradationModel
| covariateSurvivalModel
| reliabilitySurvivalModel
| pairwiseSimilarityModel
| hashSimilarityModel
| residualSimilarityModel