Problem 572298 · easy · Level 05 Advanced Algorithms & Graphs

What a Gimbal's Pole Says About Its Swing

poles · settling time · overshoot · oscillation period · complex numbers

A camera gimbal on a drone turns the camera to a new heading. Its control loop runs every dt seconds, and its slowest (dominant) pole is at z = re + im*j. You do not need to simulate anything: the pole's polar form z = r * (cos θ + j sin θ) already says how the camera will move.

  • Radius r = |z|: decay. After k samples the pole's part of the response has shrunk to r ** k of its start. The usual settling rule waits until it is down to 2 %: r ** k = 0.02, so k = ln(0.02) / ln(r) samples, and the settling time is k * dt seconds. Keep k as a real number (do not round it).
  • Angle θ = |angle of z| (in radians, between 0 and π): oscillation. Each sample turns the pole by θ, so one full swing takes 2π / θ samples, a period of 2π / θ * dt seconds. A pole on the positive real axis (θ = 0) does not oscillate at all: its period is None.
  • Overshoot. The first overshoot comes half a swing after the start, π / θ samples, by which time the swing has shrunk to r ** (π / θ). So the overshoot is about 100 * r ** (π / θ) per cent of the step. With θ = 0 there is no overshoot: 0.0.

(These are exact for a loop whose step response is set by one pair of poles, and good estimates when one pair dominates.) cmath.polar(complex(re, im)) gives (r, angle); math.atan2(im, re) gives the angle too.

Write read_pole(re, im, dt) that returns (settling_time, period, overshoot_percent).

Examples

Input:  re = 0.8, im = 0.3, dt = 0.01
Output: (0.24861070488208192, 0.1751309632540762, 25.2109970130379)
Explanation: r = 0.8544 and θ = 0.3588 rad. Settling takes ln(0.02) / ln(0.8544) = 24.86 samples,
0.2486 s; one swing takes 2π / 0.3588 = 17.51 samples, 0.1751 s; the overshoot is
0.8544 ** 8.757 = 0.252, about 25 %.

Input:  re = 0.8, im = 0, dt = 0.5
Output: (8.765709298763475, None, 0.0)
Explanation: a real pole: 0.8 ** 17.53 = 0.02, so 17.53 samples of 0.5 s. No swing, no overshoot.

Constraints

  • 0 < |z| < 1 (the loop is stable); dt > 0
  • answers are compared with a tolerance of 1e-6; a list is accepted in place of the tuple

Goals

  • Read a pole's radius as a rate of decay and turn it into a settling time
  • Read a pole's angle as an oscillation and turn it into a period
  • Estimate the overshoot from how much the swing decays in half a period
Starting Python…