Servo Motion Control: Trajectories & Cascaded Loops

Making axes move precisely and smoothly. Learn motion profiles (trapezoidal, S-curve, jerk limits), cascaded current–velocity–position loops and why each is faster than the next, tuning procedures, feedforward (velocity, acceleration, friction), following error, multi-axis coordination (interpolation, electronic gearing and camming), resonance and notch filters, and motion controllers and networks — with Python for profiles and a cascaded-loop simulation.

A servo axis must follow a commanded trajectory with minimal error, settle quickly without overshoot, and reject disturbances — while respecting motor torque, speed and current limits. Industrial servo drives achieve this with a trajectory generator and three nested control loops.

Good trajectories are as important as good tuning: an abrupt command excites resonances and saturates the motor, while a smooth, jerk-limited profile gets there faster in practice.

An analogy

Cascaded loops are like a company hierarchy: the position loop (manager) sets targets for the velocity loop (supervisor), which sets targets for the current loop (worker). The worker must react fastest, the supervisor faster than the manager, or orders pile up and the system oscillates.

Trajectory generation

The motion controller converts 'go to X' into a time-parameterised reference of position, velocity and acceleration respecting limits. Trapezoidal velocity profiles (constant acceleration) are simple; S-curves add jerk limits for smoothness; polynomial (e.g. quintic) and spline trajectories give continuous derivatives for robots and CNC paths.

Cascaded control loops

The standard servo architecture:

Feedforward and following error

Feedback reacts to errors; feedforward anticipates them. Velocity feedforward removes the steady following error during constant-speed moves; acceleration (inertia) feedforward supplies the torque for acceleration; friction feedforward compensates Coulomb friction. With accurate feedforward the feedback loops only correct small residuals, allowing lower gains and better robustness.

Multi-axis coordination and resonance

Coordinated motion interpolates multiple axes along lines, arcs and splines (G-code, robot paths); electronic gearing and camming lock slave axes to a master (packaging, printing). Mechanical resonances are handled by notch and low-pass filters, input shaping and higher stiffness. Motion networks (EtherCAT, PROFINET IRT, SERCOS) synchronise axes to microseconds; standards like PLCopen Motion Control provide function blocks (MC_MoveAbsolute, MC_GearIn).

Formulas

Worked example: Triangle profile

Given: D = 20 mm, a_max = 2 m/s², v_max = 0.5 m/s

Find: Profile type and time.

Answer: Triangle, peak 0.2 m/s, total 0.2 s

Worked example: Following error

Given: K_p = 50 1/s, v = 100 mm/s, no feedforward

Find: e_ss.

Answer: 2 mm lag — velocity feedforward removes it

Worked example: Acceleration feedforward

Given: J = 2e-4 kg·m², α = 500 rad/s², K_t = 0.05

Find: i_ff.

Answer: 2 A

Trapezoidal and S-curve profiles

# Trapezoidal and S-curve motion profiles for a 200 mm move
D, vmax, amax = 0.200, 0.5, 2.0
t_a = vmax / amax
d_a = 0.5 * amax * t_a**2
if 2 * d_a > D:
    t_a = (D / amax) ** 0.5; vmax = amax * t_a; t_c = 0.0
else:
    t_c = (D - 2 * d_a) / vmax
T = 2 * t_a + t_c
print(f"trapezoid: accel {t_a:.3f} s, cruise {t_c:.3f} s, total {T:.3f} s, peak v {vmax:.2f} m/s")
# Same move, S-curve with jerk limit 20 m/s^3 (jerk phases add time)
jmax = 20.0
t_j = amax / jmax
T_s = T + t_j
print(f"S-curve (jerk {jmax} m/s^3): jerk time {t_j:.3f} s -> total ~{T_s:.3f} s, smoother (less vibration)")
# trapezoid: accel 0.250 s, cruise 0.150 s, total 0.650 s, peak v 0.50 m/s
# S-curve (jerk 20.0 m/s^3): jerk time 0.100 s -> total ~0.750 s, smoother (less vibration)

The S-curve takes slightly longer on paper, but because it doesn't excite machine resonances the axis often settles sooner and more accurately in reality — pick-and-place machines use jerk-limited profiles for exactly this reason.

Cascaded position–velocity control

# Cascaded position (P) and velocity (PI) loops on a motor+load (current loop assumed ideal)
J, b, Kt = 2e-4, 1e-4, 0.05
dt = 1e-4
Kp_pos = 20.0                                     # 1/s  (outer loop ~5x slower than inner)
Kp_v, Ki_v = 0.4, 8.0                             # A per rad/s, A per rad (inner bandwidth ~100 rad/s)
theta = w = integ = 0.0
target = 1.0                                      # rad
peak, settle = 0.0, None
hist = []
for n in range(int(0.6 / dt)):
    w_ref = Kp_pos * (target - theta)
    e_v = w_ref - w
    integ += e_v * dt
    i_cmd = max(-5, min(5, Kp_v * e_v + Ki_v * integ))
    T = Kt * i_cmd
    w += dt * (T - b * w) / J
    theta += dt * w
    peak = max(peak, theta); hist.append(theta)
for n in range(len(hist) - 1, -1, -1):
    if abs(hist[n] - target) > 0.02:
        settle = (n + 1) * dt; break
print(f"final {theta:.4f} rad, overshoot {max(0.0, (peak-target)*100):.1f}%, 2% settling {settle*1000:.0f} ms")
# final 0.9999 rad, overshoot 0.0%, 2% settling 208 ms

With the velocity loop (≈ 100 rad/s) about five times faster than the position loop (20 1/s), the axis reaches 1 rad with no overshoot in ~0.2 s. An earlier tuning with the position loop faster than the velocity loop went unstable — a direct demonstration of the cascade rule.

Common mistakes

Applications

Key takeaways

Going further