Saturday, March 18, 2017

Dealing with legacy Matlab code

A friend of mine has a project that works in Matlab Simulink 2007. He recently opened that simulink model in Matlab 2010 and could run it from Simulink without problems. But when he tried to transfer that model to xpc target for real time integration, the simulation hung and became unresponsive.

He and his team tried to find the problem by disabling Simulink blocks one at a time and in the end found the block that was causing problems. When they compared the 2007 version with the 2010 version, they could not find any differences which means that there is probably a backward compatibility issue that affects real time deployment. They had to manually recreate the whole model (more than hundred blocks) manually in Matlab 2010. Doing manual editing in code always carries the risk of breaking something. You might not know it unless you do tests with high coverage.

My first advice was to create a unit test framework so that you are sure that the new version yields the same outputs for the same inputs. A good strategy is to write scripts that vary inputs using unform distribution, run simulation on xpc target for every input, record outputs (or timeout when simulation hangs) and then compare outputs with previous results and create a report that highlights differences.

My second advice was to automate the update-to-newer-Matlab process by writing a program that automatically creates a new Simulink mdl file from the old one, beause it is easy to parse the mdl file which has an xml-look. Steps:
  1. Takes as input the depth of parsing. 1 = Copy the whole model. 2=Go one step deep and create separate mdl files for blocks in that depth 3=Go 2 steps deep etc.
  2. Parses the old Simulink mdl file and extracts the blocks
  3. Creates an mdl file in the new version format.
  4. Inserts the blocks into new mdl file(s)
  5. Runs unit tests on xpc target to see if the two versions have the same outputs (i.e. they are within 1e-15) neighborhood.
With this program, my friend can first check if for input depth =1, the model passes tests. If not, he can increase the depth until he can isolate the problem. Increasing depth on error could be automated too.

No comments: