Feedback Control for a simple pendulum
In this article, I discuss feedback control strategies for a simple pendulum system. A pendulum consists of a mass attached to a massless rigid rod, constrained to move along an arc. With friction and external torque applied at the pivot point, the system exhibits non-linear dynamics. I derived the equations of motion using Newton’s second law, accounting for gravitational forces, friction, and external torque.
The equation governing the pendulum’s motion is:
\ddot \theta = -\frac{g}{L}\sin(\theta) - \frac{d}{m}\dot \theta + u = -\omega^2 \sin(\theta) - \gamma \dot \theta + u
where \omega = \sqrt{\frac{g}{L}} is the natural frequency and \gamma = \frac{d}{m}.
This leads to the state-space representation:
\frac{\mathrm d}{\mathrm dt} \begin{bmatrix} x_1 \\\\ x_2 \end{bmatrix} = \begin{bmatrix} x_2 \\\\ -\omega^2 \sin(x_1) - \gamma x_2 - u \end{bmatrix}
Since this is a non-linear system, I linearized the dynamics around the equilibrium points for easier control design. Near the pendulum’s downward position, the linearized system is represented by:
\frac{\mathrm d}{\mathrm dt} \begin{bmatrix} x_1 \\\\ x_2 \end{bmatrix} = \begin{bmatrix} 0 & 1 \\\\ -\omega^2 & -\gamma \end{bmatrix}
The characteristic polynomial of this system is \lambda^2 + \gamma\lambda + \omega^2 = 0, showing oscillatory behavior for undamped systems.
Neural network optimization for control
To stabilize the pendulum, I used feedback control with the control law u = -\mathbf{K\,x}, which modulates the system’s behavior through state feedback. The challenge lies in selecting the optimal feedback gain \mathbf K. To solve this, I implemented a neural network trained using a genetic algorithm.
The neural network takes as input the pendulum’s angular position, velocity, and acceleration, and predicts the control action based on the current state. Below is a code snippet illustrating how I integrated the neural network into the control loop:
// compute the motion for 10 seconds
const size_t simSteps = static_cast<size_t>(T_C(10) / deltaTime);
tp::thread_pool pool;
for (size_t i = 0; i < pSize; ++i)
{
auto floop = [this, &fitness = fitness[i], idx = i, &theta0_, &thetaDot0_, &thetaDDot0_, &simSteps]() {
std::array<T, 2> y1_, y2_;
math::ode::Params<T> params_copy = params;
std::vector<T> inputs(nn::NNParams().inputs), nn_out(2);
T t_ = T_C(0.0), theta_ = theta0_, thetaDot_ = thetaDot0_, thetaDDot_ = thetaDDot0_;
for (size_t j = 0; j < simSteps; ++j)
{
inputs[0] = theta_ / T_C(2.0 * T_PI);
inputs[1] = thetaDot_ / T_C(2.0 * T_PI);
inputs[2] = thetaDDot_ / T_C(2.0 * T_PI);
mNN->feedforward(inputs, nn_out, idx, false);
params_copy.u = -KGainNN * (nn_out[0] * (theta_ - control::Params<T>().y_ref[0]) +
nn_out[1] * (thetaDot_ - control::Params<T>().y_ref[1]));
y1_ = {theta_, thetaDot_};
ma::rk4singlestep(ge::motionFun, deltaTime, t_, y1_, y2_, params_copy);
theta_ = y2_[0];
thetaDot_ = y2_[1];
ge::motionFun(time, y2_, y1_, params_copy);
thetaDDot_ = y1_[1];
fitness += std::abs(theta_ - control::Params<T>().y_ref[0]);
fitness += std::abs(thetaDot_ - control::Params<T>().y_ref[1]);
t_ += deltaTime;
}
fitness /= T_C(simSteps);
};
}
The neural network, trained using a genetic algorithm, evolves over generations, with each network evaluated on how well it minimizes the error between the pendulum’s current state and the desired reference point. The genetic algorithm selects top performers, updates weights and biases, and generates a new population for further optimization.
Conclusion
In conclusion, I demonstrated the implementation of feedback control for a pendulum system using both classical control theory and neural network optimization. This hybrid approach provides an effective means of stabilizing the pendulum and minimizing deviation from equilibrium points. For more insights into this topic, you can find the details here.
The code for this implementation is available on Github here.