Position Loop — P (Baseline)

Field Value
Title Position Loop — P (Baseline)
Type theory
Status draft
Version 1.0.0
Component position-loop-pid
Date 2026-08-31

Theory document: Explains the mathematical and engineering principles behind a component or algorithm. This document is descriptive — it records the why and how at a scientific level, independent of any specific implementation. Equations use KaTeX (\(inline\) and \[block\]). Block diagrams use Mermaid or ASCII art.


Overview

The baseline position controller converts position error into a speed reference \(\omega_m^*\) for the inner speed loop. Under cascade separation — inner speed loop bandwidth at least 5× the position bandwidth — the closed-loop position bandwidth equals \(K_p\) directly. No parameter identification is required.

The law is a PI, not the pure P this chapter derives. The derivation below is the P design the cascade shipped with and still the way to read the proportional path; the integral term removes the standing error the P design leaves under a constant velocity reference. Its zero and the weight the proportional term gives the reference are fixed by the design in Integral zero and reference weighting below, not by the loop tunings.

Operates exclusively in the 1 kHz outer handler.


Prerequisites

Symbol Meaning Unit
\(\omega_{bw}^p\) Desired closed-loop position bandwidth rad/s
\(\omega_{bw}^s\) Inner speed-loop closed-loop bandwidth rad/s
\(\omega_{m,max}\) Maximum mechanical angular velocity (hardware limit) rad/s
\(T_s^o\) Outer loop sample period (\(= 1\) ms) s

See documentation/theory/foc-plant-models.md §3 for the position plant derivation.


Mathematical Foundation

Plant Model

Under cascade separation (treating the speed loop as ideal, \(\omega_m \approx \omega_m^*\)), the position dynamics reduce to a pure integrator:

\[ \frac{d\theta_m}{dt} = \omega_m \]

Transfer function from \(\omega_m^*\) to \(\theta_m\):

\[ G_\theta(s) = \frac{1}{s} \]

P Controller Design

A proportional controller \(C(s) = K_p\) closes the integrator loop. This is the proportional path of the implemented PI; see the note in the Overview:

\[ \boxed{\omega_m^*[k] = K_p \cdot \mathrm{wrap}\bigl(\theta_m^*[k] - \theta_m[k]\bigr)} \]

The closed-loop transfer function is:

\[ \frac{\Theta_m(s)}{\Theta_m^*(s)} = \frac{K_p}{s + K_p} \]

The position bandwidth equals the proportional gain directly:

\[ \omega_{bw}^p = K_p \]

Bandwidth selection: Cascade separation requires:

\[ K_p = \omega_{bw}^p \leq \frac{\omega_{bw}^s}{5} \]

Exceeding this limit causes the position loop to drive the speed loop into instability.

Angle-Error Wrapping

Position error must be wrapped to \((-\pi, \pi]\) to ensure the shortest arc is always taken:

\[ e_\theta[k] = \mathrm{wrap}\bigl(\theta_m^*[k] - \theta_m[k]\bigr) \]

\[ \mathrm{wrap}(x) = x - 2\pi\, \mathrm{round}\!\left(\frac{x}{2\pi}\right) \]

Without wrapping, a \(+3.1\) rad reference reached from \(-3.1\) rad would command a \(6.2\) rad (354°) rotation through the long arc instead of the \(0.08\) rad short arc.

Integral zero and reference weighting

The integral zero sits at a fifth of the position bandwidth, \(K_i = 0.2\,\omega_{bw}^p K_p\), and the proportional term acts on \(b\,\theta^* - \theta\) with \(b = 0.75\) rather than on the error:

\[ \omega_m^*[k] = \omega_m^*[k-1] + K_p\left(b\,\Delta\theta^*[k] - \Delta\theta_m[k]\right) + K_i T_s^o\, e_\theta[k] \]

in the velocity form the implementation uses, with every difference wrapped as the error is.

The zero used to sit at the integral weight times the bandwidth, a twentieth of it with the default weight. That places a slow closed-loop pole just beside the zero, and the pair leaves a tail whose size is the residue of that pole: under an ideal speed loop at \(\omega_{bw}^p = 18.85\) rad/s the poles fall at \(-0.995\) and \(-17.9\) rad/s against a zero at \(-0.94\), and a 1.5 rad step keeps some 0.089 rad of overshoot that decays over a second — 0.055 rad is still there half a second later. A torque step pushing the same way as that tail starts its excursion already most of the way across a 0.08 rad recovery band.

Moving the zero up to \(\omega_{bw}^p/5\) alone shortens the tail but makes it larger, because the zero also lies in the reference path. Weighting the reference in the proportional term takes the zero out of the reference path without touching disturbance rejection, which sees the full \(K_p\) through \(\Delta\theta_m\). With \(b = 0.75\) a 1.5 rad step overshoots by well under 1 % and is within 0.01 rad of the setpoint 450 ms after the step.

Output Limiting

The speed reference is clamped to \(\pm\omega_{m,max}\) to prevent demanding speeds beyond the mechanical or electrical limits of the drive:

\[ \omega_m^*[k] = \mathrm{clamp}\bigl(K_p \cdot e_\theta[k],\ -\omega_{m,max},\ \omega_{m,max}\bigr) \]


Numerical Properties

Property Value
Ops per 1 kHz cycle 2 MACs (1 multiply + wrap + clamp)
Steady-state position error Non-zero under constant velocity reference for the P design; removed by the integral term
Steady-state error at rest Zero (no steady velocity → no position error)
Requires J, Bf No
Tuning knobs 1 (\(K_p = \omega_{bw}^p\)); the integral zero and reference weight are design constants

Limitations & Assumptions


References

  1. Krishnan, R. — Permanent Magnet Synchronous and Brushless DC Motor Drives, CRC Press, 2010.
  2. Åström, K.J. & Wittenmark, B. — Computer-Controlled Systems, 3rd ed., Prentice Hall, 1997.