WEBVTT

00:01.500 --> 00:05.660
Welcome back to the mini-projects here in the Python course and we are

00:05.660 --> 00:08.080
now looking at the second project.

00:08.740 --> 00:13.740
And here it's about model calibration of a one-track model of a

00:13.740 --> 00:14.060
vehicle.

00:16.380 --> 00:21.540
And yes, that comes in principle, or I used a bit of code that I also

00:21.540 --> 00:25.200
used in a publication last year.

00:26.220 --> 00:29.960
It was about validation of a vehicle one-track model.

00:31.280 --> 00:35.940
And yes, if you want to, you can read a bit of the background there in

00:35.940 --> 00:36.240
the paper.

00:36.380 --> 00:41.980
This is referenced in the bibtex file to the repository.

00:42.640 --> 00:45.360
And you can also use the code for the paper, which is also available

00:45.360 --> 00:46.000
here in the github.

00:48.220 --> 00:49.240
But you don't need that.

00:49.500 --> 00:53.420
So everything is prepared here so that you can start there.

00:53.420 --> 01:01.000
Yes, and the mini-project is about trying reference data that come

01:01.000 --> 01:02.000
from a two-track model.

01:02.520 --> 01:09.980
In this case I used a Simulink model and thus fitted a one-track

01:09.980 --> 01:10.400
model.

01:11.140 --> 01:16.740
And there we will adjust the transverse stiffness of the wheels with

01:16.740 --> 01:17.440
an optimizer.

01:17.440 --> 01:21.560
And yes, calibrating reference data from simulation models.

01:22.760 --> 01:25.700
This is a very typical task that occurs in practice.

01:26.820 --> 01:29.420
This is to settle a large field of mathematical optimization.

01:31.520 --> 01:34.600
Mathematical optimization is a very important topic.

01:35.220 --> 01:37.060
This occurs in all possible fields.

01:38.360 --> 01:41.980
This can also be in the direction of production, for example, that you

01:41.980 --> 01:43.220
want to optimize some production steps.

01:44.320 --> 01:48.640
Or in finance mathematics and of course also a lot in the field of

01:48.640 --> 01:48.900
engineering.

01:50.100 --> 01:53.880
And in essence, when optimizing, it is about trying to improve a

01:53.880 --> 01:58.180
problem with free parameters.

01:59.920 --> 02:03.580
And for this you set up a cost function and then there are different

02:03.580 --> 02:08.680
optimization procedures that change these parameters until this cost

02:08.680 --> 02:11.260
function has a better value than the starting value.

02:11.260 --> 02:15.000
This is perhaps on a very, very high level of flight, which is

02:15.000 --> 02:16.080
actually mathematical optimization.

02:17.440 --> 02:23.240
And in connection with models with free parameters or changeable

02:23.240 --> 02:28.340
parameters, which are also often called greybox models, the whole

02:28.340 --> 02:29.560
thing is called calibrating.

02:30.220 --> 02:34.640
This is not to be confused with calibrating measuring and testing

02:34.640 --> 02:34.820
devices.

02:35.780 --> 02:42.380
This is simply the term for these physical models with unknown

02:42.380 --> 02:46.240
parameters or parameters where you only roughly know the order of

02:46.240 --> 02:46.240
magnitude.

02:49.260 --> 02:51.060
I don't think I have to say much about the one-spot model.

02:53.400 --> 02:56.020
I assume you all have good knowledge of it.

02:57.440 --> 02:58.680
We'll just do that very briefly.

02:59.140 --> 03:01.880
Here on the right is an exemplary representation.

03:01.880 --> 03:09.060
What you do is you take a vehicle, which normally has four wheels, you

03:09.060 --> 03:14.060
pack these wheels together in axes on each single wheel.

03:16.280 --> 03:21.460
This has shown that up to about 4 meters per square second

03:21.460 --> 03:26.900
acceleration such a one-spot model can very well reproduce the

03:26.900 --> 03:29.020
behavior of a vehicle.

03:32.860 --> 03:36.440
Some dynamics are basically ignored in the one-spot model.

03:37.660 --> 03:40.280
This is pitch and roll dynamics, which then disappears.

03:41.300 --> 03:45.240
And the focus, for example, is assumed to be on the level of the

03:45.240 --> 03:45.240
runway.

03:46.040 --> 03:48.560
So that doesn't work for all vehicles.

03:48.860 --> 03:52.420
If they have very high buildings or something and then the cross

03:52.420 --> 03:56.540
-dynamics gets bigger, then these one-spot models become inaccurate.

03:56.540 --> 04:01.160
But for many, many applications this is actually good enough.

04:02.080 --> 04:03.140
And this is used quite often.

04:04.360 --> 04:08.980
And down here is shown the state-of-the-art form of the one-spot

04:08.980 --> 04:09.340
model.

04:10.240 --> 04:15.540
You can read the exact reference and so on here in the book by

04:15.540 --> 04:16.240
Schramm.

