|
Modelica Assignment
|
Practical Information
GoalsIn this assignment, you will use the Modelica Language to first create a model of a Cyber-Physical System (CPS) and then create a controller for optimal control of the CPS. You will learn:
You are discouraged but allowed to make use of any GenAI tool in solving the assignment or writing the report (for example, to correct grammatical mistakes) as long as you adhere to the UA Guidelines for students on responsible use of GenAI.
You are required to cite any use of GenAI and describe what portions of the assignment you used it for. Note that a significant part of demonstrating that the learning goals have been achieved, includes being able to
This will be evaluated in a short (~15 minute) individual oral evaluation, which will typically be conducted in the week following the deadline of every assignment. OpenModelicaYou will use OpenModelica to perform all the tasks. You can install the latest stable version of OpenModelica on your systems by following the directions by going to the OpenModelica website > Download > Windows/Linux/Mac (based on your OS). Choose the 'Official Release' package. Installing OpenModelica installs a number of applications in your system: OMEditThe OpenModelica Connection Editor (OMEdit) is the standard graphical user interface that is used for graphical Modelica model creation and editing. We will use OMEdit for all the tasks. Launch instructions and other features of OMEdit are described on the OMEdit website. OMEdit has 4 different views but we are only interested in the Modelling and Plotting views. We will primarily use OMEdit to design the model. Information about the other OpenModelica applications are just given for information. Modelica Standard LibraryA major advantage of using Modelica is the availability of a wide variety of Modelica libraries, making it easier to re-use blocks and classes from these libraries. For the assignment, you should ensure, once you have installed OpenModelica, that the Modelica Standard Library (MSL) package is also correctly downloaded, and automatically loaded when you start OMEdit. To do so, go to File > Manage Libraries > Install Library > select Modelica with Version 4.0.0 > OK. The Modelica Standard Library should be visible when you restart OMEdit. OMNotebookOMNotebook is a notebook-like tool to learn the usage of OpenModelica and construct more-readable documentation which incorporates code-windows in between text. Think of Jupyter Notebooks. OMShellOMShell is an interactive session handler that parses and interprets commands and Modelica expressions for evaluation, simulation, plotting, etc. The session handler also contains simple history facilities, and completion of file names and certain identifiers in commands. We will not use OMShell because we want to learn and visualize graphically the models that we are building. Hence we will only use OMEdit. We will use Python because we can then directly use the data obtained from simulations for analysis through a number of data analysis packages available in Python. One thing to note is that a Modelica model needs to be compiled only once. Once compiled, the parameters can be changed in subsequent executions/simulation runs without having to re-compile the model. This is advantageous since compilation can prove to be a significant overhead if we are optimising for a number of different parameters and ranges (read: the number of simulation runs could go into the tens of thousands or more, when using simulation for the purpose of optimization). BasicsWhile the Modelica language and its capabilities of object-oriented acausal modeling of the multi-physics have already been described in the lectures, what follows is a 'how-to' to get started building your own Modelica models for the assignment using OMEdit. On the left of the OMEdit window is the Libraries pane which displays all the libraries that have been loaded in the current Modelica session. Modelica models are organised in Packages which can contain other packages and Modelica classes. Create a Modelica Package![]() Figure 1: Example package creation. Go to File > New > New Modelica Class > in the Create New Modelica Class dialog box > enter a valid package name > for Specialization, select Package, this is also shown in Fig.1 > OK. You should now see your Modelica package in the Libraries pane. You should save it before proceeding further by clicking on the corresponding icon in the menu bar or going to File > Save. If you have already created and saved a package, you can load it in the current session by going to File > Open Model/Library Files, and choosing the corresponding file in the file browser. Create your first Modelica ModelRight click on your Modelica package in the Libraries window > in the drop-down menu > select New Modelica Class > in the create New Modelica Class dialog box > enter a valid class name > for Specialization, select Model > for Insert in class ensure the textbox specifies the Modelica package within which you want to create your Modelica model > OK. You have created your first Modelica model! You should save it before proceeding further by clicking on the corresponding icon in the menu bar or going to File > Save. Modelica classes can extend other Modelica classes, i.e. inherit the declarations from the extended class. They may also simply re-use components defined in other Modelica classes. Build/Edit your Modelica ModelDouble click on the Modelica model you want to edit. This takes you to the Modeling view. In the top right corner of the Modeling view are 3 buttons to toggle between different editing interfaces. The 2nd button is to open the graphical editor and the 3rd button is to open the textual editor. ![]() Figure 2: Buttons to change editor views. The Icon view is only used to arrange connector points for a block. The diagram view can only be used in case the model consists of blocks with causal/acausal connections between them. Look at the Modelica By Example website for simple introductory examples of Modelica models based on simple Ordinary Differential Equations of physics. If you are making a component-based model. You can add components to the model by dragging them from the Libraries pane onto the graphical editor. You will be prompted to give the component a unique name. You can draw connections between the interfaces of components by holding the left mouse button while simultaneously moving it from one interface ot the other. This highly intuitive. You can modify parameters of the components by double-clicking on them, which will open the Element Parameters box. Simulate your Modelica Model in OMEdit![]() Figure 3: 'Check Model' and 'Simulation' buttons in OMEdit. Once you have defined a complete and correct Modelica model, you can now simulate it. To do so, you should click on the S icon in the menu bar. This opens the Simulation Setup dialog box. You can set simulation parameters in this dialog box. Make sure that you have verified the simulation start time, stop time, step-size/number of intervals, solver method (DASSL is preferred), and tolerance (the default 1e-6 is good enough, as low as possible is preferred ideally). You can also set the output format to output the data to a file. However, we do not need to do so, since we will later perform simulations through Python where we will handle the simulation output directly. This is just for visualization and initial validation of the model. Click OK to begin simulation. Note: You can also 'check' the model by clicking on the tick-mark icon in the menu bar. The output from this can be observed in the message browser. The message browser will tell you if something is missing in the model, or if there are inconsistencies in the model. Visualize simulation traceClicking OK in the Simulation Setup ideally takes you to the Plotting view. If not, you can go to the plotting view through the corresponding tab in the bottom-right corner. On the right you will see the variable browser. You can select any variable/s to plot them in the pane and observe their values over the simulation. The values indicated in the variables pane is the value of that variable at the end of the simulation. Parametrizing simulation quantities in OMEditTo define a parameter you simply have to use the 'parameter' keyword followed by its unit name and default value in this syntax: parameter <unit> <name> = <default value> ;If you want to parametrize a quantity which is a parameter of a block in your model. Simply double-click on the block in the graphical editor and change the parameter value to the parameter name. This value need not be a numeric quantity, but it can be a reference to the name of the parameter within the model, or a function of the parameter as well. Once you have changed the value in the block, go to the textual editor of your model (not of the block!), and use the same syntax as above to define a parameter. Note that the name of this parameter should correspond to the name of the parameter you have defined in the value of the block. Look at the following image for an example: ![]() Figure 4: Parametrizing the values of the block-parameters of the blocks in your model. Multiple simulations and analyses of your Modelica modelThe example Python file contained in the zip file describes how to use Python to simulate and visualize data from an example Modelica model which will be introduced in the tutorial as well. We will perform multiple simulations by generating the executable through OMEdit. You should make sure that the executable is generated and not deleted in the right directory by:
To generate these files, once the settings mentioned above are correctly configured, you should simulate the model in OMEdit at least once. To re-simulate your model, but not from OMEdit, you can simply use the terminal command to execute the executable which is in a subdirectory of the working directory as described above. This subdirectory is named 'package_name.model_name' and the executable in this subdirectory is executed with the command './model_name' (in Linux). For the example, it will be './NewtonCooling'. Note that you should change the current directory of the terminal session to the example/NewtonCooling/ directory before doing so. This cannot be done from within the example/ directory. The simulation results will be stored in the same directory as the executable. By default, it is a MAT-file, and you should try to use the same because it is the most efficient (compared to CSV, etc.). At the end of each simulation you should read the MAT-file, and record the variables that you are interested in before performing the next simulation, because this file will be overwritten during re-simulation. You can read the MAT-files generated by OpenModelica using the read_mat_file() function in the example code! To re-simulate the model, but with different parameters, you can use command line as well. You simply have to structure your command using the -override flag, as the following './model_name -override parameter1=value, parameter2=value ..'.This is also described and demonstrated in the example code. To implement a loop over the parameter values, you will have to write a Python script. You can execute shell commands using the os package as demonstrated in the example. Take special note that os.changeDir function is used to change the working directory of the virtual shell to the results directory. Assignment Overview
This assignment consists of five main parts:
Each part is aligned with one of the learning goals Problem StatementVehicle suspension systems are critical components that ensure passenger comfort and vehicle stability by isolating the cabin from road irregularities. A well-designed suspension system must balance multiple objectives: maintaining ride height, minimizing vibrations transmitted to passengers, and ensuring that accelerations stay within comfort limits defined by automotive standards. ![]() Figure 5: Simplified illustration of a car suspension system, taken from this paper. Modern active suspension systems use actuators that can apply controlled forces to adapt the suspension characteristics in real-time. However, these actuators often exhibit nonlinear behavior due to the physics of their spring and damper elements. Accurate modeling of these nonlinearities is essential for designing effective controllers and predicting real-world performance. In this assignment, you will work with a quarter-car model that includes:
The goal is to design and tune a controller for the active suspension system such that:
Actuator Model CreationYou are the control engineer and the designer/scientist/client has given you the information below. Your task is to model the whole system using the information given below, in Modelica. Special care should be taken to parametrize the model correctly. The first step will always be to make an appropriately named Modelica package. This will serve as the package for your entire Modelica assignment. You SHOULD create NEW models ONLY within this package, for each part of the entire assignment. The actuator sits between the wheel assembly and the car body. It consists of a spring and a damper in parallel, together with an electro-mechanical actuator that can apply an additional force $F_{act}(t)$ on command of the controller. Both the spring and the damper of this actuator behave nonlinearly: the spring stiffens when it is compressed or extended far from its natural length, and the damper resists fast motion more strongly than slow motion. We describe both effects with a cubic term added to the usual linear term. The manufacturer of the actuator has provided us with the equations that describe its behavior. The actuator is a one-dimensional element with two ends, and its behavior only depends on the relative displacement and relative velocity between these two ends. They are: $$ s_{rel}(t) = s_b(t) - s_a(t) $$ $$ v_{rel}(t) = \frac{d}{dt} s_{rel}(t) $$ $$ f_{spring}(t) = c_1 \cdot \left(s_{rel}(t) - s_{rel,0}\right) + c_2 \cdot \left(s_{rel}(t) - s_{rel,0}\right)^3 $$ $$ f_{damper}(t) = d_1 \cdot v_{rel}(t) + d_2 \cdot \left(v_{rel}(t)\right)^3 $$ $$ f(t) = f_{spring}(t) + f_{damper}(t) + F_{act}(t) $$ Where:
Note that the actuator is not a stand-alone system. It must be connected to other physical components (the wheel and the car body) and to a control signal (from the controller). In Modelica, this is done through connectors. Our actuator has three of them:
Note that the designers of the mechanical domain part of the Modelica Standard Library have chosen to use position and force in a mechanical interface (known as pin in the electrical domain and flange in the mechanical domain), rather than velocity and force (with product = power), which would be more elegant and consistent with the interfaces in other physical domains. In the mechanical domain, historically, position and force were used. The force f(t) inside the actuator acts on both of its ends, equally and in opposite directions (Newton's third law). Following the sign convention of the Modelica.Mechanics.Translational library of the MSL, this is expressed with the following two equations: $$ f_a(t) = -f(t) $$ $$ f_b(t) = f(t) $$ where $f_a$ and $f_b$ are the forces of flange_a and flange_b respectively. This means that a positive $f$ (for example, when the spring is stretched beyond its natural length) pulls the two ends of the actuator towards each other. You are referred to the documentation of Modelica.Mechanics.Translational.Interfaces to learn more about translational connectors. Have a look in particular at PartialCompliant, which is the base class that the MSL uses for its own springs and dampers. TasksYou are the engineer and the manufacturer has given you the information above. Your task is to model the actuator as a re-usable Modelica block, using the information given above. Special care should be taken to parametrize the block correctly.
Note: A block on its own cannot be simulated, since nothing is connected to its connectors. You will test your block in the next part of the assignment, when you connect it to a calibration experiment. BEWARE! Often customer requirements will be given in multiple units as in the above (for example metres and centimetres). It is your task to unify and express them all in a single unitary system so that your solution is numerically correct. The recommended way is to use SI units in all cases. BONUS: for explicitly specifying the units of all the variables and parameters in your Modelica model by reusing definitions from the MSL. BONUS: for explicitly describing each parameter and variable with comments in your Modelica code. Note: There are many assumptions in our model, for example, that the actuator is massless, that its force is applied instantaneously, and that it has no limits on its stroke or on the force it can apply. Actuator Model CalibrationYou have successfully created an abstract model of the actuator, but it is not complete. Remember the nonlinear coefficients $c_2$ and $d_2$ that the manufacturer did not provide? These are parameters that cannot be estimated either by measurement (for example, weighing a component to determine its the mass) or by computation from the design (for example, if weighing is not possible, by using a model of the geometry and the mass density of the component). How will you determine their values so that your model truly represents reality? This is done through parameter estimation, also known as model calibration (though the two are often mixed and described as parameter calibration). The idea is that we try (combinations of) different parameter values, and compare the output of the simulation of the Modelica model with data obtained from measurements on the real system. The parameters, which give the least error (the smallest "distance") between the two traces are said to be the best fit, and are chosen accordingly. Note that this implicitly assumes that the model structure is correct. An exhaustive way of finding optimal parameter values is to loop over possible values for the parameters to find the combination that gives the closest match mentioned above. This is known as a parameter sweep. From the manufacturer, we already know that:
Hence, we need to find the nonlinear coefficients $c_2$ and $d_2$. We cannot perform two separate experiments in which the effect of one of the coefficients is nullified: as soon as the actuator moves, both the spring and the damper produce a force. Hence, both coefficients must be estimated together, from a single experiment, by sweeping over all combinations of $c_2$ and $d_2$. Experimental setupIn the real-world experiment, the actuator was removed from the car and mounted on a test bench:
The real life-data from the experiment is provided in this csv file. This data represents the measured force $f$ in the actuator (in Newtons), sampled every $2$ milliseconds, for $2$ seconds. As with any real measurement, the data contains some noise. ![]() Figure 6: Imposed length of the actuator (top), and measured force in the actuator (bottom), in the real-life calibration experiment. TasksThe main purpose of this part of the assignment is finding the nonlinear coefficients $c_2$ and $d_2$ of the actuator, based on experimental data (i.e., observations/measurements on the real system).
BEWARE! The csv data has a few more data-points than you would expect from a time step of $0.002$ seconds for $2$ seconds. This is because OpenModelica adds extra data-points at events, i.e. at $t = 1 s$ and $t = 2 s$, where the interpolation in the table changes. If your model is set up as described above, your simulation trace will have exactly the same time-stamps as the csv data. Plant Model CreationNow that you have a calibrated model of the actuator, you will model the rest of the car and its passenger, i.e. the plant. In contrast to the actuator, you will build the plant using the graphical editor in OMEdit, by connecting blocks from the Modelica.Mechanics.Translational package of the Modelica Standard Library, together with your own actuator block. TIP: Have a look at the documentation and the examples section in the Modelica.Mechanics.Translational package to learn how to use the different components. This is important to understand how to set the parameters for the different components. The general assumptions are as follows:
The Modelica.Mechanics.Translational.Components.Mass block does not include gravitational force on the mass. Since we have six bodies that are all subject to gravity, we provide you with a re-usable block that combines a mass with its weight, in this Modelica file. Copy the gravity_mass block into your assignment package, for example by pasting its code into the textual view of your package, just before the end of the package. You can access the internal mass of a gravity_mass block using the dot-notation, for example head.mass.s, head.mass.v, and head.mass.a for the position, velocity, and acceleration of a block named head. The passenger is modelled with a simplified biomechanical model, which divides the human body into four masses (lower body, upper torso, arms, and head), connected to each other by spring-dampers that represent the muscles and joints. The passenger sits on a seat on the car body, which is connected to the wheel by the actuator that you created earlier. The wheel touches the road through the tire. ![]() Figure 7: Lumped parameter quarter-car model (plus occupant) with 6 Degrees of Freedom (6DOF). The design parameters are set as follows:
Implement the system described above, as a Modelica model, using the graphical editor in OMEdit, the provided gravity_mass block for each of the six bodies, and your actuator block. Then do the following:
![]() Figure 8: Trace of the road height, as described by the above table. Report your model, and graph the traces of the road height, the height of the wheel, the height of the car body, and the acceleration of the head of the passenger. Recall the requirements from the problem statement. Does the car body stay within 0.45 m and 0.55 m? Does the acceleration of the head stay below 0.315 m/s²? What do you think is the solution (that we will eventually implement)? BONUS: for giving meaningful names to all blocks and elements in your model/s. NOTE: This is a highly simplified model of a car and its passenger. In practice, the car body also pitches and rolls, all four wheels interact with each other, the tire can lose contact with the road, and the human body is modelled with many more degrees of freedom. Controller Model CreationYou will now create a PID controller for the car suspension system. You will do this in the graphical editor. A PID (Proportional-Integral-Derivative) controller is widely used in practice to drive the output of the plant towards a set-point. This set-point could change in time. We will however, consider the set-point is constant. In our example, the set-point represents the desired height of the car body. The control output from the PID controller, i.e. $u(t)$ drives the plant / process. The plant produces an output i.e. $h(t)$. The difference between the measured output $h(t)$ and the desired output $r(t)$ (a.k.a the set-point) is called the error $e(t)$. This error value is processed in the PID controller in three different ways as shown in the figure: ![]() Figure 9: PID control loop (adapted from Wikipedia).
Hence, the output from the PID controller $u(t)$ is given by: $$u(t) = (K_p \cdot e(t)) + (K_i \cdot \int_0^t e(t) dt) + (K_d \cdot \dfrac{d e(t)}{dt}) $$The gains $K_p$, $K_i$, and $K_d$ modulate the behavior of the PID controller. You may read more about a PID controller online. The essential point is that three signals are summed, which forms the PID control output $u(t)$. So, to sum up, in our case:
Hence, the equation for implementing the control is: $$ e(t) = r - h(t) $$ coupled with the equations above.Note: In our simple case, the set-point is constant Task 1: PID controller block
Note: Do not model any part of the PID controller using textual equations. In this task of the assignment you should use the graphical view to model the PID equations. Only use the textual syntax to define the parameters and interfaces of your block. Task 2: PID control loopYou can finally use all the blocks that you have defined before, in your own PID control loop!
Simulate the controlled car with $K_p = 10000$, $K_i = 1$, and $K_d = 100$ for 40 seconds with a step-size of 0.002 seconds. Report the traces of the height of the car body, the acceleration of the head of the passenger, and the force applied by the actuator. Compare them with the traces of the uncontrolled plant model from the previous section. Do you think this is an optimal controller? Why or why not? Vary the PID controller parameters and observe the effect on the control outcome. Report your observations. Note: Do not model any part of the PID control loop using textual equations. Only use the textual syntax to define the parameters of your model. Controller Model TuningSimilar to the calibration of the actuator parameters (recall that we calibrated $c_2$ and $d_2$), the controller also needs to be tuned for the most ideal control outcome. However, we do not directly have reference data to compare the simulation output to like we had in parameter estimation. Instead, the designer (you) should come up with a cost function to ascertain if the plant behaves as required. Recall the three requirements from the problem statement:
The first requirement is an objective: we want to minimize the error between the height of the car body and the set-point. The other two are constraints: a controller that violates them is unacceptable, no matter how well it tracks the set-point. Task 1: Design of the cost function
Task 2: Early termination of simulationsThe tuning will require hundreds of simulations. Many of them are hopeless long before they end:
Recall the modelling of discontinuous behavior in Modelica using the 'when' statement, that you learnt in the theory lectures. Here is a reference to the syntax. Inside a when statement, you can call the built-in function terminate("<message>"), which ends the simulation successfully at that moment and prints the message to console.
Note: The Boolean variables are stored in the simulation results like any other variable (as 0 or 1), so your Python script can read their final values to find out if/why a simulation ended early. Task 3: Tune PID controller
BEWARE! The best parameters do not depend on the order in which you simulate the combinations. However, the number of simulations that are terminated early because of the cost limit, and hence the total duration of the tuning, does depend on this order. BONUS: for measuring and reporting how much time the early termination saves, by also running the tuning with the early termination disabled (for example, by overriding the limits with very large values). Congratulations! You have successfully modeled a physical system and an optimal controller for it in Modelica! Note: This is a very naive controller, and the gains that you obtain are only optimal for this particular road profile and passenger. In practice, active suspension controllers are tuned for many different roads and loads, and they must also respect the limits on the force and stroke of the actuator. Practical Issues
|
| Maintained by Hans Vangheluwe. | Last Modified: 2026/10/15 10:42:11. |