Skip to content

Mechatronics

Mechatronics: mechanisms joined to circuits and suspensions of masses, springs, and dampers.

ArmatureElement(label, visual=None, *, p_v=0.0, p_i=0.0, n_v=0.0, n_i=0.0)

Bases: TwoPinElement

Winding of a motor, a two-pin element whose voltage the coupling with the inertia of the motor gives.

Parameters:

Name Type Description Default
label str

The label of the element, unique among the parts of its system.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
p_v object

The potential of the positive pin.

0.0
p_i object

The current into the positive pin.

0.0
n_v object

The potential of the negative pin.

0.0
n_i object

The current into the negative pin.

0.0

Examples:

>>> from skcomplex.systems.engineering.mechatronics import ArmatureElement
>>> sorted(ArmatureElement.ports)
['n', 'p']
Source code in src/skcomplex/systems/engineering/mechatronics/_mechatronics.py
53
54
55
56
57
58
59
60
61
62
63
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    p_v: object = 0.0,
    p_i: object = 0.0,
    n_v: object = 0.0,
    n_i: object = 0.0,
) -> None:
    super().__init__(label, visual, p_v=p_v, p_i=p_i, n_v=n_v, n_i=n_i)

InertiaElement(label, visual=None, *, phi=0.0, phi_d1=0.0, J=1.0, b=1.0)

Bases: Element

Rotating inertia of the angle phi, a coordinate of a Lagrangian.

Parameters:

Name Type Description Default
label str

The label of the element, unique among the parts of its system.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
phi Annotated[object, StateSpec(order=2)]

The initial angle.

0.0
phi_d1 object

The initial angular velocity.

0.0
J Annotated[object, ParameterSpec(domain=POSITIVE)]

The moment of inertia.

1.0
b Annotated[object, ParameterSpec(domain=POSITIVE)]

The coefficient of viscous friction.

1.0

Examples:

>>> from skcomplex.systems.engineering.mechatronics import InertiaElement
>>> InertiaElement('rotor', J=0.5).J
0.5
Source code in src/skcomplex/systems/engineering/mechatronics/_mechatronics.py
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    phi: Annotated[object, StateSpec(order=2)] = 0.0,
    phi_d1: object = 0.0,
    J: Annotated[object, ParameterSpec(domain=POSITIVE)] = 1.0,
    b: Annotated[object, ParameterSpec(domain=POSITIVE)] = 1.0,
) -> None:
    super().__init__(label, visual=visual)
    self.phi = phi
    self.phi_d1 = phi_d1
    self.J = J
    self.b = b

LevitatedBallElement(label, visual=None, *, v=0.0, b=1.0, m=0.2)

Bases: Element

Conductive ball levitated in a vacuum, whose velocity relaxes between the impulses of the levitating field.

Between impulses the velocity follows v' = -b v, and every impulse of the field changes it by m or -m.

Parameters:

Name Type Description Default
label str

The label of the ball.

required
visual VisualSpec | None

How the ball is drawn, or None for default_visual_.

None
v Annotated[float, StateSpec()]

The initial velocity.

0.0
b Annotated[float, ParameterSpec(domain=open(0, oo))]

The damping rate.

1.0
m Annotated[float, ParameterSpec()]

The strength of every impulse.

0.2

Examples:

>>> from skcomplex.systems.engineering.mechatronics import LevitatedBallElement
>>> LevitatedBallElement('ball').m
0.2
Source code in src/skcomplex/systems/engineering/mechatronics/_magnetic_levitation.py
48
49
50
51
52
53
54
55
56
57
58
59
60
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    v: Annotated[float, StateSpec()] = 0.0,
    b: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.0,
    m: Annotated[float, ParameterSpec()] = 0.2,
) -> None:
    super().__init__(label, visual=visual)
    self.v = v
    self.b = b
    self.m = m

MotorCouplingInteraction(label, *, armature, inertia, k=1.0)

Bases: Interaction

Coupling of an armature and an inertia by a motor constant k.

The voltage of the armature is the back electromotive force k phi', and its current exerts the torque k p_i on the angle, which adds to the Euler-Lagrange equation of the angle.

Parameters:

Name Type Description Default
label str

The label of the interaction, unique among the parts of its system.

required
armature Annotated[str, RoleSpec()]

The path of the armature.

required
inertia Annotated[str, RoleSpec()]

The path of the inertia.

required
k Annotated[object, ParameterSpec(domain=POSITIVE)]

The motor constant.

1.0

Examples:

