SELF-BALANCING
MOTORCYCLE: PART III
1. Introduction
In this section, we'll model our system without deriving and using differential equations. Simscape, a Simulink's dedicated library, will calculate everything for us based on the system's parts, taking into account their geometry, densities, and the way they are connected to each other. We'll first model a simple system, the same one from the previous section, and then the full system, consisting of the real motorcycle 3D parts. To finish, we'll develop the same controller from the previous section and make sure that it works as intended with our model.
2. Modeling a simple system
Let's begin by turning the motorcycle into a simpler system as before, consisting of a block and an inertia disk. We won't consider any friction between the parts as well. We'll add a massless black circle to the wheel in order to visualize its angular displacement:

To build this model, we use simple geometry objects, in this case a block and a disk. We can specify their dimensions and have Simscape calculate their moments of inertia by using their masses or densities. In this case, we load the parameters into Matlab's workspace using the same script from the previous section, and reference it in the model. For the block, its dimensions are given by l (length), d (width) and h (height), and its mass by mb:

Here's the Simscape model:

We'll briefly explain how this simple system was created in this environment and the basics of how it works. In Simscape, each part has its own coordinates system, and so does the ground, which is called the "world frame". For convention, in every project, we want to use a right-handed coordinate system:

In this coordinate system, gravity acts negatively on the Z-axis. Simulink also uses this convention, and in the "mechanism configuration" block we can confirm this, as gravity is already set to -9.81 m/s² on the Z-direction:

Next, we have to add a revolute joint to the system, which is the wheel-ground axis. A revolute joint has a base and a follower. In this case, the base is the ground, which is fixed. That's why we have to add the joint before adding any of the physical parts. The revolute joint rotates around its own Z-axis by definition, but our current Z-axis is the world-frame one, which is vertical. To make the revolute joint rotate around a horizontal axis, we have to add a rotation between the ground frame and the revolute joint frame. To do this, we use a "rigid transform" block:

Notice on the image below how by rotating the world-frame axis by -90º (right-hand convention) around Y we put the revolute joint Z-axis where the -X world-frame axis was before, and thus make the rotating join horizontal, with gravity acting perpendicular to it.

world frame

new revolute joint frame
Next, we have to create two rotating frames for the body. One for the wheel-ground axis, and one for the reaction wheel. These frames will have the same coordinate system as the previous revolute joint so that we keep everything logical and neat and don't have to add unnecessary transforms to describe how the parts are connected:

ground frame

inertia wheel frame
We then add another revolute joint, the one for the inertia wheel, to the respective previously created body frame (which in this case is the base), and finally, the inertia wheel (which in this case is the follower), also connected to this joint. Note that the fact that for this joint the body is the base and the reaction wheel the follower is what gives us the joint velocity and being the relative speed between the two, which you may recall is the way we're measuring it in the real model, as opposed to its absolute speed, which would be relative to the ground.
​
You'll see that there's no rigid transform between the body frame and the inertia wheel frame. This is because we were able to define a frame for both the body and the wheel that already accurately defines the way they are connected. That's not the case for the marker, and therefore we have to add a rigid transform to move it 4 cm from the wheel surface center:


Going forward, we can define initial conditions, inputs, and outputs to the revolute joints. For this simulation, we'll define a starting leaning angle of 4º and a zero speed. Because first we're running a model with no motor torque, we'll only define the outputs, which will be the position and velocity of the wheel-ground axis, and the velocity of the inertia wheel axis. Below we show the block diagram for the first joint just to illustrate how they are defined:

Lastly, we convert the reads from radians to degrees using the appropriate block, just like we did in the model in the previous chapter. Here, however, there's one additional step. Simulink and Simscape work with two different "unit" types. Simulink works with "Simulink units" and Simscape with "physical units". Therefore, we can't just connect Simscape units to Simulink blocks and vice-versa. First, we need to convert the unit to the right type. To do this, we use the "PS-Simulink converter" and the "Simulink-PS converter" to change between signal types. That's what we do in the model before the "Radians to Degrees" block:

PS-Simulink converter
Now that we understand how the model was built, let's run the simulation. Remember that the initial conditions are a 4º leaning angle and zero speed:
By checking the data inspector, we can see that the system's behavior is exactly the same from the equations model in the previous chapter:

Let's go ahead and add a feedback controller just like we did before. We'll create a state vector and feed it to the gain matrix. Here's the new model:


The new plants, now with the motor torque input:

(click to enlarge)
We'll use the same gains as the equations model:

Let's see how it goes:


