UBCSailbot / sailbot_workspace

UBC Sailbot's monorepo
https://ubcsailbot.github.io/sailbot_workspace/main/
Apache License 2.0
4 stars 1 forks source link

Implement controllers for rudder and sail actuation mechanisms #306

Closed DFriend01 closed 5 months ago

DFriend01 commented 7 months ago

Purpose

There are high-level controllers that give us high-level information on what we want to do. For example, the wingsail controller computes the trim tab angle that we want to have in order to achieve maximum thrust. However, what is the mechanism that actually turns the trim tab from position $a$ to $b$? That is the goal of the low-level control node.

In particular, this issue focuses on implementing the backbone logic of the low-level control node -- the logic that actually turns the rudder and trim tab. In reality, this is handled by ELEC in the real system, but we need a way to simulate this in our boat simulator.

Description

Controller Behavior

The first thing we need to consider is what behavior we should be observing as we step through time. Recall that the simulator operates iteratively in timesteps, so the controller should be designed with this in mind. For example, suppose we want to turn the rudder from $5\degree$ to $20\degree$. A naive implementation would immediately set the rudder angle to $20\degree$ after one timestep. The timestep we use is 0.5 seconds, so that would correspond to turning the rudder 15 degrees in 0.5 seconds (that is fast!). What we really want is a gradual adjustment over time -- something like the following:

$$5\degree \to 7.5\degree \to 10\degree \to \dots \to 20\degree$$

Software Design

The software design should utilize OOP principles that allow the implementation to generalize to both the rudder and sail actuators. The idea is that if somebody wanted to implement their own controller, there should be little to no changes in the public interface that is exposed. A few things to consider are:

Concrete Implementations

There are two concrete implementations that we want out of this issue:

  1. The rudder actuator
  2. The sail actuator

For the rudder controller, we decided to go with Raye's implementation since there were issues with the PID controller, but in the future we will likely want to use PID instead to reflect the real system. The new rudder angle is given as follows (note that it's in radians):

$$\phi_{\text{target}} = \dfrac{k_p}{1 + c_p \left|e[t]\right|} \cdot e[t]$$

$$e[t] = \text{atan2}\left(\sin\left(\text{DesiredHeading}[t] - \text{CurrentHeading}[t]\right), \cos\left(\text{DesiredHeading}[t] - \text{CurrentHeading}[t]\right)\right)$$

For your reference, Raye used $k_p = 0.7$ and $c_p = 0.34$, but feel free to adjust when necessary. You can assume that the desired heading and current heading are supplied when beginning a new actuation.

For the sail controller, you can assume that the target trim tab angle is supplied directly when beginning a new actuation (no need to compute it as the rudder controller does -- the high-level sail controller does that work for you).

Your implementation should be inside the directory boat_simulator/nodes/low_level_control.