>>> from skcomplex.systems.engineering.mechatronics import MotorCouplingInteraction
>>> MotorCouplingInteraction('motor', armature='winding', inertia='rotor', k=0.5).k
0.5
Source code in src/skcomplex/systems/engineering/mechatronics/_mechatronics.py
223
224
225
226
227
228
229
230
231
232
233
234
def __init__(
    self,
    label: str,
    *,
    armature: Annotated[str, RoleSpec()],
    inertia: Annotated[str, RoleSpec()],
    k: Annotated[object, ParameterSpec(domain=POSITIVE)] = 1.0,
) -> None:
    super().__init__(label)
    self.armature = armature
    self.inertia = inertia
    self.k = k

QuarterCarElement(label, visual=None, *, y1=0.0, y1_d1=0.0, y2=0.0, y2_d1=0.0, m1=250.0, m2=30.0, k=16000.0, b=1000.0, kt=160000.0, height=0.05, at=0.5)

Bases: Element

Body of displacement y1 and wheel of displacement y2, with a tire between the wheel and a road step.

The element holds the tire, whose force on the wheel is kt (road - y2), and a suspension interaction joins the body and the wheel.

Parameters:

Name Type Description Default
label str

The label of the element, unique among the parts of its system.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
y1 Annotated[object, StateSpec(order=2)]

The initial displacement of the body.

0.0
y1_d1 object

The initial velocity of the body.

0.0
y2 Annotated[object, StateSpec(order=2)]

The initial displacement of the wheel.

0.0
y2_d1 object

The initial velocity of the wheel.

0.0
m1 Annotated[object, ParameterSpec(domain=POSITIVE)]

The mass of the body.

250.0
m2 Annotated[object, ParameterSpec(domain=POSITIVE)]

The mass of the wheel.

30.0
k Annotated[object, ParameterSpec(domain=POSITIVE)]

The stiffness of the suspension.

16000.0
b Annotated[object, ParameterSpec(domain=POSITIVE)]

The damping of the suspension.

1000.0
kt Annotated[object, ParameterSpec(domain=POSITIVE)]

The stiffness of the tire.

160000.0
height Annotated[object, ParameterSpec()]

The height of the road step.

0.05
at Annotated[object, ParameterSpec()]

The time of the road step.

0.5

Examples:

>>> from skcomplex.systems.engineering.mechatronics import QuarterCarElement
>>> QuarterCarElement('car', height=0.05).height
0.05
Source code in src/skcomplex/systems/engineering/mechatronics/_mechatronics.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    y1: Annotated[object, StateSpec(order=2)] = 0.0,
    y1_d1: object = 0.0,
    y2: Annotated[object, StateSpec(order=2)] = 0.0,
    y2_d1: object = 0.0,
    m1: Annotated[object, ParameterSpec(domain=POSITIVE)] = 250.0,
    m2: Annotated[object, ParameterSpec(domain=POSITIVE)] = 30.0,
    k: Annotated[object, ParameterSpec(domain=POSITIVE)] = 16000.0,
    b: Annotated[object, ParameterSpec(domain=POSITIVE)] = 1000.0,
    kt: Annotated[object, ParameterSpec(domain=POSITIVE)] = 160000.0,
    height: Annotated[object, ParameterSpec()] = 0.05,
    at: Annotated[object, ParameterSpec()] = 0.5,
) -> None:
    super().__init__(label, visual=visual)
    self.y1 = y1
    self.y1_d1 = y1_d1
    self.y2 = y2
    self.y2_d1 = y2_d1
    self.m1 = m1
    self.m2 = m2
    self.k = k
    self.b = b
    self.kt = kt
    self.height = height
    self.at = at

VibratingTableElement(label, visual=None, *, i2=0.0, uC=0.0, x=0.0, v=0.0, U=0.141, omega=1.5915, R=1.5, L=0.25, C=0.1, K=500.0, m=10.0, B=2.0, k1=0.5, k2=17.0, alpha=2.5, linear=False)

Bases: Element

Electromagnetic vibrating table, a shaker whose table a supplied electromagnet pulls against a spring.

The source u = U sin(omega t) feeds a resistor R and a capacitor C, whose voltage uC drives the current i2 of the coil L against the back electromotive force k1 v of the moving table. The electromagnet pulls the table of mass m, held by a spring K and a damper B, with the force g(i2) = k2 tan(alpha i2) / alpha, or with its linearization k2 i2 at the origin. The states follow i2' = (uC - k1 v) / L, uC' = (u - uC) / (R C) - i2 / C, x' = v, and m v' = g(i2) - K x - B v.

