1 - Simple Powertrain¶
System in Analysis¶
The complete example code is available
here.
The mechanical powertrain to be studied is reported in the image below:

The flywheel and the gear 1 are connected to the DC motor output
shaft and rotate with it. The gear 2 mates with gear 1 and is
connected to gear 3 through a rigid shaft, so gear 2 and gear 3
rotate together. The gear 3 mates with gear 4, to which is connected
to gear 5 through another rigid shaft, so gear 4 and gear 5 rotate
together. Finally, gear 5 mates with gear 6, which is connected to
the external load.
The analysis is focused on powertrain elements kinematics and torques.
Model Set Up¶
As a first step, we instantiate the components of the mechanical powertrain:
from gearpy.mechanical_objects import DCMotor, Flywheel, SpurGear
from gearpy.units import AngularSpeed, InertiaMoment, Torque
motor = DCMotor(
name='motor',
no_load_speed=AngularSpeed(15000, 'rpm'),
maximum_torque=Torque(10, 'mNm'),
inertia_moment=InertiaMoment(3, 'gcm^2')
)
flywheel = Flywheel(
name='flywheel',
inertia_moment=InertiaMoment(20, 'kgcm^2')
)
gear_1 = SpurGear(
name='gear 1',
n_teeth=10,
inertia_moment=InertiaMoment(1, 'gcm^2')
)
gear_2 = SpurGear(
name='gear 2',
n_teeth=80,
inertia_moment=InertiaMoment(3100, 'gcm^2')
)
gear_3 = SpurGear(
name='gear 3',
n_teeth=10,
inertia_moment=InertiaMoment(4, 'gcm^2')
)
gear_4 = SpurGear(
name='gear 4',
n_teeth=60,
inertia_moment=InertiaMoment(5000, 'gcm^2')
)
gear_5 = SpurGear(
name='gear 5',
n_teeth=10,
inertia_moment=InertiaMoment(12, 'gcm^2')
)
gear_6 = SpurGear(
name='gear 6',
n_teeth=50,
inertia_moment=InertiaMoment(7600, 'gcm^2')
)
See DCMotor,
Flywheel and
SpurGear for
more details on instantiation parameters.
Then it is necessary to specify the connection types between the
components. We choose to study a non-ideal powertrain so, in order to
take into account power loss in mating due to friction, we specify a
\(90\%\) gear mating efficiency:
from gearpy.utils import add_fixed_joint, add_gear_mating
add_fixed_joint(master=motor, slave=flywheel)
add_fixed_joint(master=flywheel, slave=gear_1)
add_gear_mating(master=gear_1, slave=gear_2, efficiency=0.9)
add_fixed_joint(master=gear_2, slave=gear_3)
add_gear_mating(master=gear_3, slave=gear_4, efficiency=0.9)
add_fixed_joint(master=gear_4, slave=gear_5)
add_gear_mating(master=gear_5, slave=gear_6, efficiency=0.9)
See add_fixed_joint
and add_gear_mating
for more details.
We have to define the external load applied to gear 6. To keep the
example simple, we can consider a constant load torque:
def ext_torque(time, angular_position, angular_speed):
return Torque(500, 'mNm')
gear_6.external_torque = ext_torque
Finally, it is necessary to combine all components in a powertrain object:
from gearpy.powertrain import Powertrain
powertrain = Powertrain(motor=motor)
See Powertrain for more
details on this class and its methods.
Simulation Set Up¶
Before performing the simulation, it is necessary to specify the initial condition of the system in terms of angular position and speed of the last gear in the mechanical powertrain. In this case we can consider the gear 6 still in the reference position:
from gearpy.units import AngularPosition
gear_6.angular_position = AngularPosition(0, 'rad')
gear_6.angular_speed = AngularSpeed(0, 'rad/s')
Finally, we have to set up the simulation parameters: the time discretization for the time integration and the simulation time. Now we are ready to run the simulation::
from gearpy.units import TimeInterval
from gearpy.solver import Solver
solver = Solver(powertrain=powertrain)
solver.run(
time_discretization=TimeInterval(0.5, 'sec'),
simulation_time=TimeInterval(20, 'sec')
)
See Solver for more details.
Results Analysis¶
We can get a snapshot of the system at a particular time of interest:
from gearpy.units import Time
powertrain.snapshot(target_time=Time(10, 'sec'))
Mechanical Powertrain Status at Time = 10 sec
angular position (rad) angular speed (rad/s) angular acceleration (rad/s^2) torque (Nm) driving torque (Nm) load torque (Nm) pwm
motor 9714.908984 1119.894923 1.085094 0.000013 0.002871 0.002858 1.0
flywheel 9714.908984 1119.894923 1.085094 0.000013 0.002871 0.002858
gear 1 9714.908984 1119.894923 1.085094 0.000013 0.002871 0.002858
gear 2 1214.363623 139.986865 0.135637 0.000092 0.020668 0.020576
gear 3 1214.363623 139.986865 0.135637 0.000092 0.020668 0.020576
gear 4 202.393937 23.331144 0.022606 0.000495 0.111606 0.111111
gear 5 202.393937 23.331144 0.022606 0.000495 0.111606 0.111111
gear 6 40.478787 4.666229 0.004521 0.002227 0.502227 0.500000
The default unit used for torques are not so convenient in this case, so we prefer to get results in a different unit:
powertrain.snapshot(
target_time=Time(10, 'sec'),
angular_position_unit='rot',
torque_unit='mNm',
driving_torque_unit='mNm',
load_torque_unit='mNm'
)
Mechanical Powertrain Status at Time = 10 sec
angular position (rot) angular speed (rad/s) angular acceleration (rad/s^2) torque (mNm) driving torque (mNm) load torque (mNm) pwm
motor 1546.175787 1119.894923 1.085094 0.012731 2.870527 2.857796 1.0
flywheel 1546.175787 1119.894923 1.085094 0.012731 2.870527 2.857796
gear 1 1546.175787 1119.894923 1.085094 0.012731 2.870527 2.857796
gear 2 193.271973 139.986865 0.135637 0.091666 20.667798 20.576132
gear 3 193.271973 139.986865 0.135637 0.091666 20.667798 20.576132
gear 4 32.211996 23.331144 0.022606 0.494998 111.606109 111.111111
gear 5 32.211996 23.331144 0.022606 0.494998 111.606109 111.111111
gear 6 6.442399 4.666229 0.004521 2.227489 502.227489 500.000000
See
Powertrain.snapshot
for more details on method parameters.
Notice that the load torque applied on the gear 6 is exactly the
constant external torque we defined beforehand.
About 10 seconds after the simulation start, the driving torque applied
on gear 6 is almost equal to the load torque on it, resulting in a
very tiny angular acceleration. As a result, we can conclude that the
system is almost in a stationary condition 10 seconds after the start.
We can get a more general view of the system by plotting the time
variables of each element with respect to time:
powertrain.plot(figsize=(12, 9))

This plot is pretty crowded, and we are not interested in all time variables, so we can focus the plot only on interesting elements and variables. We can also specify a more convenient unit to use when plotting torques:
powertrain.plot(
elements=['gear 6', motor],
variables=['torque', 'driving torque', 'angular speed', 'load torque'],
torque_unit='mNm',
figsize=(8, 6)
)

See Powertrain.plot for
more details on method parameters.
Notice that we specified the elements either by the string name or by
instance name, both ways work. Also notice that the plot automatically
sorts:
the elements: the motor on the left and following elements proceeding to the right,
the time variables: kinematic variables at the top, then torques
grouped together in a single row and motor PWM in the last row.
We can see that at 10 seconds the angular speeds of motor and gear 6
are almost constant, confirming the insight previously mentioned by
analyzing the time snapshot: at 10 seconds the system is almost in a
stationary state.
We can see that, as the time passes, the driving torque on gear 6
equals the constant load torque and, as a result, the net torque on the
gear becomes close to zero.