04:16.340 --> 04:18.980
Everything is described exactly there.

04:19.900 --> 04:20.900
Here only very briefly.

04:21.120 --> 04:30.160
So what goes in as, in principle, driving entrance size, is the little

04:30.160 --> 04:32.400
tether back here.

04:33.060 --> 04:38.120
This is used for the angle at which the front wheel is slid in.

04:39.420 --> 04:42.040
Or described angle at which the front wheel is slid in.

04:42.420 --> 04:44.240
Then we have two state sizes.

04:44.240 --> 04:49.640
This is the gear rate, this psi dot, and the swimming angle, beta.

04:51.140 --> 04:57.300
And then here in the A-matrix of the state-of-the-art model you have

04:57.300 --> 04:59.560
quite a few constants.

05:00.380 --> 05:04.700
These are distances, i.e.

05:04.700 --> 05:08.860
distances between the center of gravity and the wheel axles.

05:08.960 --> 05:11.000
These are this L, V and LR.

05:11.640 --> 05:18.920
Then you have the cross-stripes for the axles and thus also for the

05:18.920 --> 05:19.220
tires.

05:19.500 --> 05:20.940
So here everything is summarized.

05:22.400 --> 05:26.080
This is called CF and CR here in the small model.

05:26.980 --> 05:28.680
And what else is in it is the speed.

05:29.160 --> 05:31.980
It is now constant here, with which the vehicle moves forward.

05:33.500 --> 05:38.800
And then there is such an inertia, a sluggishness around the high

05:38.800 --> 05:39.060
axle.

05:40.140 --> 05:41.700
This is then the large tether.

05:43.340 --> 05:49.200
And as I said, this tilt of the front wheel is then the model

05:49.200 --> 05:49.520
entrance.

05:54.640 --> 05:56.380
And the reference data.

05:56.900 --> 05:58.900
Normally you take measurement data from driving tests.

05:58.980 --> 06:03.620
But now here for the lecture I just took a reference model that has a

06:03.620 --> 06:04.200
different structure.

06:04.760 --> 06:06.300
This is a more complicated model.

06:06.400 --> 06:07.640
This is then a two-spoke model.

06:08.640 --> 06:15.400
This is simply available in Simulink in the Vehicle Dynamics Toolbox.

06:16.220 --> 06:19.180
You can simply use this and load it in.

06:19.240 --> 06:20.580
This is also available in various versions.

06:21.580 --> 06:24.440
In terms of the representation, you can already see that it has four

06:24.440 --> 06:24.700
wheels.

06:25.240 --> 06:28.260
So that also takes into account such roll dynamics.

06:31.460 --> 06:38.800
And what you can put in there for modeling is a steering angle that

06:38.800 --> 06:39.520
you put in.

06:39.640 --> 06:41.440
And here I made it relatively easy.

06:41.980 --> 06:43.880
A sinus wave comes in, i.e.

06:43.880 --> 06:48.240
a sinus maneuver for a certain period of time.

06:49.000 --> 06:53.140
And otherwise all other parameters have been kept constant.

06:54.180 --> 06:56.720
And the speed is also rather slow, i.e.

06:56.740 --> 06:57.780
10 meters per second.

06:58.400 --> 07:02.760
This is simply there so that the cross-dynamics does not get so high

07:02.760 --> 07:07.280
and that the entrance model is still halfway there.

07:07.520 --> 07:16.140
And the two sizes that we look at, the gear ratio and the swimming

07:16.140 --> 07:19.500
angle, that the entrance model can still depict that quite well.

07:20.120 --> 07:22.660
And that has then simply been saved here as a mat file.

07:24.380 --> 07:27.660
The model is also in the Propository as a Simulink file.

07:27.660 --> 07:31.400
If you have the corresponding toolbox, you can also run it.

07:31.820 --> 07:39.080
And then there is such a small m-file that converts the mat files into

07:39.080 --> 07:40.000
CSV files.

07:42.060 --> 07:46.660
And you can also find the CSV files here under mini-projects.

07:47.400 --> 07:51.560
They are then simply tied into the repository here.

07:51.560 --> 07:56.480
And these are then simply time and the corresponding value.

07:56.660 --> 08:01.640
So the first line is the time and the second line here would be the

08:01.640 --> 08:02.120
swimming angle.

08:04.140 --> 08:06.600
And here would be the same for the gear ratio.

08:06.740 --> 08:08.540
This is then in this CSV.

08:11.220 --> 08:15.400
And then there is the model entrance, i.e.

08:15.460 --> 08:18.080
the inclination of the front wheel as an angle.

08:24.040 --> 08:28.160
In order to process this with Python and to optimize such a model, we

08:28.160 --> 08:29.800
need a few steps first.

08:30.980 --> 08:32.940
First we load a few libraries.

08:34.100 --> 08:42.640
I already said optimization and there is this Optimize module at

08:42.640 --> 08:42.640
SciPy.