Parameters:

Name Type Description Default
label str

The label of the shaker.

required
visual VisualSpec | None

How the shaker is drawn, or None for default_visual_.

None
i2 Annotated[float, StateSpec()]

The initial current of the coil.

0.0
uC Annotated[float, StateSpec()]

The initial voltage of the capacitor.

0.0
x Annotated[float, StateSpec()]

The initial displacement of the table.

0.0
v Annotated[float, StateSpec()]

The initial velocity of the table.

0.0
U Annotated[float, ParameterSpec()]

The amplitude of the supply voltage.

0.141
omega Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The angular frequency of the supply voltage.

1.5915
R Annotated[float, ParameterSpec(domain=open(0, oo))]

The resistance.

1.5
L Annotated[float, ParameterSpec(domain=open(0, oo))]

The inductance of the coil.

0.25
C Annotated[float, ParameterSpec(domain=open(0, oo))]

The capacitance.

0.1
K Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The stiffness of the spring.

500.0
m Annotated[float, ParameterSpec(domain=open(0, oo))]

The mass of the table.

10.0
B Annotated[float, ParameterSpec(domain=closed_open(0, oo))]

The damping coefficient.

2.0
k1 Annotated[float, ParameterSpec()]

The electromechanical constant of the back electromotive force.

0.5
k2 Annotated[float, ParameterSpec()]

The mechanical-electrical constant, the slope of the force of the electromagnet at zero current.

17.0
alpha Annotated[float, ParameterSpec(domain=open(0, oo))]

The scale of the current in the characteristic of the electromagnet.

2.5
linear bool

Whether the force of the electromagnet is its linearization k2 i2.

False

Examples:

>>> from skcomplex.systems.engineering.mechatronics import VibratingTableElement
>>> VibratingTableElement('shaker').k2
17.0
Source code in src/skcomplex/systems/engineering/mechatronics/_vibrating_table.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    i2: Annotated[float, StateSpec()] = 0.0,
    uC: Annotated[float, StateSpec()] = 0.0,
    x: Annotated[float, StateSpec()] = 0.0,
    v: Annotated[float, StateSpec()] = 0.0,
    U: Annotated[float, ParameterSpec()] = 0.141,
    omega: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 1.5915,
    R: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 1.5,
    L: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.25,
    C: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 0.1,
    K: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 500.0,
    m: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 10.0,
    B: Annotated[float, ParameterSpec(domain=RealSet.closed_open(0, oo))] = 2.0,
    k1: Annotated[float, ParameterSpec()] = 0.5,
    k2: Annotated[float, ParameterSpec()] = 17.0,
    alpha: Annotated[float, ParameterSpec(domain=RealSet.open(0, oo))] = 2.5,
    linear: bool = False,
) -> None:
    super().__init__(label, visual=visual)
    self.i2 = i2
    self.uC = uC
    self.x = x
    self.v = v
    self.U = U
    self.omega = omega
    self.R = R
    self.L = L
    self.C = C
    self.K = K
    self.m = m
    self.B = B
    self.k1 = k1
    self.k2 = k2
    self.alpha = alpha
    self.linear = linear

dc_motor(V=12.0, *, R=1.0, L=0.5, k=0.5, J=0.1, b=0.2)

Return a DC motor whose armature circuit of components drives an inertia on a Lagrangian coordinate.

A voltage source drives a resistor, an inductor, and the armature in series. The armature has the voltage k phi', and its current exerts the torque k i on the angle of an inertia with viscous friction, so the angular velocity settles at k V / (R b + k^2).

Parameters:

Name Type Description Default
V float

The voltage of the source.

12.0
R float

The resistance of the armature circuit.

1.0
L float

The inductance of the armature circuit.

0.5
k float

The motor constant.

0.5
J float

The moment of inertia of the rotor.

0.1
b float

The coefficient of viscous friction of the rotor.

0.2

Returns:

Name Type Description
system System

The system, with the angle rotor.phi, the angular velocity rotor.phi_d1, and the current winding.p_i.

Examples:

>>> from skcomplex.systems.engineering.mechatronics import dc_motor
>>> dc_motor(k=0.3).interactions[-1].k
0.3
Source code in src/skcomplex/systems/engineering/mechatronics/_mechatronics.py
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
@register_system(
    field='engineering/mechatronics',
    tags=('mechatronics', 'circuit', 'acausal components', 'euler-lagrange', 'ode'),
    references=('Fritzson 2015',),
    defaults={'until': 10.0, 'dt': 0.01},
    observables=lambda system: [
        ObservableSpec('speed', _speed_of_rotor),
        ObservableSpec('current', _current_of_winding),
    ],
)
def dc_motor(
    V: float = 12.0,
    *,
    R: float = 1.0,
    L: float = 0.5,
    k: float = 0.5,
    J: float = 0.1,
    b: float = 0.2,
) -> System:
    """Return a DC motor whose armature circuit of components drives an inertia on a Lagrangian coordinate.

    A voltage source drives a resistor, an inductor, and the armature in series. The armature has the voltage `k phi'`,
    and its current exerts the torque `k i` on the angle of an inertia with viscous friction, so the angular velocity
    settles at `k V / (R b + k^2)`.

    Args:
        V:
            The voltage of the source.

        R:
            The resistance of the armature circuit.

        L:
            The inductance of the armature circuit.

        k:
            The motor constant.

        J:
            The moment of inertia of the rotor.

        b:
            The coefficient of viscous friction of the rotor.

    Returns:
        system:
            The system, with the angle `rotor.phi`, the angular velocity `rotor.phi_d1`, and the current `winding.p_i`.

    Examples:
        >>> from skcomplex.systems.engineering.mechatronics import dc_motor
        >>> dc_motor(k=0.3).interactions[-1].k
        0.3
    """
    return System(
        elements=[
            VoltageSourceElement('source', V=V),
            ResistorElement('resistor', R=R),
            InductorElement('coil', L=L),
            ArmatureElement('winding'),
            GroundElement('ground'),
            InertiaElement('rotor', J=J, b=b),
        ],
        interactions=[
            ConnectionInteraction('supply', members=['source', 'resistor'], ports=['p', 'p']),
            ConnectionInteraction('series', members=['resistor', 'coil'], ports=['n', 'p']),
            ConnectionInteraction('terminal', members=['coil', 'winding'], ports=['n', 'p']),
            ConnectionInteraction('neutral', members=['winding', 'source', 'ground'], ports=['n', 'n', 'p']),
            EulerLagrangeInteraction(
                'rotation',
                target='rotor',
                states='phi',
                lagrangian=_rotor_lagrangian,
                dissipation=_rotor_dissipation,
            ),
            MotorCouplingInteraction('motor', armature='winding', inertia='rotor', k=k),
        ],
    )

magnetic_levitation(v=None, *, b=1.0, m=0.2)

Return a conductive ball levitated in a vacuum by a field that pushes and pulls it with alternating impulses.

The velocity follows v' + b v = m Σ_k [δ(t + 1 - 4 k) - δ(t - 1 - 4 k)]: it relaxes freely, rises by m at the times 4 k - 1, and falls by m at the times 4 k + 1. Its periodic solution, with the triangular wave τ(t) = (2 / π) arcsin(sin(π t / 2)) and the rectangular wave e(t) = sign(cos(π t / 2)), is v = m / (2 cosh b) exp(-b τ(t) e(t)) e(t), which the ball follows from the start when it starts at m / (2 cosh b).

Parameters:

Name Type Description Default
v float | None

The initial velocity, or None for the value m / (2 cosh b) of the periodic solution at time 0.

None
b float

The damping rate.

1.0
m float

The strength of every impulse.

0.2

Returns:

Name Type Description
system System

The system, with the velocity ball.v, raised by the impulses push and lowered by the impulses pull.

Examples:

>>> from skcomplex.systems.engineering.mechatronics import magnetic_levitation
>>> round(magnetic_levitation(b=1.0, m=0.2).elements[0].v, 4)
0.0648
Source code in src/skcomplex/systems/engineering/mechatronics/_magnetic_levitation.py
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
@register_system(
    field='engineering/mechatronics',
    tags=('mechatronics', 'levitation', 'impulses', 'events', 'ode'),
    references=('Pilipchuk 2010', 'Trzaska 2023'),
    defaults={'until': 20.0, 'dt': 0.01},
)
def magnetic_levitation(v: float | None = None, *, b: float = 1.0, m: float = 0.2) -> System:
    """Return a conductive ball levitated in a vacuum by a field that pushes and pulls it with alternating impulses.

    The velocity follows `v' + b v = m Σ_k [δ(t + 1 - 4 k) - δ(t - 1 - 4 k)]`: it relaxes freely, rises by `m` at the
    times `4 k - 1`, and falls by `m` at the times `4 k + 1`. Its periodic solution, with the triangular wave
    `τ(t) = (2 / π) arcsin(sin(π t / 2))` and the rectangular wave `e(t) = sign(cos(π t / 2))`, is
    `v = m / (2 cosh b) exp(-b τ(t) e(t)) e(t)`, which the ball follows from the start when it starts at
    `m / (2 cosh b)`.

    Args:
        v:
            The initial velocity, or `None` for the value `m / (2 cosh b)` of the periodic solution at time 0.

        b:
            The damping rate.

        m:
            The strength of every impulse.

    Returns:
        system:
            The system, with the velocity `ball.v`, raised by the impulses `push` and lowered by the impulses `pull`.

    Examples:
        >>> from skcomplex.systems.engineering.mechatronics import magnetic_levitation
        >>> round(magnetic_levitation(b=1.0, m=0.2).elements[0].v, 4)
        0.0648
    """
    start = m / (2 * math.cosh(b)) if v is None else v
    push = {'v': lambda s: s.target.v + s.target.m}
    pull = {'v': lambda s: s.target.v - s.target.m}
    return System(
        elements=[LevitatedBallElement('ball', v=start, b=b, m=m)],
        interactions=[
            ImpulseInteraction('push', target='ball', reset=push, period=IMPULSE_PERIOD, start=3.0),
            ImpulseInteraction('pull', target='ball', reset=pull, period=IMPULSE_PERIOD, start=1.0),
        ],
    )

quarter_car(height=0.05, *, at=0.5, m1=250.0, m2=30.0, k=16000.0, b=1000.0, kt=160000.0)

Return a quarter-car suspension driving over a road step.

A body of mass m1 rests on a spring and a damper above a wheel of mass m2, and a tire spring joins the wheel to the road, which steps to height at time at. Both displacements settle at the height of the step.

Parameters:

Name Type Description Default
height float

The height of the road step.

0.05
at float

The time of the road step.

0.5
m1 float

The mass of the body.

250.0
m2 float

The mass of the wheel.

30.0
k float

The stiffness of the suspension.

16000.0
b float

The damping of the suspension.

1000.0
kt float

The stiffness of the tire.

160000.0

Returns:

Name Type Description
system System

The system, with the displacements car.y1 of the body and car.y2 of the wheel.

Examples:

>>> from skcomplex.systems.engineering.mechatronics import quarter_car
>>> quarter_car(height=0.1).elements[0].height
0.1
Source code in src/skcomplex/systems/engineering/mechatronics/_mechatronics.py
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
@register_system(
    field='engineering/mechatronics',
    tags=('mechatronics', 'suspension', 'mass spring damper', 'ode', 'second order'),
    references=('Fritzson 2015',),
    defaults={'until': 10.0, 'dt': 0.005},
    observables=lambda system: [ObservableSpec('energy', _spring_energy)],
)
def quarter_car(
    height: float = 0.05,
    *,
    at: float = 0.5,
    m1: float = 250.0,
    m2: float = 30.0,
    k: float = 16000.0,
    b: float = 1000.0,
    kt: float = 160000.0,
) -> System:
    """Return a quarter-car suspension driving over a road step.

    A body of mass `m1` rests on a spring and a damper above a wheel of mass `m2`, and a tire spring joins the wheel to
    the road, which steps to `height` at time `at`. Both displacements settle at the height of the step.

    Args:
        height:
            The height of the road step.

        at:
            The time of the road step.

        m1:
            The mass of the body.

        m2:
            The mass of the wheel.

        k:
            The stiffness of the suspension.

        b:
            The damping of the suspension.

        kt:
            The stiffness of the tire.

    Returns:
        system:
            The system, with the displacements `car.y1` of the body and `car.y2` of the wheel.

    Examples:
        >>> from skcomplex.systems.engineering.mechatronics import quarter_car
        >>> quarter_car(height=0.1).elements[0].height
        0.1
    """
    car = QuarterCarElement('car', m1=m1, m2=m2, k=k, b=b, kt=kt, height=height, at=at)
    suspension = SpringDamperInteraction(
        'suspension',
        target='car',
        states=('y1', 'y2'),
        stiffness='k',
        damping='b',
        divisor={'y1': 'm1', 'y2': 'm2'},
    )
    return System(elements=[car], interactions=[suspension])

vibrating_table(*, U=0.141, omega=1.5915, R=1.5, L=0.25, C=0.1, K=500.0, m=10.0, B=2.0, k1=0.5, k2=17.0, alpha=2.5, linear=False)