The system behaves as expected and we've got a nice response where all the speeds and torque go to zero in steady-state. Let's see how it goes when we add an angle offset to it. We'll add a 1º bias:


Here too we got a good response. The system goes to zero even though there's a bias on the leaning angle, and the inertia wheel goes to a constant speed. Here obviously we're more concerned about the system behavior than with the actual values of the torque and wheel speed. We'll better tune those when we get to simulate the real motorcycle model which we'll do shortly.
​
To finish the simulations with this simple model, let's set the bias to zero and add random disturbances to the motorcycle. This could be anything like wind, the bike turning a little bit, or some other type of external force input to the system. This torque will be randomly generated by the "random number" Simulink's block:


The disturbance goes as an input torque to the wheel-ground axis:

(click to enlarge)
Let's see how it responds to random perturbations:


The system is able to stay upright as remains stable around 0º. Now we'll move to simulate the real system which will not be made of a block and a disk, but of the real motorcycle components.
3. Modeling a real system
We're going to build a model that is exactly the same as the real-world one using the 3D parts that we've drawn. We've weighted each part and Simscape is going to compute the moment of inertia of each of them with that information, the part's geometry, and the axis around which they are turning. We're not going to go into detail here as to how the connections between the parts were created, but they follow the exact same principles of the simple model that we've explained at the beginning of this chapter. Here's the model:

(click to enlarge)
Ground

Rear Wheel

Battery

Servo

Fork

Front Wheel

Boards

Inertia Wheel

(click to enlarge)
Here's the result:


We've set up the parts in different colors to make it easy to visualize. Each of those has its own mass and its moment of inertia is being calculated individually. This is a very powerful tool because as we've mentioned before, by working with equations that we write manually it would take a very long time and would be unpractical to calculate the moment of inertia of each component, but here we can do it using the 3D parts that we'd already had to draw anyway.
​
First let's simulate the free-response with an initial angle of 4º and zero speed, just like before:

We can see that the behavior is the same as before, with the reaction wheel velocity being the opposite of the motorcycle's since it's the relative and not the absolute velocity that we're reading. This model, although it doesn't completely represent reality (remember we're not accounting for friction between the parts, for example), shows us some other characteristics of the real system, since it's computing the behavior of all the parts, taking into account their geometries, densities, etc. In other words, the fact that Simscampe calculates the moment of inertia of all parts separately shows us things that we don't see in the "simple model". For example, the fact that the model isn't 100% symmetrical and the wheels are also not perfectly aligned means that the center of mass of the system isn't in the vertical middle point. It's offset to either side:


This means that the angle where the motorcycle is balancing upright isn't zero anymore, and we have to account for that as we'll see shortly. Later in the real model we'll also notice this bias and how it affects the motorcycle's behavior.
​
Now let's implement the same controller as before with gains of 1, 0.1, and 0.0002 respectively. We've rearranged the model so that it's intuitive to see the plant and the controller:

In the controller, we now have a bias block that in this simulation is set to zero, so it won't have any effect on the system:

The plant is the same as before, with the initial angle set to 4º. Let's see how the system responds:

The response is good, however, notice how the settling angle is -1.5º and not zero. This is because the center of mass, in this case, is located to the left, and therefore to stay balanced the motorcycle has to turn to the right so that the weight forces pass through the cm and there's no torque. This also causes the inertia wheel to spin at a high speed of about 7,400 rpm which is something we do not want. To solve this problem we'll add a bias to the system in order to account for this offset. In other words, we'll make sure that the 0º corresponds to the balance angle:

Now let's see what changes regarding the response:

We've kept the same gains and now there's a little overshoot, which is fine, we can later tune the gains to remove it. The most important thing is that now, with the bias, the motorcycle is settling around 0º and the inertia wheel speed is very low, around 50 RPM. This is the behavior that we want.
​
Let's add some disturbance to the system:

And analyze its behavior as well:

The system responds well to random perturbations. The required torque is never too high, outside the range of our DC motor, and the wheel speed is within acceptable ranges, never settling at a high RPM. Moreover, these perturbations are being generated into the system every 100ms. In the real model this won't be the case as they will be less frequent.
4. Conclusion
In this section, we've modeled a simple and a real system without deriving its differential equations. Simscape allows us to build systems using 3D parts and automatically computes its behavior, making it easier to work with more complex systems, and allowing us to see certain characteristics that would be missed in a simplified model. Now we're ready to test all this in our real-world motorcycle. In the next chapter, we'll implement the exact same controller that we did both here and in the previous part and make the motorcycle self-balance.