Someone recently challenged me to convert the curling simulator we published a few years ago (See this post and this post) to take advantage of new features not available at that time: App Designer and Stateflow for MATLAB.
As you can guess, this is not the kind of challenge I can say no to!
You can find the final result here: The Curling Game App
Here is a diagram illustrating at a high level how the curling app is implemented:
If you download the app, here is a description of the files you will see:
- TestCurling.m: A test created using the App Testing Framework. This allows me to execute my app programmatically and validate that it behaves as expected.
- curling.mlapp: The main app.
- curlingLogic.sfx: The Stateflow chart where all the logic and actions of the app are defined.
- curlingSimulator.slx: A Simulink model simulating the dynamics of the stones on the ice.
- msfcn_showTrack.m and msfcnsweeper.m: MATLAB S-Function used in the Simulink model to animate the curling game in the app.
Let's now look at each part individually
As I mentioned in a previous post, Stateflow charts executed in MATLAB are very convenient to define the behavior of MATLAB apps. In such application, the MATLAB app itself only defines the graphical elements in the app, and maps apps callbacks to events in the Stateflow chart.
Here is what the app looks like in design view:
In terms of code, this is very simple. I simply define a startupFcn callback to instantiate the Stateflow Chart, where I pass to it a handle to the MATLAB app. Then for each item in the app (buttons, axes, etc), I define a callback that triggers an event in the Stateflow chart.
MATLAB Stateflow chart
This is where all the app functionalities are defined. Here is what it looks like:
This logic divides one throw in 4 states: waiting, pick a target, specify speed and spin, and throw. Transitions between each state are triggered by the app, and in each state I can interact with the app's components like I would do in MATLAB code. You will see more about how the stones are animated at the end of this post.
Once the user clicks the "Go" button in the app, the Stateflow chart starts the simulation and waits for it to finish. For that, I periodically check the simulation status using the after function.
For a few utilities that I needed in multiple places in the chart, I created MATLAB Functions inside Stateflow that I can call from multiple places in the chart. Here is an example function used every time I need to draw a new stone.
Compared to the version I described in my 2018 post, the Simulink model did not change much. The only item I had to modify was the MATLAB S-Function to animate the stones during the simulation.
For the S-Function to interact with the app, it needs a handle to it. Before starting the simulation, the Stateflow chart stores this handle to the app in the S-Function block userdata. That way, the S-function can retrieve it and set the position of the stones at every time step. Here is what the Output method looks like:
When developing an app like this one, it can be tedious to test and debug if you need to manually click the same series of buttons again and again. This is where the App Testing Framework comes into play.
I created a function that programmatically executes one throw. For that, the press method of the App Testing framework allows me to press a button or a specific location in the App.
Then in a test, I call this method with different targets and velocities. At the end, I verify that all the stones are where they are expected.
Here is what my screen looks like when I run the test. Notice the blue circle where the programmatic clicks are happening, along with the Stateflow animation, making it easy for me to validate that it is doing the right thing:
Now it's your turn
Download this latest version of The Curling Game App on MATLAB Central and let us know what you think in the comments below.