08:45.000 --> 08:48.400
Otherwise we take a second library, which is called Control.

08:48.400 --> 08:57.480
This is a nice library with which you can handle control techniques in

08:57.480 --> 08:59.260
Python.

09:00.040 --> 09:05.060
For example, you can generate and simulate such state-of-the-art

09:05.060 --> 09:05.060
models.

09:05.800 --> 09:07.920
But you can also generate controllers.

09:09.640 --> 09:13.940
And yes, it is also worth taking a look at this control library.

09:14.360 --> 09:15.680
It is also very nicely documented.

09:15.680 --> 09:20.020
And the other two imports are standard NumPy.

09:20.240 --> 09:22.180
As I said, you need that in almost every script.

09:22.480 --> 09:26.000
And then for plotting, so that we can look at a few results, the

09:26.000 --> 09:26.580
matplotlib.

09:28.880 --> 09:32.960
Then there is a small code block here in the notebook.

09:33.660 --> 09:39.980
This is simply because the notebooks are also tested on Travis CI with

09:39.980 --> 09:40.820
continuous integration.

09:41.620 --> 09:54.180
This is just a bit of a workaround to find these CSV files from

09:54.180 --> 09:54.180
different paths.

09:54.780 --> 09:57.040
This is not so important here at first.

09:57.980 --> 09:59.680
You can certainly solve this a bit more elegantly.

10:00.180 --> 10:04.320
If you have a suggestion, I would be interested in how to do this

10:04.320 --> 10:04.840
well.

10:04.840 --> 10:11.180
It's just that Travis starts all the things from a different folder

10:11.180 --> 10:13.720
than if you run it locally.

10:14.660 --> 10:16.260
But that's not so important now.

10:17.100 --> 10:22.980
What we still need is a function so that we can read the CSV files in

10:22.980 --> 10:23.300
Python.

10:23.580 --> 10:27.400
And there is already a nicely pre-made function from NumPy.

10:28.060 --> 10:30.840
It's called genfrom.txt.

10:31.780 --> 10:34.000
And then you can very easily read the things.

10:35.780 --> 10:38.060
This is shown here with the three lines.

10:38.700 --> 10:41.640
So two-dimensional arrays would be generated each.

10:43.800 --> 10:46.300
And you always assign the file here.

10:46.960 --> 10:52.540
And as a separator between the individual values, you can also assign

10:52.540 --> 10:52.540
it.

10:52.620 --> 10:56.120
In this case, the file is a comma.

10:56.120 --> 11:00.500
So it's relatively easy to read CSV files in Python.

11:05.170 --> 11:10.350
And then, of course, it makes sense for us to display the written data

11:10.350 --> 11:15.630
in the CSV files and later also the model outputs and simulations.

11:16.810 --> 11:17.410
And then we can look at plots.

11:19.130 --> 11:23.290
And then we do a common plotting function.

11:24.070 --> 11:26.790
And here it becomes relatively easy.

11:27.230 --> 11:34.690
So the arguments, that's the gear ratio of the swimming angle and the

11:34.690 --> 11:34.970
title.

11:35.210 --> 11:38.930
Just so that you can interactively overwrite the diagram a bit.

11:39.330 --> 11:41.410
And then this is plotted, so to speak.

11:42.790 --> 11:45.530
You can see these three plot commands here.

11:45.850 --> 11:47.470
That's very easy.

11:47.610 --> 11:48.610
And then a legend.

11:51.070 --> 11:54.690
And then let's just take a look at what it looks like for the two

11:54.690 --> 11:58.730
-track model that was simulated in Simulink.

11:59.750 --> 12:06.870
And then you can just call up the function and ultimately pass on the

12:06.870 --> 12:08.190
correct values.

12:09.350 --> 12:16.670
And you can see here that it took 30 seconds.

12:16.670 --> 12:21.470
I just see a mistake down here.

12:21.830 --> 12:23.750
The legend description is not correct.

12:24.270 --> 12:31.290
This is simply because the data was tested with 100 Hz.

12:31.610 --> 12:33.510
And that's why it says 3000 there.

12:33.790 --> 12:36.990
But that's not the time in seconds, it's actually the samples.

12:37.570 --> 12:38.970
We'd have to change that again.

12:40.150 --> 12:42.230
And yes, there you can now see the sequences.

12:42.370 --> 12:48.950
So here this sinusoidal movement of the angle of the front wheel.

12:49.710 --> 12:56.310
And then how the gear speed, the gear ratio and the swimming angle

12:56.310 --> 12:57.690
behave with it.

12:58.450 --> 13:01.470
And in the end the maneuver is over and then everything goes back to

13:01.470 --> 13:01.670
zero.

13:02.070 --> 13:03.690
So that would be the reference data now.

13:04.550 --> 13:10.190
And then we're going to build up the one-track model and see how it

13:10.190 --> 13:12.190
behaves with the same stimulation.