Return an electromagnetic vibrating table, a shaker driven by a sinusoidal supply after its switch closes.

The source u = U sin(omega t) feeds a resistor and a capacitor, whose voltage drives the current i2 of the coil of an electromagnet against the back electromotive force k1 v of the table. The electromagnet pulls the table, held by a spring and a damper, with the force g(i2) = k2 tan(alpha i2) / alpha, whose slope k2 at zero current is the one of Trzaska's linearized model. From rest, a transient of about 8 s dies out and the table vibrates steadily at the supply frequency, and the linearized model, g(i2) = k2 i2, gives nearly the same response since the current stays small.

Parameters:

Name Type Description Default
U float

The amplitude of the supply voltage in V.

0.141
omega float

The angular frequency of the supply in rad/s.

1.5915
R float

The resistance in Ω.

1.5
L float

The inductance of the coil in H.

0.25
C float

The capacitance in F.

0.1
K float

The stiffness of the spring in N/m.

500.0
m float

The mass of the table in kg.

10.0
B float

The damping coefficient in Ns/m.

2.0
k1 float

The electromechanical constant in Wb/m.

0.5
k2 float

The mechanical-electrical constant, the slope of the force of the electromagnet at zero current.

17.0
alpha float

The scale of the current in the characteristic of the electromagnet in 1/A.

2.5
linear bool

Whether the force of the electromagnet is its linearization k2 i2.

False

Returns:

Name Type Description
system System

The system, with the current shaker.i2, the capacitor voltage shaker.uC, the displacement shaker.x, and the velocity shaker.v.

Examples:

>>> from skcomplex.systems.engineering.mechatronics import vibrating_table
>>> vibrating_table(linear=True).elements[0].linear
True
Source code in src/skcomplex/systems/engineering/mechatronics/_vibrating_table.py
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
@register_system(
    field='engineering/mechatronics',
    tags=('mechatronics', 'electromagnet', 'vibration', 'forcing', 'ode'),
    references=('Trzaska 2023',),
    defaults={'until': 40.0, 'dt': 0.01},
)
def vibrating_table(
    *,
    U: float = 0.141,
    omega: float = 1.5915,
    R: float = 1.5,
    L: float = 0.25,
    C: float = 0.1,
    K: float = 500.0,
    m: float = 10.0,
    B: float = 2.0,
    k1: float = 0.5,
    k2: float = 17.0,
    alpha: float = 2.5,
    linear: bool = False,
) -> System:
    """Return an electromagnetic vibrating table, a shaker driven by a sinusoidal supply after its switch closes.

    The source `u = U sin(omega t)` feeds a resistor and a capacitor, whose voltage drives the current `i2` of the coil
    of an electromagnet against the back electromotive force `k1 v` of the table. The electromagnet pulls the table,
    held by a spring and a damper, with the force `g(i2) = k2 tan(alpha i2) / alpha`, whose slope `k2` at zero current
    is the one of Trzaska's linearized model. From rest, a transient of about 8 s dies out and the table vibrates
    steadily at the supply frequency, and the linearized model, `g(i2) = k2 i2`, gives nearly the same response since
    the current stays small.

    Args:
        U:
            The amplitude of the supply voltage in V.

        omega:
            The angular frequency of the supply in rad/s.

        R:
            The resistance in Ω.

        L:
            The inductance of the coil in H.

        C:
            The capacitance in F.

        K:
            The stiffness of the spring in N/m.

        m:
            The mass of the table in kg.

        B:
            The damping coefficient in Ns/m.

        k1:
            The electromechanical constant in Wb/m.

        k2:
            The mechanical-electrical constant, the slope of the force of the electromagnet at zero current.

        alpha:
            The scale of the current in the characteristic of the electromagnet in 1/A.

        linear:
            Whether the force of the electromagnet is its linearization `k2 i2`.

    Returns:
        system:
            The system, with the current `shaker.i2`, the capacitor voltage `shaker.uC`, the displacement `shaker.x`,
            and the velocity `shaker.v`.

    Examples:
        >>> from skcomplex.systems.engineering.mechatronics import vibrating_table
        >>> vibrating_table(linear=True).elements[0].linear
        True
    """
    shaker = VibratingTableElement(
        'shaker',
        U=U,
        omega=omega,
        R=R,
        L=L,
        C=C,
        K=K,
        m=m,
        B=B,
        k1=k1,
        k2=k2,
        alpha=alpha,
        linear=linear,
    )
    return System(elements=[shaker])