• linear algebra
    • matrices/vectors (what they are, the information they encode, common operations between them)
    • passive transformations (i.e. mapping b/w spaces)
    • active transformations (i.e. moving in current space)
  • calculus
    • integrals (what they are, how to easily compute them)
    • derivatives (what they are, how to easily compute them)
  • statistics
    • normal random variables (what they are, variation, standard deviation)
  • control theory
    • PID controllers (what they are, how to implement them, how to tune them)

Recently I was curious about how rockets steer themselves.

Stochastic Systems and PID Controllers

The actuators and sensors of a rocket, like all devices, are not perfect. Thus when it wants to thrust at a certain angle, it won’t hit that angle exact. It will be a normally distributed random variable centered at that angle

It is not just the thrust that is subject to this inaccuracy. All actuators and sensors of the rocket are. Thus a rocket is a stochastic system, not a deterministic one.

Control theory is a field of engineering that deals with handling stochastic systems like this. More specifically it deals with guiding the actuators to constantly steer a sensor value to some target value, and then to keep it there (as best you can).

For example, you want the robot to be at position x, so you use the actuators (motors) to move it to x. But since this is a stochastic system, you may not have arrived exactly at x. So you use the actuators to try to move him to x again.

In a strictly mathematical sense, your variable always has a delta from its target. In other words, the variables current value is different from the value you’d like it to be. This difference tells you in what direction the variable needs to move in.

But you can do one better. In addition to knowing the delta between the target value and current value, you know the direction/magnitude the variable is currently moving towards, i.e. you know its derivative. This info is useful, b/c for example, the higher the derivative heading in the wrong direction, the stronger you’d want the correction signal to be.

Also, actuators often don’t take the variable exactly to the target value, there is usually a constant error remaining. By taking into account this constant error, i.e. by seeing how big the integral of the error is, you can periodically give commands to steer the variable’s value closer to the target value.

A controller that takes into account the error, its derivative and its integral, and uses this information to proportionally control actuators, is called a PID controller.

A PID controller, given the error, derivative of the error, and integral of the error, will tell you the magnitude/direction of the commmand to apply to the actuator in order to reduce the error. The output scales linearly wrt all 3 of these variables (error, derivative of the error, and integral of the error). Very simple.

Basic PID Controller Implementation

Here is a basic implementation of a PID controller in python.

import math

class PIDController:
    """A basic PID controller. Naive implemenation of integral/derivative."""

    def __init__(self, p_constant, i_constant, d_constant) -> None:
        self.p_constant = p_constant
        self.i_constant = i_constant
        self.d_constant = d_constant
        self._integral = 0
        self._last_error = 0

    def update(self, error, dt) -> float:
        self._integral += error * dt
        derivative = (error - self._last_error) / dt
        self._last_error = error
        value = self.p_constant * error + self.i_constant * self._integral + self.d_constant * derivative

        return value

Here is example usage of it.

controller = PIDController(0.1,0.1,0.1)
plant = YourPlant() # w.e. your "plant" is (rocket, robot, etc)

while True:
    # dt = delta time, time since plant/controller were last updated
    error = plant.update(dt)
    command = controller.update(error,dt)

Of course, the integral and derivative implementation in the above PID controller is minimal, use more complex implementations as needed, but always start with the simplest thing that works for what you are trying to achieve.

The Rocket

I built a basic virtual rocket to test/practice my control theory learnings.

I used python as the programming langauge. I used the pymunk physics engine to simulate gravity and to allow me to attach impulses to bodies. Pymunk is a pythonic wrapper around the chipmunk2d physics engine. I used pyglet for rendering and basic event handling. Pyglet is a light weight, low dependency (only depends on python) wrapper around OpenGL. I used numpy to sample normally distributed random variables. I used my own PID controller.

With no Controller

These videos show how the rocket behaves with no controller. It just spazzes lol.

Here is the no-controller rocket being launched vertically.

Here is the no-controller rocket being launched at an angle.

With Controller

These videos show how the rocket behaves with a (PID) controller.

Here is the controlled rocket being launched vertically.

Here is the controlled rocket being launched at an angle.

Steering During Flight

The controlled rocket has pretty good control, so I wondered if I could make it steer during flight.

So I decided to make it constantly head towards the position of the mouse.

Here is a video showing the result.