13:12.610 --> 13:15.410
So the task would be here now, the same steering angle goes in.

13:16.170 --> 13:21.290
And then the question is, how well can the one-track model then

13:21.290 --> 13:22.710
reproduce these processes?

13:24.110 --> 13:28.470
This is a simpler model of the structure compared to the reference.

13:29.130 --> 13:32.890
And that's actually quite often the case that when you model, that you

13:32.890 --> 13:38.630
have simpler models of the structure than the reference data or the

13:38.630 --> 13:40.870
systems with which you have recorded the reference data.

13:41.670 --> 13:47.370
That's the main reason why you even simulate to simplify things and

13:47.370 --> 13:48.090
then also to predict.

13:52.640 --> 13:57.480
So we take the Control Systems library from Python.

13:57.480 --> 14:01.620
Here again the model structure is simply given in the state space

14:01.620 --> 14:02.100
representation.

14:02.920 --> 14:07.220
And now let's take a quick look at what it looks like, what features

14:07.220 --> 14:07.560
are there.

14:08.080 --> 14:13.460
So you can model with this Python Control Systems library LTE systems,

14:13.640 --> 14:14.080
for example.

14:15.700 --> 14:17.580
You can generate time series.

14:19.160 --> 14:21.120
What else do you have?

14:21.940 --> 14:26.880
Yes, such modules with which you can do frequency analysis, time

14:26.880 --> 14:33.020
series, also state space models can be generated and modeled.

14:34.040 --> 14:39.100
So this is really a very, very large library with which you can work.

14:39.860 --> 14:43.880
And as I said, there is also a very nice documentary about it.

14:47.650 --> 14:54.130
And such a state space model can now be defined with the library as

14:54.130 --> 14:54.610
follows.

14:55.330 --> 14:59.070
Up here, that's basically a function that I wrote myself.

14:59.550 --> 15:01.930
A few arguments are passed on.

15:02.590 --> 15:07.210
These are then the transverse stiffnesses, so basically all the

15:07.210 --> 15:09.430
parameters that the reference model has.

15:10.130 --> 15:12.870
These are then the distances between the center of gravity and the

15:12.870 --> 15:21.150
front and rear axle, the vehicle mass and then the sluggishness around

15:21.150 --> 15:23.390
the high axle and the speed.

15:24.130 --> 15:27.730
And then the individual elements in this A-matrix are simply

15:27.730 --> 15:27.810
calculated.

15:27.950 --> 15:31.750
These are these A11, A12 entries.

15:31.810 --> 15:39.250
So A11 stands for this first term and A12 is the second term.

15:39.250 --> 15:46.130
So this is basically where this A-matrix is built up, the transition

15:46.130 --> 15:47.730
matrix of the state space model.

15:48.670 --> 15:51.650
And here it is simply put together as a numpy array, as a two

15:51.650 --> 15:52.450
-dimensional array.

15:54.110 --> 15:56.450
We do the same with this B-vector.

15:56.810 --> 16:01.190
So that's exactly one-to-one with the mathematical formulation on the

16:01.190 --> 16:01.750
slide before.

16:02.290 --> 16:05.790
And the C and D-matrix are basically only available as standard in the

16:05.790 --> 16:06.130
model.

16:08.790 --> 16:12.970
So we just do that with standard values.

16:14.550 --> 16:19.390
And then you can use this command CTRL-SS, which stands for state

16:19.390 --> 16:22.070
space model, to generate such an object.

16:23.290 --> 16:28.250
And when we have generated it, then you can also simulate it with the

16:28.250 --> 16:28.630
library.

16:34.260 --> 16:38.940
And first of all, we take initial values, which we also used from the

16:38.940 --> 16:40.840
Simulink model, i.e.

16:40.860 --> 16:41.420
transferred one-to-one.

16:42.940 --> 16:45.140
Here you can see that the model is being built up.

16:45.440 --> 16:48.600
And here you can now see values for the transverse stiffness in front

16:48.600 --> 16:51.520
and back and then a few distances in meters and a vehicle mass.

16:52.520 --> 16:58.500
And with that, such a model is generated as an object.

16:59.500 --> 17:05.660
And with the command from the CTRL-Systems library, CTRL-Force

17:05.660 --> 17:10.260
-Response, you can then simulate the state space model.

17:10.260 --> 17:13.780
And of course the model will be transferred.

17:19.520 --> 17:21.480
A time vector will be transferred.

17:22.040 --> 17:25.320
And then this U here, which is basically the steering wheel angle.

17:25.540 --> 17:29.580
So that's the driving input into the model.

17:29.860 --> 17:32.520
And we also have a few starting conditions that can be specified.

17:33.500 --> 17:36.240
And then you get different values.

17:36.560 --> 17:37.940
You can also have the time vector output.

17:38.820 --> 17:41.460
I have now let the conditions out, so to speak.

17:43.300 --> 17:45.520
And then you can basically plot them.

17:52.310 --> 17:54.710
This is done here in the plot.

