neclib.controllers.antenna_pid#

PID controller for telescope main dish.

Optimum control parameter is calculated using a simple function consists of Proportional, Integral and Derivative terms:

\[u(t) = K_\mathrm{p} \, e(t) + K_\mathrm{i} \int e(\tau) \, \mathrm{d}\tau + K_\mathrm{d} \frac{ \mathrm{d}e(t) }{ \mathrm{d}t }\]

where \(K_\mathrm{p}, K_\mathrm{i}\) and \(K_\mathrm{d}\) are non-negative constants, \(u(t)\) is the controller’s objective parameter, and \(e(t)\) is the error between desired and actual values of explanatory parameter.

Note

This script will be executed in high frequency with no vectorization, and there are many arrays updated frequently. These mean that the use of Numpy may not be the best choice to speed up the calculation. Measure the execution time first, then implement.

Aliases#

LinearExtrapolate

Extrapolate Python objects.

ParameterList

List, specialized in parameter storing.

class PIDController(*, pid_param=(1.0, 0.5, 0.3), max_speed=<Quantity 1.6 deg / s>, max_acceleration=<Quantity 1.6 deg / s2>, error_integ_count=50, threshold={'accel_limit_off': <Quantity 20. arcsec>, 'cmd_coord_change': <Quantity 400. arcsec>, 'target_accel_ignore': <Quantity 2. deg / s2>})[source]#

Bases: object

PID controller for telescope antenna.

PID controller, a classical but sophisticated controller for system which has some delay on response to some input. This controller handles only 1 device, so use 2 instances for Az-El control of telescope antenna.

Parameters:
  • pid_param (Tuple[float, float, float]) – Coefficients for PID formulation, list of [K_p, K_i, K_d].

  • max_speed (Union[str, Quantity]) – Maximum speed for telescope motion.

  • max_acceleration (Union[str, Quantity]) – Maximum acceleration for telescope motion.

  • error_integ_count (int) – Number of error data to be stored for integral term calculation.

  • threshold (Dict[Literal['cmd_coord_change', 'accel_limit_off', 'target_accel_ignore'], ~typing.Union[str, ~astropy.units.quantity.Quantity]]) –

    Thresholds for conditional executions. Interpreted keys are:

    • cmd_coord_change (angle)

      If separation between new command coordinate and last one is larger than this value, this controller assumes the target coordinate has been changed and resets the error integration.

    • accel_limit_off (angle)

      If separation between encoder reading and command coordinate is smaller than this value, this controller stops applying acceleration limit for quick convergence of drive.

    • target_accel_ignore (angular acceleration)

      If acceleration of target coordinate exceeds this value, the target_speed term is ignored as such commands most likely caused by software bug or network congestion.

Variables:
  • k_p (float) – Proportional term coefficient.

  • k_i (float) – Integral term coefficient.

  • k_d (float) – Derivative term coefficient.

  • k_c (float) – Constant term coefficient.

  • max_speed (float) – Upper limit of drive speed in [ANGLE_UNIT / s].

  • max_acceleration (float) – Upper limit of drive acceleration in [ANGLE_UNIT / s^2].

  • error_integ_count (int) – Number of data stored for error integration.

  • threshold (Dict[str, u.Quantity]) – Thresholds for conditional controls.

  • cmd_speed (ParameterList[float]) – List of last 2 PID calculation results in unit [ANGLE_UNIT / s].

  • time (ParameterList[float]) – List of last error_integ_count UNIX timestamps the calculations are done.

  • cmd_coord (ParameterList[float]) – List of last 2 command coordinates in [ANGLE_UNIT].

  • enc_coord (ParameterList[float]) – List of last 2 encoder readings in [ANGLE_UNIT].

  • error (ParameterList[float]) – List of last error_integ_count deviation values between cmd_coord and enc_coord.

  • target_speed (ParameterList[float]) – List of last 2 rate of change of command coordinates in [ANGLE_UNIT / s].

Notes

This controller adds constant term to the general PID formulation. This is an attempt to follow constant motions such as raster scanning and sidereal motion tracking.

speed = (K_c * target_speed)
    + (k_p * error)
    + (k_i * error_integral)
    + (k_d * error_derivative)

This class keeps last 50 error values (by default) for integral term. This causes optimal PID parameters to change according to PID calculation frequency, as the time interval of the integration depends on the frequency.

Tip

All methods assume the argument is given in ANGLE_UNIT, and return the results in that unit. If you need to change it, substitute ANGLE_UNIT before instantiating this class.

Examples

>>> neclib.controllers.PIDController.ANGLE_UNIT
deg
>>> controller = neclib.controllers.PIDController(
...     pid_param=[1.5, 0, 0],
...     max_speed="1000 arcsec/s",
...     max_acceleration="1.6 deg/s",
... )
>>> target_coordinate, encoder_reading = 30, 10  # deg
>>> controller.get_speed(target_coordinate, encoder_reading)
1.430511474609375e-05  # deg/s
>>> controller.get_speed(target_coordinate, encoder_reading)
0.20356178283691406  # deg/s
ANGLE_UNIT: ClassVar[Literal['deg', 'rad', 'arcmin', 'arcsec']] = 'deg'#

Unit in which all public functions accept as its argument and return.

property dt: float#

Time interval of last 2 PID calculations.

property error_integral: float#

Integral of error.

property error_derivative: float#

Derivative of error.

get_speed(cmd_coord, enc_coord, stop=False, *, cmd_time=None, enc_time=None)[source]#

Modulated drive speed.

Parameters:
  • cmd_coord (float) – Instructed Az/El coordinate.

  • enc_coord (float) – Az/El encoder reading.

  • stop (bool) – If True, the telescope won’t move regardless of the inputs.

  • cmd_time (Optional[float]) –

  • enc_time (Optional[float]) –

Return type:

float

params(**kwargs)[source]#
Return type:

Generator[None, None, None]