Posted: January 9, 2013

After my two recent posts on modeling friction and kinematic clutches, I felt as though I had missed out on some opportunities to explain how these kinds of kinematic models fit into the big picture of transmission modeling. So for this post, I'd like to take a step back and not focus exclusively on the internal workings of components, but to show how these kinds of techniques can be used to model complete subsystems.

I should also point out that all the source code used in this example
and my previous post about kinematic clutches is now available on
GitHub in the `xogeny/Kinematics`

repository and is distributed
under a Creative Commons Attribution 3.0 Unported
License.

Just as with the two previous posts, the models here will be what I would call "functional" models. That is to say that the models should reproduce the function of (in this case) a transmission but without the need to specify lots of design details.

The main function of the transmission is to act as a gear to allow the engine and/or electric motors to generate torque in a speed range that leads to efficient energy conversion. However, since the speed of the vehicle changes over a wide range, it is necessary for the "gear ratio" of the transmission to change in some manner in order to keep the engine/motors operating at their most efficient speeds.

However, a transmission is not always "in gear". For example, when you put the transmission in neutral, the transmission disconnects the engine from the driveline. Also, in an automatic transmission the effects of the torque converter are felt whenever the bypass clutch is disengaged. In this post, our functional transmissions will provide the functionality of neutral, but not the functionality of the torque converter.

The architecture for our transmission model looks like this:

```
partial model PartialTransmission
Modelica.Mechanics.Rotational.Interfaces.Support support "Transmission housing";
Modelica.Mechanics.Rotational.Interfaces.Flange_b output_shaft "Output shaft";
KinematicClutch kinematicClutch(shift_time=engagement_time, start_engaged=start_engaged) "Provides neutral functionality";
Modelica.Mechanics.Rotational.Interfaces.Flange_a input_shaft "Input shaft";
Modelica.Blocks.Interfaces.BooleanInput engage "Signal transmission to engage";
parameter Modelica.SIunits.Time engagement_time;
parameter Boolean start_engaged=true;
protected
replaceable PartialGear gear(final useSupport=true);
equation
connect(gear.support, support);
connect(gear.flange_b, output_shaft);
connect(kinematicClutch.flange_b, gear.flange_a);
connect(kinematicClutch.flange_a, input_shaft);
connect(kinematicClutch.command, engage);
end PartialTransmission;
```

A simple summary of this model is that it includes a gear box and an
engagement clutch. The engagement clutch is the `KinematicClutch`

from my previous post and is controlled by
the Boolean input signal `engage`

, which is used to signal the
transmission to engage (i.e., shift out of neutral).

Note that the `gear`

model is `replaceable`

. This is, in fact, why
the entire model is `partial`

. The model is useless unless an
**actual** gear model is specified.

As an aside, you may also notice that the `gear`

model is in a
`protected`

section. This is by design. In order to make this model
into a non-partial version, a gear model must be specified. Because
the `gear`

model is protected, such a change can only be made by
**extending** from this class. It may seem like a minor point, but
this is actually a useful and important technique for model
management. Without this "pattern", people might drag **this** model
down into a diagram and then modify the gear model. For reasons that
I won't really get into now (perhaps a topic for a future post), this
can create some serious headaches for managing complex models. By
making the `gear`

model protected, it forces users to create a new
**named model**, not just some "anonymous instance". But I digress,
back to the topic at hand.

We will use this model as the foundation for two models in this post, a continuously variable transmission (CVT) model and a step ratio transmission model.

Most of the interesting behavior in our transmission will come from a
gear model. We already saw that our `PartialTransmission`

model
specifies a way to specify the particular kind of gear model we want
in the transmission. The interface for the model is defined by the
`PartialGear`

model and looks like this:

```
partial model PartialGear "Base class for a variety of kinematic gear models"
extends Modelica.Mechanics.Rotational.Interfaces.PartialElementaryTwoFlangesAndSupport2;
protected
Real R "gear ratio";
Modelica.SIunits.Angle phi_a "Angle between left shaft flange and support";
Modelica.SIunits.Angle phi_b "Angle between right shaft flange and support";
equation
phi_a = flange_a.phi - phi_support;
phi_b = flange_b.phi - phi_support;
der(phi_a) = R*der(phi_b);
0 = R*flange_a.tau + flange_b.tau;
end PartialGear;
```

This is almost an exact copy of the `IdealGear`

model from the
Modelica Standard Library (MSL). This model is `partial`

because the
gear ratio, `R`

, is declared in the model, but there is no equation for
it. In order to create a non-partial implementation, it is necessary
to extend this model and provide a definition for the behavior of `R`

As another aside, one thing to note here is the presence of a
`support`

element to represent the housing of the gear box. Far too
often, people overlook the effects of reaction torques in drivelines
so I always make it a point to explicitly include the transmission
housing, even if I simply connect it to a mechanical ground.