17:54.810 --> 17:56.570
Then we use the same plot function again.

17:57.190 --> 17:59.830
As I said, sorry, the x-axis labels down here.

17:59.950 --> 18:02.570
So that's basically hundredths of a second.

18:03.650 --> 18:05.950
And then we are like this.

18:06.810 --> 18:11.310
It fits qualitatively, but it looks a bit different in all the

18:11.310 --> 18:15.970
projections than the two-track model that we had as a reference.

18:16.890 --> 18:20.370
And yes, that's simply because the one-track model has a simpler

18:20.370 --> 18:20.870
structure.

18:21.470 --> 18:29.110
And although we have now passed the exact values, the reference data

18:29.110 --> 18:29.770
cannot follow that closely.

18:29.770 --> 18:34.310
Yes, and a typical task is to tune such models.

18:34.810 --> 18:37.750
And yes, then there are different tasks.

18:38.070 --> 18:41.830
So one task would be to use a model to determine such unknown

18:41.830 --> 18:42.550
parameters.

18:43.910 --> 18:46.850
We don't want to do that here now, but we want to tune the parameters

18:46.850 --> 18:51.630
in such a way that the output of the model fits better with the

18:51.630 --> 18:52.310
reference data.

18:53.310 --> 18:58.610
And yes, that's basically a step in the work that you take to improve

18:58.610 --> 19:01.030
the prediction of the model.

19:01.890 --> 19:07.610
This can lead to the fact that the parameters are no longer in the

19:07.610 --> 19:08.810
actual size order.

19:09.930 --> 19:16.130
So you don't have the identification of the parameters as a goal, but

19:16.130 --> 19:19.730
rather that the model output is well connected to the reference data.

19:19.730 --> 19:25.290
And depending on how different the model structures are, this can vary

19:25.290 --> 19:25.970
significantly.

19:26.790 --> 19:33.230
So if you have reference data from a system or a reference model that

19:33.230 --> 19:37.750
is quite complicated and has a lot of dynamics in it, and you then

19:37.750 --> 19:41.850
take a very, very simple model and want to simulate it, then it may be

19:41.850 --> 19:47.650
that the parameter values ​​then deviate a whole corner from this

19:47.650 --> 19:48.510
reference model.

19:48.970 --> 19:52.190
So that's relatively normal.

19:52.850 --> 19:56.330
This is simply due to this simplification that you have in the

19:56.330 --> 19:57.190
simulation model.

19:57.790 --> 20:00.790
Certain physical effects are completely suppressed there.

20:00.790 --> 20:04.950
And then it is actually not surprising that the parameters can no

20:04.950 --> 20:10.730
longer match exactly with the reference parameters.

20:12.110 --> 20:18.210
But such simple models can be used very well to make predictions and

20:18.210 --> 20:19.390
to model the system behavior.

20:20.770 --> 20:23.290
And the simple models still have the charm that they also calculate

20:23.290 --> 20:24.210
very, very quickly.

20:25.070 --> 20:28.530
So if you have a very simple model structure, it can be simulated

20:28.530 --> 20:32.150
much, much faster than a very large, complicated model.

20:32.810 --> 20:35.710
Here in the example, the difference in simulation time is not that

20:35.710 --> 20:36.010
big.

20:36.110 --> 20:40.750
But if you think of larger system simulations, it can do a lot more

20:40.750 --> 20:41.590
very quickly.

20:43.170 --> 20:47.610
So that's just a bit of a background on why we want to tune the model

20:47.610 --> 20:55.250
parameters a bit and want to push the simple model into the same

20:55.250 --> 21:00.990
starting behavior with the optimization as the more complicated two

21:00.990 --> 21:01.530
-spot model.

21:05.940 --> 21:08.640
Let's take a look at a direct comparison again.

21:09.440 --> 21:15.560
Here the reference data from the two-spot model and the simulated data

21:15.560 --> 21:16.860
from the one-spot model are shown.

21:16.860 --> 21:23.340
And here you can see that, for example, the swimming angle of the one

21:23.340 --> 21:25.460
-spot model is significantly larger.

21:26.200 --> 21:27.180
So that's shown here in red.

21:28.500 --> 21:31.300
And the reference, that's this two-spot model.

21:31.880 --> 21:36.440
So you can see that it fits quite well in terms of quality, but not in

21:36.440 --> 21:36.920
terms of quantity.

21:38.360 --> 21:45.740
The one-spot model can quite well depict the characteristic behavior,

21:46.520 --> 21:49.520
but it doesn't quite fit into the peaks.

21:49.640 --> 21:52.880
And also in terms of dynamics, it looks a bit different.

21:53.660 --> 21:56.180
For example, this is a bit sluggish here.

21:56.380 --> 21:58.160
There's something going on behind it.

22:01.560 --> 22:05.840
What we need now for mathematical optimization is a so-called cost

22:05.840 --> 22:07.820
function or objective function.

