diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 9a4ac22..0548819 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -17,25 +17,10 @@ jobs: strategy: fail-fast: false matrix: - include: - #- os: macos-latest - # release: R2024a - # products: > - # Simulink - # Simulink_Test - # Simulink_Coverage - # Simulink_Check - # Simulink_Coder - # Embedded_Coder - - os: ubuntu-22.04 - release: R2024a - products: > - Simulink - Simulink_Test - Simulink_Coverage - Simulink_Check - Simulink_Coder - Embedded_Coder + os: [ubuntu-22.04] + release: [R2024a, R2025a] + + # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -51,7 +36,13 @@ jobs: # MATLAB release to set up (R2021a or later) release: ${{matrix.release}} # Products to set up in addition to MATLAB, specified as a list of product names separated by spaces - products: ${{matrix.products}} + products: > + Simulink + Simulink_Test + Simulink_Coverage + Simulink_Check + Simulink_Coder + Embedded_Coder # Run the run_tests script in the root of the repo - name: Run script @@ -84,6 +75,16 @@ jobs: output: both thresholds: '40 60' + - name: upload artifact + uses: actions/upload-artifact@v4 + if: success() || failure() + with: + # Name of the artifact to upload. + # Optional. Default is 'artifact' + name: testreport${{matrix.release}} + path: ./testreport/* + retention-days: 30 + - name: Update Summary if: success() || failure() run: | diff --git a/readme.md b/readme.md index 8eb7c7e..6405854 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,12 @@ # Introduction to the Plasma Control System Simulation Platform (PCSSP) -PCSSP provides standardized methods for the design and assessment of modules and models for plasma control. It essentially provides you with a systematic framework to develop, test, integrate, and deploy controller and tokamak models. PCSSP relies on a git submodule called SCDDS to implement the Simulink functionality regarding data dictionaries and referenced models. Both PCSSP and SCDDS are developed under a GPL license. You are invited to contribute to both projects that ultimately will be merged into one toolbox for control development and deployment on tokamaks. +PCSSP provides standardized methods for the design and assessment of modules and models for plasma control. It essentially provides you with a systematic framework to develop, test, integrate, and deploy controller and tokamak models. PCSSP relies on a git submodule called SCDDS (Simulink-based Control Design & Deployment Suite) to implement the Simulink functionality regarding data dictionaries and referenced models. Both PCSSP and SCDDS are developed under a LGPL license. You are invited to contribute to both projects that ultimately will be merged into one toolbox for control development and deployment on tokamaks. ## Full documentation The full documentation of PCSSP is automatically deployed from its source code in this repository to readthedocs. You can find it [here](https://pcssp.readthedocs.io/en/latest/index.html) ## Directory structure: - configurations: Simulink configuration definitions for codegen and simulation -- scdds-core: git submodule (!) to handle data-dictionaries and module references in Simulink +- scdds: git submodule (!) to handle data-dictionaries and module references in Simulink - src: inherited PCSSP classes - testing: inherited PCSSP classes for testing modules - templates: pcssp examples @@ -19,7 +19,7 @@ The full documentation of PCSSP is automatically deployed from its source code i ## To run: ### (Only required for code generation): define an environment variable SCDDS_COREPATH to point to scdds-core in your ~/.bashrc. For example, on a typical linux system the path could be: -`export SCDDS_COREPATH="~/Documents/MATLAB/pcssp-nightly/scdds"` +`export SCDDS_COREPATH="~/Documents/MATLAB/pcssp/scdds"` ### Open Matlab on your system. On the ITER SDCC cluster you can for example type the following in a new terminal window: `module load intel MATLAB` @@ -31,7 +31,7 @@ The full documentation of PCSSP is automatically deployed from its source code i This will tell git to use the simulink 3-way merge tool to resolve merge conflicts in binary slx files. ### Navigate to the templates/ directory, and open one of the provided examples -Detailed documentation on how to develop your own PCSSP modules is not yet integrated in this repo, you can contact one of the lead developers below to obtain a PDF. +Detailed documentation on how to develop your own PCSSP modules is available on the [readthedocs](https://pcssp.readthedocs.io/en/latest/index.html) ### License This code is distributed under the `LGPL-v3` license. Copyright is retained by the ITER Organization. @@ -43,7 +43,7 @@ The authors would greatly appreciate it if the modifications are shared back to The above is a non binding summary of the legal text. The full and legally binding text is in the license file `LICENSE.md`. -Note that this software requires Matlab/Simulink, including toolboxes needed for C code generation (typically Embedded coder) and Simulink Test. Users must obtain their own licenses from Mathworks. +Note that this software requires Matlab/Simulink, including toolboxes needed for C code generation (typically Embedded coder) and Simulink Check, Test, Coder. Users must obtain their own licenses from Mathworks. ### Contributing The code is hosted on [https://github.com/iterorganization/pcssp](https://github.com/iterorganization/pcssp) and can be freely cloned. The Git submodule is hosted on [https://gitlab.epfl.ch/spc/scdds/scdds-core](https://gitlab.epfl.ch/spc/scdds/scdds-core) diff --git a/run_tests.m b/run_tests.m index 8f5ca0f..3293981 100644 --- a/run_tests.m +++ b/run_tests.m @@ -1,5 +1,6 @@ function results = run_tests() + % main script to initialize PCSSP and run all tests in batch % PCSSP - Plasma Control System Simulation Platform diff --git a/scdds b/scdds index 795f681..ef9f9e8 160000 --- a/scdds +++ b/scdds @@ -1 +1 @@ -Subproject commit 795f68191682b684c09dbd4b9d83925a64e427b9 +Subproject commit ef9f9e80e747650697b157f676f97010db774f64 diff --git a/templates/KMAG/test_PCSSP_KMAG.m b/templates/KMAG/test_PCSSP_KMAG.m index ae86a6b..4ded166 100644 --- a/templates/KMAG/test_PCSSP_KMAG.m +++ b/templates/KMAG/test_PCSSP_KMAG.m @@ -78,9 +78,9 @@ function run_verification_sim(testCase) u_base = timeseries(ulog.Data(:,ii),ulog.Time); - % remove first 1s transient before comparing - u_out = u_out.delsample('Index',[1:20]); - u_base = u_base.delsample('Index',[1:20]); + % % remove first 1s transient before comparing + % u_out = u_out.delsample('Index',[1:20]); + % u_base = u_base.delsample('Index',[1:20]); plot(u_out); hold on; plot(u_base); diff --git a/templates/PID_example/modules/TF/pcssp_TF_obj.m b/templates/PID_example/modules/TF/pcssp_TF_obj.m index 241f429..f5bfa9d 100644 --- a/templates/PID_example/modules/TF/pcssp_TF_obj.m +++ b/templates/PID_example/modules/TF/pcssp_TF_obj.m @@ -18,11 +18,12 @@ obj = obj.addbus('pcssp_PID_outBus', 'pcssp_PID_outBus_def' ); obj = obj.addbus('pcssp_TF_outBus', 'pcssp_TF_outBus_def' ); +%% link PID refdd for shared bus + +% obj = obj.addrefdd('pcssp_PID.sldd'); -%% Tasks -%% Print (optional) -obj.printinfo; +%% Tasks end diff --git a/templates/PID_example/modules/TF/pcssp_TF_test.m b/templates/PID_example/modules/TF/pcssp_TF_test.m index 13d4023..ee79c56 100644 --- a/templates/PID_example/modules/TF/pcssp_TF_test.m +++ b/templates/PID_example/modules/TF/pcssp_TF_test.m @@ -6,7 +6,7 @@ isCodegen = false; end - methods + methods(Test) function bla(testCase) end diff --git a/templates/PID_example/modules/sensor/pcssp_PID_sensor_test.m b/templates/PID_example/modules/sensor/pcssp_PID_sensor_test.m index 8aca2fa..add42c1 100644 --- a/templates/PID_example/modules/sensor/pcssp_PID_sensor_test.m +++ b/templates/PID_example/modules/sensor/pcssp_PID_sensor_test.m @@ -7,10 +7,7 @@ isCodegen = 0; % flag to trigger module tests for codeGen end - methods - function bla(testCase) - - end + methods(Test) end diff --git a/templates/cruise_control/controller/cruise_controller_load_fp.m b/templates/cruise_control/controller/cruise_controller_load_fp.m new file mode 100644 index 0000000..2dcc8c4 --- /dev/null +++ b/templates/cruise_control/controller/cruise_controller_load_fp.m @@ -0,0 +1,6 @@ +function [fp] = cruise_controller_load_fp(obj) + + +fp.timing = obj.gettiming; +end + diff --git a/templates/cruise_control/controller/cruise_controller_load_tp.m b/templates/cruise_control/controller/cruise_controller_load_tp.m new file mode 100644 index 0000000..d367c82 --- /dev/null +++ b/templates/cruise_control/controller/cruise_controller_load_tp.m @@ -0,0 +1,25 @@ +function [tp] = cruise_controller_load_tp() +%% function to define tunable parameters for the cruise controller + +%% define PID parameter for PID pcssp module for velocity control + +tp.Pvel = 3; +tp.Ivel =0; +tp.Dvel = 0; + +%% define Transfer function numerator and denominator for position control +tp.pos_num = [4320 -4.2772e+03]; +tp.pos_den = [1 -0.8931]; + +%% saturation limits +tp.pos_acc_saturation = 1000; +tp.neg_acc_saturation = -1000; + +%% controller constants +tp.switch_constant = 10; % distance between cars when to switch to pos control +tp.min_safety_distance= 5; % minimum safety distance between cars +tp.safe_time = 2; % safe time between cars + + +end + diff --git a/templates/cruise_control/controller/pcssp_cruise_controller.slx b/templates/cruise_control/controller/pcssp_cruise_controller.slx new file mode 100644 index 0000000..890654a Binary files /dev/null and b/templates/cruise_control/controller/pcssp_cruise_controller.slx differ diff --git a/templates/cruise_control/controller/pcssp_cruise_controller_obj.m b/templates/cruise_control/controller/pcssp_cruise_controller_obj.m new file mode 100644 index 0000000..782ea68 --- /dev/null +++ b/templates/cruise_control/controller/pcssp_cruise_controller_obj.m @@ -0,0 +1,15 @@ +function obj = pcssp_cruise_controller_obj() + + +obj = pcssp_module('pcssp_cruise_controller'); + +%% Timing of the algorithm +obj=obj.settiming(0,1e-3,10.0); + +%% Fixed parameters init functions +obj=obj.addfpinitfcn('cruise_controller_load_fp','cruise_controller_fp'); + +%% Tunable parameters structure name +obj=obj.addtunparamstruct('cruise_controller_tp', @()cruise_controller_load_tp()); + +end \ No newline at end of file diff --git a/templates/cruise_control/controller/pcssp_cruise_controller_test.m b/templates/cruise_control/controller/pcssp_cruise_controller_test.m new file mode 100644 index 0000000..e174529 --- /dev/null +++ b/templates/cruise_control/controller/pcssp_cruise_controller_test.m @@ -0,0 +1,26 @@ +classdef pcssp_cruise_controller_test < pcssp_module_test + % test for PCSSP_PID demo module + % see pcssp_module test class for all standard pcssp module tests + + properties + algoobj = @()pcssp_cruise_controller_obj(); + isCodegen = 1; % flag to trigger module tests for codeGen + end + + methods(Test) + function build_cruise_controller(testCase) + + obj = testCase.algoobj(); + obj.init; + obj.setup; + obj.build('auto'); + + obj.write_XML + + end + + end + + + +end \ No newline at end of file diff --git a/templates/cruise_control/cruise_control_run_topm.m b/templates/cruise_control/cruise_control_run_topm.m new file mode 100644 index 0000000..0029d48 --- /dev/null +++ b/templates/cruise_control/cruise_control_run_topm.m @@ -0,0 +1,35 @@ +%% main script to run the cruise control example + +% define PCSSP modules and top model class instances +[topm,obj_voiture,obj_controller] = cruise_control_topm_obj(); + +% initialize and setup all PCSSP models +topm.init; +topm.setup; + +%% compile and simulate + +topm.compile; +out = topm.sim; +simout = logsout2struct(out); + +%% plot + +h = tiledlayout(3,1,'TileSpacing','compact','Padding','compact'); + +h1 = nexttile; +plot(h1,simout.follower_position_position.Time,simout.follower_position_position.Values); +hold on; +plot(h1,simout.leader_position_position.Time,simout.leader_position_position.Values); +legend(h1,'follower position','leader position') + +h2 = nexttile; + +plot(h2,simout.velocity_error.Time,simout.velocity_error.Values); +legend(h2,'velocity error') + +h3 = nexttile; +plot(simout.controller_mode.Time,simout.controller_mode.Values); +legend(h3,'controller mode'); + +h.XLabel.String = 't (s)'; \ No newline at end of file diff --git a/templates/cruise_control/cruise_control_topm.slx b/templates/cruise_control/cruise_control_topm.slx new file mode 100644 index 0000000..74ebf2b Binary files /dev/null and b/templates/cruise_control/cruise_control_topm.slx differ diff --git a/templates/cruise_control/cruise_control_topm_obj.m b/templates/cruise_control/cruise_control_topm_obj.m new file mode 100644 index 0000000..9fed824 --- /dev/null +++ b/templates/cruise_control/cruise_control_topm_obj.m @@ -0,0 +1,17 @@ +function [topm,obj_voiture,obj_controller] = cruise_control_topm_obj() + +%% configure top model +topm = pcssp_top_class('cruise_control_topm'); + + +%% initialize PCSSP modules +obj_voiture = pcssp_Voiture_obj(); % input is the size of the inBus +obj_controller = pcssp_cruise_controller_obj(); + +%% add modules and wrappers to top model + +topm = topm.addmodule(obj_voiture); +topm = topm.addmodule(obj_controller); + + +end \ No newline at end of file diff --git a/templates/cruise_control/model/pcssp_Voiture.slx b/templates/cruise_control/model/pcssp_Voiture.slx new file mode 100644 index 0000000..1983c60 Binary files /dev/null and b/templates/cruise_control/model/pcssp_Voiture.slx differ diff --git a/templates/cruise_control/model/pcssp_Voiture_harness.slx b/templates/cruise_control/model/pcssp_Voiture_harness.slx new file mode 100644 index 0000000..bf457f2 Binary files /dev/null and b/templates/cruise_control/model/pcssp_Voiture_harness.slx differ diff --git a/templates/cruise_control/model/pcssp_Voiture_harness_run.m b/templates/cruise_control/model/pcssp_Voiture_harness_run.m new file mode 100644 index 0000000..7801e04 --- /dev/null +++ b/templates/cruise_control/model/pcssp_Voiture_harness_run.m @@ -0,0 +1,19 @@ +function out = pcssp_Voiture_harness_run(obj) + +% initialize object +obj.init; +obj.setup; + +% define waveforms +SimIn = Simulink.SimulationInput([obj.getname '_harness']); +ds = createInputDataset(obj.getname); + + +input.acceleration = timeseries(5*ones(1,2),[0 10]); +ds = setElement(ds,1,input,'acceleration'); + +SimIn = SimIn.setExternalInput(ds); + +out = sim(SimIn); + +end \ No newline at end of file diff --git a/templates/cruise_control/model/pcssp_Voiture_inBus_def.m b/templates/cruise_control/model/pcssp_Voiture_inBus_def.m new file mode 100644 index 0000000..cf3c926 --- /dev/null +++ b/templates/cruise_control/model/pcssp_Voiture_inBus_def.m @@ -0,0 +1,24 @@ +function [busNames, Buses] = pcssp_Voiture_inBus_def() + + busNames={}; + Buses={}; + + clear elems; + elems(1) = Simulink.BusElement; + elems(1).Name = 'acceleration'; + elems(1).Dimensions = 1; + elems(1).DimensionsMode = 'Fixed'; + elems(1).DataType = 'double'; + elems(1).SampleTime = -1; + elems(1).Complexity = 'real'; + elems(1).DocUnits = 'm/s^2'; + + pcssp_voiture_inBus = Simulink.Bus; + pcssp_voiture_inBus.Description = 'input acceleration for car model'; + pcssp_voiture_inBus.DataScope = 'Auto'; + pcssp_voiture_inBus.Elements = elems; + + busNames{1} = 'pcssp_voiture_inBus'; + Buses{1} = pcssp_voiture_inBus; + +end diff --git a/templates/cruise_control/model/pcssp_Voiture_loadfp.m b/templates/cruise_control/model/pcssp_Voiture_loadfp.m new file mode 100644 index 0000000..bdb67f9 --- /dev/null +++ b/templates/cruise_control/model/pcssp_Voiture_loadfp.m @@ -0,0 +1,6 @@ +function fp = pcssp_Voiture_loadfp(obj) + +%% store module timing in fixed parameter structure + +fp.timing = obj.gettiming; +end \ No newline at end of file diff --git a/templates/cruise_control/model/pcssp_Voiture_loadtp.m b/templates/cruise_control/model/pcssp_Voiture_loadtp.m new file mode 100644 index 0000000..8ca20e6 --- /dev/null +++ b/templates/cruise_control/model/pcssp_Voiture_loadtp.m @@ -0,0 +1,10 @@ +function TP = pcssp_Voiture_loadtp() +% Setup tunable control params default values for PCSSP car module in the +% cruise control example +% +TP.numerator = 1; +TP.denominator = [1e-2 1]; +TP.v0 = 0; +TP.s0 = 0; + +end diff --git a/templates/cruise_control/model/pcssp_Voiture_obj.m b/templates/cruise_control/model/pcssp_Voiture_obj.m new file mode 100644 index 0000000..797b51b --- /dev/null +++ b/templates/cruise_control/model/pcssp_Voiture_obj.m @@ -0,0 +1,22 @@ +function obj = pcssp_Voiture_obj() + +% example PCSSP module that implements a simple PID controller + +obj = pcssp_module('pcssp_Voiture'); + +%% Timing of the algorithm +obj=obj.settiming(0,1e-3,10.0); + +%% Fixed parameters init functions +obj=obj.addfpinitfcn('pcssp_Voiture_loadfp','pcssp_Voiture_fp'); + +%% Tunable parameters structure name +obj=obj.addtunparamstruct('pcssp_Voiture_tp', @()pcssp_Voiture_loadtp()); + + +%% Buses +obj = obj.addbus('', @() pcssp_Voiture_inBus_def()); +obj = obj.addbus('', @() pcssp_Voiture_outBus_def()); + +end + diff --git a/templates/cruise_control/model/pcssp_Voiture_outBus_def.m b/templates/cruise_control/model/pcssp_Voiture_outBus_def.m new file mode 100644 index 0000000..b20befa --- /dev/null +++ b/templates/cruise_control/model/pcssp_Voiture_outBus_def.m @@ -0,0 +1,32 @@ +function [busNames, Buses] = pcssp_Voiture_outBus_def() + + busNames={}; + Buses={}; + + clear elems; + elems(1) = Simulink.BusElement; + elems(1).Name = 'position'; + elems(1).Dimensions = 1; + elems(1).DimensionsMode = 'Fixed'; + elems(1).DataType = 'double'; + elems(1).SampleTime = -1; + elems(1).Complexity = 'real'; + elems(1).DocUnits = 'm'; + + elems(2) = Simulink.BusElement; + elems(2).Name = 'velocity'; + elems(2).Dimensions = 1; + elems(2).DimensionsMode = 'Fixed'; + elems(2).DataType = 'double'; + elems(2).SampleTime = -1; + elems(2).Complexity = 'real'; + elems(2).DocUnits = 'm/s'; + + + + pcssp_Voiture_outBus = Simulink.Bus; + pcssp_Voiture_outBus.Elements = elems; + + busNames{1} = 'pcssp_Voiture_outBus'; + Buses{1} = pcssp_Voiture_outBus; +end \ No newline at end of file diff --git a/templates/cruise_control/model/pcssp_Voiture_test.m b/templates/cruise_control/model/pcssp_Voiture_test.m new file mode 100644 index 0000000..d6e508a --- /dev/null +++ b/templates/cruise_control/model/pcssp_Voiture_test.m @@ -0,0 +1,14 @@ +classdef pcssp_Voiture_test < pcssp_module_test + % test for PCSSP_PID demo module + % see pcssp_module test class for all standard pcssp module tests + + properties + algoobj = @()pcssp_Voiture_obj(); + isCodegen = 0; % flag to trigger module tests for codeGen + end + + methods(Test) + + end + +end \ No newline at end of file diff --git a/templates/cruise_control/pcssp_cruise_control_topm_test.m b/templates/cruise_control/pcssp_cruise_control_topm_test.m new file mode 100644 index 0000000..f7ac038 --- /dev/null +++ b/templates/cruise_control/pcssp_cruise_control_topm_test.m @@ -0,0 +1,15 @@ +classdef pcssp_cruise_control_topm_test < pcssp_topmodel_test + + properties + topm = @()pcssp_closed_loop_obj(); + end + + methods(Test) + + + + end + + + +end \ No newline at end of file diff --git a/testing/UpgradeAdvisorR2025a.txt b/testing/UpgradeAdvisorR2025a.txt new file mode 100644 index 0000000..db8e843 --- /dev/null +++ b/testing/UpgradeAdvisorR2025a.txt @@ -0,0 +1 @@ +mathworks.design.CheckForProperFcnCallUsage,mathworks.design.CSStoVSSConvert,mathworks.design.ConvertMdlrefVarToVSS,mathworks.design.CheckAndUpdateOldMaskedBuiltinBlocks,mathworks.design.CheckMaskDisplayImageFormat,mathworks.design.CheckRapidAcceleratorSignalLogging,mathworks.design.CallsGetParamCompiledSampleTime,mathworks.design.CheckMaskRunInitFlag,mathworks.codegen.EfficientTunableParamExpr,mathworks.design.CheckExpFcnMdlSpecification,mathworks.design.CheckSingleSimulationOutput,mathworks.design.CheckSystemObjectUpdate,mathworks.design.CheckAndUpdateOldMaskTabnames,mathworks.design.emptyVariantObject,mathworks.design.ModelInfoKeywordSubstitution,mathworks.simulink.SB2SL.Check,mathworks.stateflow.ImportCustomCode.check,mathworks.design.CaseSensitiveBlockDiagramNames,mathworks.design.Update,mathworks.codegen.toolchainInfoUpgradeAdvisor.check,mathworks.codegen.CheckSupportedCompInstalled.check,mathworks.codegen.codertarget.check,mathworks.design.ReplaceEnvironmentControllerBlk,mathworks.design.CheckSLXFileCompressionLevel,mathworks.design.Sigbldr.upgradeCheck,mathworks.design.SLXModelProperties,mathworks.design.VirtualBusUsage,mathworks.design.UpdateRequireCompile,mathworks.design.CheckVirtualBusAcrossModelReference,mathworks.design.ModelLevelMessages,mathworks.design.ReplaceZOHDelayByRTB,mathworks.design.ParameterTuning,mathworks.design.MergeBlkUsage,com.mathworks.sorting.datastorecheck,mathworks.simulink.MLFBOutputDimensions,mathworks.design.CheckForSFcnUpgradeIssues,mathworks.design.InitParamOutportMergeBlk,mathworks.design.CheckConstRootOutportWithInterfaceUpgrade,mathworks.design.DiscreteBlock \ No newline at end of file diff --git a/testing/pcssp_module_test.m b/testing/pcssp_module_test.m index 959d59d..997ab06 100644 --- a/testing/pcssp_module_test.m +++ b/testing/pcssp_module_test.m @@ -29,7 +29,7 @@ end properties - + doUpgradeAdvisor end methods(TestClassSetup) @@ -40,7 +40,16 @@ function setup_paths(~) % function to setup desired paths end function define_testIDs(testCase) - testCase.checkIDlist = 'UpgradeAdvisorR2024a.txt'; + % grab current matlab release + matlab_version = matlabRelease().Release; + file_name = ['UpgradeAdvisor',char(matlab_version),'.txt']; + if exist(file_name,'file') == 2 % checkIDs are saved for this release + testCase.checkIDlist = file_name; + testCase.doUpgradeAdvisor = 1; + else + testCase.checkIDlist = ''; + testCase.doUpgradeAdvisor = 0; + end end end @@ -48,8 +57,7 @@ function define_testIDs(testCase) methods(TestMethodSetup) % empty for now function clear_workspaces_and_sldds(~) - disp('clearing workspace, models, and sldds'); - clear; + disp('clearing models and sldds'); bdclose all; Simulink.data.dictionary.closeAll('-discard') end @@ -63,7 +71,7 @@ function pcssp_ITER_codeGen_compliance(testCase) % module if testCase.isCodegen - checkIDs = readcell(testCase.checkIDlist); + checkIDs = readcell("checkinstanceIDs.txt"); result = run_model_advisor(testCase,checkIDs,'configurationSettingsAutocpp','configurations_container_pcssp.sldd'); % Print error flag to output testCase.verifyEqual(result.numFail,0); @@ -84,6 +92,20 @@ function pcssp_ITER_model_compliance(testCase) end + function run_upgrade_advisor(testCase) + + if testCase.doUpgradeAdvisor + fprintf('Running Upgrade Advisor checks for model %s\n', func2str(testCase.algoobj)) + checkIDs = readcell(testCase.checkIDlist); + result = run_model_advisor(testCase,checkIDs,'pcssp_Simulation','configurations_container_pcssp.sldd'); + testCase.verifyEqual(result.numFail,0); + + else + warning('No CheckIDs found, skipping Upgrade Advisor tests') + end + + end + function harness_SIL_run(testCase) module = testCase.algoobj(); diff --git a/tools/logsout2struct.m b/tools/logsout2struct.m index e9237c8..9ac63ef 100644 --- a/tools/logsout2struct.m +++ b/tools/logsout2struct.m @@ -26,9 +26,19 @@ for ii = 1:out.yout.numElements myElem = out.yout.getElement(ii); % grab Signal data + + % determine signal name + prefix_name = ''; + if any(myElem.Name=='<') % it's a bus, name not unique. Add the blockPath + % prefix_name = strrep(strrep(myElem.Name, '<' , ''), '>' , ''); + block_name = getBlock(myElem.BlockPath,1); + block_name = strsplit(block_name,'/'); + prefix_name = [block_name{end}, '_']; + prefix_name = strrep(prefix_name,' ',''); + end % convert timeseries object to structure - structout_yout = Simulink.SimulationData.forEachTimeseries(@(ts)write_structout(ts),myElem.Values); + structout_yout = Simulink.SimulationData.forEachTimeseries(@(ts)write_structout(ts,prefix_name),myElem.Values); field_nms = fieldnames(structout_yout); %grab names of signals @@ -56,7 +66,18 @@ for jj = 1:out.logsout.numElements myElem = out.logsout.getElement(jj); - structout_logsout = Simulink.SimulationData.forEachTimeseries(@(ts)write_structout(ts),myElem.Values); + + % determine signal name + prefix_name = ''; + if any(myElem.Name=='<') % it's a bus, name not unique. Add the blockPath + block_name = getBlock(myElem.BlockPath,1); + block_name = strsplit(block_name,'/'); + prefix_name = [block_name{end}, '_']; + prefix_name = strrep(prefix_name,' ','_'); + end + + + structout_logsout = Simulink.SimulationData.forEachTimeseries(@(ts)write_structout(ts,prefix_name),myElem.Values); field_nms = fieldnames(structout_logsout); @@ -82,17 +103,19 @@ %% Helper function -function structout = write_structout(ts) +function structout = write_structout(ts,prefix_name) +if any(ts.Name=='<') + ts_name = strrep(strrep(ts.Name, '<' , ''), '>' , ''); -% determine signal name -name = ts.Name; -if any(name=='<') - name = strrep(strrep(ts.Name, '<' , ''), '>' , ''); - +else + ts_name = ts.Name; + end -structout.(name).Time = ts.Time; -structout.(name).Values = ts.Data; +write_name = [prefix_name , ts_name]; + +structout.(write_name).Time = ts.Time; +structout.(write_name).Values = ts.Data; end