If we wish to create a CVT model, the only thing we really need to do is create a continuously variable gear model. At first glance, the following model might appear to suffice:

```
model CVT_Gear "A continuously variable gear"
extends Modelica.Mechanics.Rotational.Icons.Gear;
extends Kinematics.Interfaces.PartialGear;
Modelica.Blocks.Interfaces.RealInput ratio "Desired gear ratio";
equation
R = ratio;
end CVT_Gear;
```

However, there is a subtle problem here. With this definition, we
have no assurances about the smoothness of the input signal `ratio`

.
Specifically, it might not be smooth. This means someone could
command a step change in ratio. This is a problem because in our
previous base class, `PartialGear`

, we had the following line:

```
der(phi_a) = R*der(phi_b);
```

It turns out that in most cases this line will be differentiated as
part of the index reduction
process. If so,
it will typically be necessary to differentiate `R`

with respect to
time.

To handle cases where index reduction may be performed, we ensure the necessary smoothness directly in our model by using a first order filter on the input signal. This is actually well aligned with the function of the CVT since CVTs cannot support step changes in ratio anyway. So our modification will not only provide the mathematical assurances we need, but will also mimic the functional behavior of the CVT. The resulting model looks like this:

```
model SmoothCVT_Gear "A continuously variable gear with smoothing"
extends Modelica.Mechanics.Rotational.Icons.Gear;
extends Kinematics.Interfaces.PartialGear;
parameter Modelica.SIunits.Time tau "Time constant for ratio change";
Modelica.Blocks.Interfaces.RealInput ratio "Desired gear ratio";
initial equation
R = ratio;
equation
tau*der(R) = ratio-R;
end SmoothCVT_Gear;
```

where `tau`

represents the time constant for the CVT shifting
process. Once we have this `SmoothCVT_Gear`

component model, we can
combine it with our `PartialTransmission`

model for a complete
(non-partial) CVT model:

```
model CVT_Transmission "A transmission with a continuous variable gear ratio"
extends Interfaces.PartialTransmission(redeclare
Kinematics.Components.SmoothCVT_Gear gear(tau=tau));
Modelica.Blocks.Interfaces.RealInput ratio "Desired gear ratio";
parameter Modelica.SIunits.Time tau "Time constant for ratio change";
equation
connect(gear.ratio, ratio);
end CVT_Transmission;
```

Voila! A continuous variable transmission model that includes all the functional behavior (neutral, engagement time, ratio change dynamics) but without the need to specify any design details.

To provide yet another example of defining functional behavior
kinematically, let's consider the behavior of the more common step
ratio transmission model. This is the kind of behavior you see in
most cars (either automatic or manual). In this case, the
transmission cannot take on just *any* gear ratio but is constrained
to a relatively small number of specific ratios.

Again, we start by extending the `PartialGear`

model:

```
model StepRatio_Gear "A step ratio gear model"
extends Modelica.Mechanics.Rotational.Icons.Gear;
extends Kinematics.Interfaces.PartialGear;
parameter Real ratios[:] "Discrete gear ratios";
Modelica.Blocks.Interfaces.IntegerInput gear "Desired gear";
parameter Modelica.SIunits.Time shift_time "Time to shift gears";
protected
Modelica.SIunits.DampingCoefficient dR "Rate of ratio change";
Modelica.SIunits.Time start_time "Start of last shift";
initial equation
R = ratios[gear];
dR = 0;
start_time = time-2*shift_time;
equation
der(R) = if time<=start_time+shift_time then dR else 0;
when change(gear) then
start_time = time;
dR = (ratios[gear]-R)/shift_time;
end when;
assert(gear>=1 and gear<=size(ratios,1),
"Selected gear is outside valid range of 1-"+String(size(ratios,1)));
end StepRatio_Gear;
```

The interface to this model has three elements:

```
parameter Real ratios[:] "Discrete gear ratios";
Modelica.Blocks.Interfaces.IntegerInput gear "Desired gear";
parameter Modelica.SIunits.Time shift_time "Time to shift gears";
```

The `ratios`

array contains the set of discrete ratios that the
transmission can support. The `gear`

input signal is an integer
signal that indicates which of the specified gear ratios is being
requested. Finally, the `shift_time`

is another parameter related to
the internal dynamics. As we have seen repeatedly with these
kinematic models, the timing of the events (shifting, engagement, etc.)
are, once again, **prescribed** by a parameter.

You may notice the presence of the `assert`

statement in the model.
This ensures that the input values for `gear`

stay within the expected
range of 1-N (where N is the number of discrete gear ratios). Should
the input stray outside that range, an error will be generated by this
`assert`

statement. The `assert`

statement is an extremely useful and
important part of making models that are robust and fail gracefully
when inputs or variables exceed their expected limits.

You will see many similarities between the implementation of this
model and the `KinematicClutch`

model. Whereas the `SmoothCVT_Gear`