22:07.820 --> 22:13.620
And you can always set it up yourself or you have to set it up

22:13.620 --> 22:16.240
yourself for mathematical optimization and calibrating.

22:16.700 --> 22:24.040
And what we want to do then is to take both states into account in the

22:24.040 --> 22:25.580
cost function.

22:26.260 --> 22:34.200
And what we also do is to normalize the values first, so that each of

22:34.200 --> 22:37.340
the two states is equally important in the cost function.

22:38.540 --> 22:40.120
And that's done here now.

22:41.040 --> 22:44.540
So a function is written, which is simply called error.

22:45.020 --> 22:47.160
You could have called it cost function, for example.

22:47.160 --> 22:57.420
And now the absolute error between the reference data and the one-spot

22:57.420 --> 23:01.800
model is calculated here with this error 0 and error 1.

23:02.400 --> 23:04.660
And then it is scaled again with the two lines.

23:06.880 --> 23:10.860
And here in the last line, the cost function is then built together.

23:11.800 --> 23:19.420
And that is always the quadratic error of the gear rate and the

23:19.420 --> 23:20.040
swimming angle.

23:20.280 --> 23:21.740
And both are simply summarized with a plus.

23:23.040 --> 23:27.660
You could also put a weighting factor in between here.

23:27.660 --> 23:33.680
Then you can basically tune the model either only to the gear rate or

23:33.680 --> 23:37.960
only to the swimming angle or some mixtures of them.

23:37.960 --> 23:41.580
So here in the cost function, you can basically influence and define

23:41.580 --> 23:44.120
your optimization problem very strongly.

23:46.640 --> 23:53.340
And also this normalization that I did there is basically optional.

23:53.340 --> 23:57.680
But it is important that each of the two states is equally important,

23:57.680 --> 23:58.700
as it is written here.

24:00.280 --> 24:05.460
But you can also use the notebook later and try to build a weighting

24:05.460 --> 24:06.340
factor in here.

24:06.340 --> 24:12.860
And then switch out one of the two states and see what the optimizer

24:12.860 --> 24:14.260
does with it in the end.

24:18.620 --> 24:24.380
And what we do first with this initially defined one-spot model is

24:24.380 --> 24:27.440
that we simply let the value of this cost function be spent.

24:28.860 --> 24:31.900
Since everything is now normalized, it no longer has a unit.

24:33.920 --> 24:36.200
You can't really interpret it that well.

24:36.200 --> 24:38.840
What you can only say is, the smaller the better.

24:39.080 --> 24:43.900
So the better the one-spot model is in the initial behavior with the

24:43.900 --> 24:45.100
two -spot model.

24:47.160 --> 24:51.780
And we start here with a value of about 3082.

24:53.220 --> 24:56.420
And now the optimizer comes into play, which then changes the

24:56.420 --> 24:59.220
parameters and, so to speak, should improve this value.

25:01.520 --> 25:05.260
What we then use is the minimize function from SciPy Optimize.

25:07.640 --> 25:10.700
And we're going to optimize two parameters now.

25:12.100 --> 25:15.140
This is the front and rear side stiffness.

25:16.880 --> 25:22.400
And for that we first need an optimizer and have to build it up.

25:23.420 --> 25:25.840
And you can see that here in principle.

25:28.620 --> 25:32.500
So first the cost function is built up.

25:32.680 --> 25:35.260
For this you need a simulation again and again.

25:35.980 --> 25:47.500
So what is changed is then the value for the front stiffness and the

25:47.500 --> 25:48.860
value for the rear stiffness.

25:48.860 --> 25:50.640
This is transferred here as an argument.

25:51.880 --> 25:54.020
And that's just an array again.

25:54.720 --> 25:58.200
And the first entry basically stands for the front, the second for the

25:58.200 --> 25:58.400
rear.

25:58.880 --> 26:01.700
And the other values are now left to the default values.

26:02.940 --> 26:06.940
So we don't turn around in this optimization problem.

26:07.000 --> 26:08.600
But you can also change that if you want.

26:09.700 --> 26:16.080
So if you now add x2 and x3 here and simply increase the vector of the

26:16.080 --> 26:17.020
parameters to be optimized.

26:17.020 --> 26:20.580
Then the optimization problem will be a little bigger again.

26:20.840 --> 26:25.480
But the optimizer then has more freedom to tune the model.

26:26.540 --> 26:34.020
I didn't do that here because we leave these geometric sizes to the

26:34.020 --> 26:34.820
default values.

26:35.620 --> 26:42.100
And then the model is basically simulated with this set of parameters.

26:42.100 --> 26:47.660
And in the end the cost function then brings out these error values.

26:48.420 --> 26:53.320
So the optimizer needs that to see whether a change here in this x0

26:53.320 --> 26:58.640
and x1 goes in the right direction or leads to greater costs.

27:02.830 --> 27:05.130
We'll take out an optimizer now.

27:06.470 --> 27:08.450
It is now chosen a bit randomly.

27:09.110 --> 27:13.130
In the documentation of the toolbox there are many optimizers.

27:13.210 --> 27:15.690
You can take a look and try out a few others.

27:17.170 --> 27:19.710
Here we just take this Powell optimizer.

27:20.650 --> 27:24.130
And what you have to give it is basically a start value.

27:24.530 --> 27:28.070
This is set here for the front and rear stiffness.

27:29.330 --> 27:35.670
And then you pass this objective function to it.

27:36.730 --> 27:45.370
Then you can simply call it up and get the optimized values displayed

27:45.370 --> 27:45.370
at the end.

27:51.920 --> 27:57.520
Here it is indicated again with a few additional output information.

27:58.460 --> 28:02.720
So how the value of the cost function is and how many iterations it

28:02.720 --> 28:03.120
has gone through.

28:04.240 --> 28:07.840
And how many times the function has been evaluated for it.

28:07.840 --> 28:10.920
And then we come to such a value at the end.

28:11.320 --> 28:13.420
So it is now smaller than the one before.

28:14.740 --> 28:18.140
And the optimizer has now found a set for these transverse

28:18.140 --> 28:18.800
stiffnesses.

28:18.860 --> 28:24.420
Where the input model simply delivers a result that is closer to the

28:24.420 --> 28:25.080
reference data.

28:26.660 --> 28:30.800
And of course you can also look at that again, that you plot that.

28:30.800 --> 28:35.700
And then I have now transferred the values ​​by hand from what the

28:35.700 --> 28:36.680
optimizer has found.

28:41.310 --> 28:47.650
And you can then first display it individually or in connection.

28:48.270 --> 28:52.710
And yes, you can now see that the input model has still not quite

28:52.710 --> 28:54.170
managed to map these reference data.

28:56.350 --> 29:01.190
But the overall value for the costs has already improved a bit.

29:02.510 --> 29:09.030
But yes, in principle, there is still a big discrepancy in the

29:09.030 --> 29:10.690
swimming angle that you can see there.

29:10.810 --> 29:13.990
That means there is still a bit of potential in how to improve that.

29:15.830 --> 29:20.130
And as I said, that's the mistake that came out after this

29:20.130 --> 29:21.370
optimization set.

29:21.370 --> 29:30.930
So that's the first step I took to adapt the model a bit better.

29:31.950 --> 29:36.210
And now the question is whether even better values ​​can ultimately be

29:36.210 --> 29:36.550
obtained.

29:37.690 --> 29:43.170
Or whether it is simply a limit case where the input model no longer

29:43.170 --> 29:47.050
makes sense to depict the dynamics of this two-stroke model.

29:48.590 --> 29:54.510
Of course, there will be some limits at some point, because the input

29:54.510 --> 29:58.150
model has a much simpler physics at its core.

30:00.410 --> 30:06.170
And that would be the task you can do here in this mini-tutorial.

30:07.230 --> 30:11.090
In this mini-project, in principle, you can now of course select other

30:11.090 --> 30:11.630
optimizers.

30:13.190 --> 30:17.730
You can also let other parameters flow into the optimization.

30:19.090 --> 30:25.030
So, for example, what I could imagine would be the sluggishness, i.e.

30:25.050 --> 30:27.490
the big tether of the input model.

30:27.890 --> 30:30.170
That you take that in again and then don't optimize over two

30:30.170 --> 30:31.890
parameters, but over three.

30:32.490 --> 30:34.370
And what you can also do is build an optimizer yourself as an

30:34.370 --> 30:35.430
alternative method.

30:37.430 --> 30:44.410
And the easiest way to look at optimization without going into

30:44.410 --> 30:49.230
complicated algorithms like genetic optimization.

30:49.950 --> 30:54.350
The easiest thing you can do is actually a random number search.

30:54.910 --> 31:02.570
It is also quite stable and delivers, or rather stable is perhaps

31:02.570 --> 31:05.870
mispronounced, of course, with every run, with such a random number

31:05.870 --> 31:08.130
search, a different value comes out.

31:08.490 --> 31:12.510
But where it is quite good is simply with cost functions that have

31:12.510 --> 31:14.530
several local optimizers.

31:16.310 --> 31:22.510
These procedures are usually able to get out of local optimizers.

31:24.310 --> 31:26.690
It's worth taking a quick look at it.

31:26.690 --> 31:32.710
And such a simple optimizer, which simply runs via Monte Carlo

31:32.710 --> 31:37.470
procedures and uses such random numbers, is shown here in pseudocode.

31:38.570 --> 31:39.510
So what do I mean by that?

31:39.810 --> 31:44.570
What you would have to set first with such an optimizer would be for

31:44.570 --> 31:48.450
the parameters to be optimized, min and max values that are somehow

31:48.450 --> 31:48.770
useful.

31:49.590 --> 31:53.190
Of course, we don't want to have negative values for the stiffness