model used a first order response to change from one ratio to another,
the `KinematicClutch`

and `StepRatio_Gear`

models slew linearly.

As with the CVT case, creating a complete transmission model is simply
a matter of extending the `PartialTransmission`

model:

```
model StepRatioTransmission "A step ratio transmission"
extends Interfaces.PartialTransmission(redeclare
Kinematics.Components.StepRatio_Gear gear(shift_time=shift_time, ratios=ratios));
parameter Modelica.SIunits.Time shift_time "Time to shift gears";
parameter Real ratios[:] "Discrete gear ratios";
Modelica.Blocks.Interfaces.IntegerInput gear_cmd "Desired gear";
equation
connect(gear.gear, gear_cmd);
end StepRatioTransmission;
```

Another benefit of this approach that I completely failed to mention
when discussing the `KinematicClutch`

models was the ability to do
backward driven models.

In the world of drive cycle simulation, there are two different "flavors" of models. The first are "forward driven", where the solution process starts with specifying the driver pedal demand and then, from there, the engine torque is computed, which gives the output torque of the transmission, which then allows the acceleration (and therefore speed) of the vehicle to be computed. However, because the speed of the vehicle is actually specified for standard drive cycles, a "backward driven" approach is often used where the speed of the vehicle is known and from there the vehicle acceleration is computed, which then leads to the calculation of the required output torque from the transmission and this allows the engine torque to be calculated, which can then be mapped to the driver pedal demand.

The beauty of these kinematic models is that **they can be used for
both forward and backward driven use cases** without any change to the
transmission model!

Consider the following forward driven model:

Note here how the torque applied to the transmission is explicitly specified. From such a simulation, we can then plot the resulting response for the load inertia:

Here is a backward driven version of the same model:

Now, to make this a backward driven model we only need to introduce a
sensor to measure speed response, a block to indicate our desired
response and an `InverseBlockConstraints`

block and we now have a
backward driven model. The essential point here is that **we did not
change the physical model at all**, only the way that the input torque
was specified.

We can see in the simulation results that the kinematic constraint (the desired response) was met perfectly and the torque required to achieve this response is computed for us:

If you have built models like this using a "block diagram" approach (e.g. in Simulink), it may seem like we've done a bit more work than expected here in smoothing and slewing these ratio changes. At first glance, it may not be obvious why this is necessary.

There are two points to make here. First, keep in mind that because of the object-oriented nature of Modelica most of the heavy lifting (dealing with smoothness of the ratio change) really only needs to be done once for each type of model and can be encapsulated within the transmission model as we have shown.

Second, and more importantly, these models are based on conservation
principles. Specifically, we are assured conservation of angular
momentum in these models. This, in turn, means that our simulation
results will always yield all the appropriate **reaction torques** in
the model.

When specifying behavior in terms of kinematic constraints, you are
formulating **implicit**, rather than explicit, equations for the
torques involved. In a sense, you are saying "compute the torque
**such that** this kinematic relationship will always be true". This
is actually quite powerful because it means that you can then go back
after a simulation and examine how much torque the `KinematicClutch`

had to be able to generate in friction or how much torque the input
shaft of the transmission needs to withstand for a given maneuver.

There are actually several different reaction torques of interest in the
examples shown. First, the `KinematicClutch`

model will compute how
much torque is necessary in order to engage the clutch and keep it
engaged (also called the "clutch torque capacity"). The gear models
(e.g. CVT, step ratio) will compute the amount of torque the
transmission will have to handle during a shift. In particular, the
so called "inertia torque", which results from having to speed up or
slow down rotating elements will be computed in our approach. For a
backward driven model, the torque required to achieve the desired
response is a form of "reaction torque" and will be computed for us.
Finally, the reaction torque on the transmission housing (due to the
kinematic constraint that "grounds" it) is also
computed. This gives you a sense of the kind of loadings that the
powertrain mount system will have to handle.

All this comes at minimal cost because of the ubiquitous application of conservation principles.

In conclusion, the use of kinematic constraints is not restricted to component models but can be a very effective tool in the early stages of a system engineering driven process to predict the behavior of systems and subsystems without the need for design information.

Since these kinds of functional models are often used for system level
design and verification processes in system engineering, this gives
kinematic models two big advantages. First, they can successfully
avoid requiring design information (which would mean going deeper down
the system engineering V than
is strictly required at this point) **and** it means that the models
can yield key requirements (torque capacity of clutches, stresses in
shafts, etc.) that must be cascaded down the design side of the V for
the next step of the process. This not only allows options and
concepts to be quickly explored but can be used to formulate
requirements that will ultimately drive the design process.

As mentioned previously, the source code for all of the models
described in this post is available on GitHub in the
`xogeny/Kinematics`

repository
and is distributed under a Creative Commons Attribution 3.0 Unported
License.

## Share your thoughts

comments powered by Disqus