31:53.190 --> 31:54.490
parameters, for example.

31:56.530 --> 31:58.830
That contradicts the whole physics.

31:59.410 --> 32:01.510
It makes sense to set such min and max values.

32:02.490 --> 32:05.850
And then you just initialize the cost function.

32:06.070 --> 32:12.090
So that was this single value in front of us, the 3082, for example,

32:12.410 --> 32:13.330
which we had first.

32:13.330 --> 32:19.450
You initialize that first with a value.

32:20.110 --> 32:20.710
Ah, that's here.

32:20.850 --> 32:21.770
Sorry, I slipped a line.

32:23.090 --> 32:31.230
And then you start again with initial parameters and save that to a

32:31.230 --> 32:33.570
variable called best parameters.

32:34.650 --> 32:39.270
And what you can also do, if you make it a bit more complicated, which

32:39.270 --> 32:43.750
is not necessary here in the pseudocode below, is that you basically

32:43.750 --> 32:47.930
look at how the percentage change from one iteration from the

32:47.930 --> 32:49.570
optimizer to the next behaves.

32:49.610 --> 32:52.210
Then you can also build in such a stop criterion.

32:53.490 --> 32:57.810
But what the actual process is then in principle, here for the

32:57.810 --> 33:01.370
simplest form that I have come up with now, is that you make a pre

33:01.370 --> 33:05.570
-loop and then you simply iterate up to the maximum number of

33:05.570 --> 33:07.170
iterations you want, i.e.

33:07.190 --> 33:08.190
for example 1000 times.

33:09.110 --> 33:15.630
Then you throw random parameters, simply with an even distribution,

33:15.810 --> 33:20.010
for example, given the min and max values.

33:20.510 --> 33:22.990
So the parameters should be within these limits.

33:23.650 --> 33:28.790
Then the input model is simulated with these parameters and then the

33:28.790 --> 33:30.470
current costs are simply calculated.

33:30.470 --> 33:35.490
And then it is compared whether the current costs that this iteration

33:35.490 --> 33:38.970
loop has just brought out, whether they are better, i.e.

33:39.010 --> 33:42.150
smaller than the previous costs.

33:42.950 --> 33:44.710
And then you can basically save that for a short time.

33:45.890 --> 33:52.010
And that basically goes on until this maximum iteration is reached.

33:52.370 --> 33:57.770
And a few times it will probably jump into this if loop, if such a

33:57.770 --> 34:02.990
random parameter set has actually led to a simulation where the costs

34:02.990 --> 34:05.930
were lower than what was previously found.

34:06.710 --> 34:13.550
So here this loop runs for example 1000 times and maybe a few hundred

34:13.550 --> 34:18.890
times or in the lower hundred range it ends up here in this loop.

34:19.590 --> 34:24.990
And then the optimizer has ultimately found a parameter set that was

34:24.990 --> 34:29.050
better than the previous starting conditions.

34:29.490 --> 34:33.570
And then you can just try to improve the input model in this

34:33.570 --> 34:34.590
calibration task.

34:35.450 --> 34:37.690
As I said, you can also work a little bit on the cost function itself

34:39.110 --> 34:46.230
or on this error function, that you only try to optimize the swimming

34:46.230 --> 34:51.670
angle, for example, whether you can get better results and just gain a

34:51.670 --> 34:55.730
little experience how to solve such optimization problems with Python.

34:57.650 --> 35:02.070
The task setting is in principle such that the input model cannot

35:02.070 --> 35:05.530
completely follow the reference data of the two-stroke model.

35:06.850 --> 35:12.110
So it's not just a bit of a rush on the reference data, what such a

35:12.110 --> 35:15.170
model can compensate for, but here we really have to do with a

35:15.170 --> 35:17.050
different model structure.

35:18.270 --> 35:22.230
The reference data, as I said, are from a model with a more

35:22.230 --> 35:26.190
complicated physical structure and the input model is much easier from

35:26.190 --> 35:27.410
the structure.

35:28.210 --> 35:32.150
There are many physical effects completely neglected.

35:32.670 --> 35:37.590
So it won't be that you get a one-to-one match and the lines are

35:37.590 --> 35:38.310
exactly on top of each other.

35:38.630 --> 35:44.390
That's not really the goal here with the task, but that you deal with

35:44.390 --> 35:48.610
optimization a bit and play around with the cost functions a bit and

35:48.610 --> 35:54.630
write an optimizer yourself and then just see how relatively easy it

35:54.630 --> 35:58.690
is in Python and how you can handle such rather complicated questions

35:58.690 --> 36:01.350
with Python.

36:03.610 --> 36:06.870
Then I would say I'm looking forward to the results.

36:07.230 --> 36:08.870
Let's see where they come from.

36:08.870 --> 36:11.730
Surely they will find a few better settings.

36:13.050 --> 36:16.950
And then I would say thank you for listening and we'll see you again

36:16.950 --> 36:18.510
at the next mini-project.

