MockControlClosedLoop

class lsst.ts.m2com.MockControlClosedLoop(is_mirror: bool = False)

Bases: object

Mock closed-loop control.

Parameters

is_mirrorbool, optional

Is mirror or not. If not, the surrogate is applied. (the default is False)

Attributes

is_runningbool

The closed-loop control is running or not.

temperaturedict

Temperature of mirror in degree C.

axial_forcesdict

Forces of the axial actuators in Newton.

tangent_forcesdict

Forces of the tangent actuators in Newton.

hardpointslist

List of the hardpoints. There are 6 actuators. The first three are the axial actuators and the latter three are the tangent links.

disp_hardpoint_homelist

Displacement of the hardpoints at the home position. The unit is meter.

control_loopMockControlLoop

Mock control loop with the force control algorithm.

Methods Summary

apply_forces(force_axial, force_tangent)

Apply the actuator forces.

calc_cmd_delay_filter_params([is_mirror, ...])

Calculate the command delay filter parameters (or more clearly, the numerator of the transfer function).

calc_cmd_prefilter_params([numerator, ...])

Calculate the command pre-filter parameters in biquadratic filters.

calc_force_control_filter_params([...])

Calculate the force control filter parameters in biquadratic filters.

calc_hp_comp_matrix(location_axial_actuator, ...)

Calculate the hardpoint compensation matrix.

calc_kinetic_decoupling_matrix(...)

Calculate the kinetic decoupling matrix.

calc_look_up_forces([lut_angle, ...])

Calculate look-up table (LUT) forces using current system state (position and temperature).

calc_temp_inv_matrix()

Calculate the temperature inversion matrix.

calculate_rigid_body_xy(radius, ...)

Calculate the rigid body (x, y) position.

get_active_actuators(hardpoints_axial, ...)

Get the active actuators.

get_actuator_location_axial()

Get the location of axial actuators.

get_actuator_location_tangent()

Get the location of tangent actuators.

get_demanded_force([applied_force_axial, ...])

Get the demanded force in Newton.

get_force_balance()

Get the data of force balance system.

get_net_forces_total()

Get the total net forces in Newton.

get_net_moments_total()

Get the total net moments in Newton * meter.

get_radius()

Get the radius of the tangential actuators.

handle_forces(is_in_position[, plant, ...])

Handle forces and update the hardpoint correction and measured forces.

hardpoint_to_rigid_body(...)

Calculate the rigid body position based on the hardpoint displacements.

is_actuator_force_out_limit([...])

The actuator force is out of limit or not.

is_cell_temperature_high()

Cell temperature is high or not.

load_file_cell_geometry(filepath)

Load the file of cell geometry.

load_file_lut(filepath)

Load the look-up table (LUT) files.

load_file_stiffness(filepath)

Load the file of stiffness matrix.

reset_force_offsets()

Reset the force offsets.

rigid_body_to_actuator_displacement(...)

Calculate the actuator displacements based on the rigid body position.

set_hardpoint_compensation()

Set the hardpoint compensation matrix.

set_kinetic_decoupling_matrix()

Set the kinetic decoupling matrix.

set_measured_forces(force_axial, force_tangent)

Set the measured actuator forces.

simulate_temperature_and_update([...])

Simulate the temperature change and update the internal value.

transfer_function_to_biquadratic_filter(...)

Transfer function to the biquadratic filters.

update_hardpoints(hardpoints)

Update the hardpoints and related internal parameters.

Methods Documentation

apply_forces(force_axial: list[float] | ndarray[Any, dtype[float64]], force_tangent: list[float] | ndarray[Any, dtype[float64]]) None

Apply the actuator forces.

Parameters

force_axiallist or numpy.ndarray

Force of the axial actuators in Newton.

force_tangentlist or numpy.ndarray

Force of the tangent actuators in Newton.

Raises

RuntimeError

When the maximum force limits reached.

static calc_cmd_delay_filter_params(is_mirror: bool = True, control_frequency: float = 20.0, bypass_delay: bool = False, num_degree: int = 5) list[float]

Calculate the command delay filter parameters (or more clearly, the numerator of the transfer function).

Notes

Translate the calculation from the Create_Filter_Params.m in ts_mtm2_matlab_tools.

For a transfer function, H(z), if the numerator is [1, 3, 3] and the denominator is [1, 2, 1], it will be:

H(z) = (z^2 + 3 * z + 3) / (z^2 + 2 * z + 1)

Since the denominator of transfer function is the demanded force change here, the linear transfer ([1.0]) is applied. Therefore, we only care about the delay of command as the output.

Parameters

is_mirrorbool, optional

Is mirror or not. If not, the surrogate is applied. (the default is True)

control_frequencyfloat, optional

Frequency of the control loop in Hz. (the default is 20.0)

bypass_delaybool, optional

Bypass the command delay or not. (the default is False)

num_degreeint, optional

Number of the degree in the transfer function. (the default is 5)

Returns

numerator_transfer_functionlist

Numerator of the transfer function from the high degree to low degree.

static calc_cmd_prefilter_params(numerator: list[float] | None = None, denominator: list[float] | None = None) tuple[float, numpy.ndarray[Any, numpy.dtype[numpy.float64]]]

Calculate the command pre-filter parameters in biquadratic filters.

Notes

Translate the calculation from the Create_Filter_Params.m in ts_mtm2_matlab_tools.

Currently, pre-filter is a pass-through filter.

Parameters

numeratorlist or None, optional

Numerator polynomial coefficients of the transfer function. If None, the linear transfer is assumed (aka. [1.0]). (the default is None)

denominatorlist or None, optional

Denominator polynomial coefficients of the transfer function. If None, the linear transfer is assumed (aka. [1.0]). (the default is None)

Returns

float

Gain.

list

Coefficients of the command pre-filter parameters.

static calc_force_control_filter_params(is_mirror: bool = True, numerator: list[float] | None = None, denominator: list[float] | None = None) tuple[float, numpy.ndarray[Any, numpy.dtype[numpy.float64]]]

Calculate the force control filter parameters in biquadratic filters.

Notes

Translate the calculation from the Create_Filter_Params.m in ts_mtm2_matlab_tools.

Parameters

is_mirrorbool, optional

Is mirror or not. If not, the surrogate is applied. (the default is True)

numeratorlist or None, optional

Numerator polynomial coefficients of the transfer function. If None, the linear transfer is assumed (aka. [1.0]). (the default is None)

denominatorlist or None, optional

Denominator polynomial coefficients of the transfer function. If None, the linear transfer is assumed (aka. [1.0]). (the default is None)

Returns

float

Gain.

coefficientslist

Coefficients of the force control filter parameters.

static calc_hp_comp_matrix(location_axial_actuator: list[list], hardpoints_axial: list[int], hardpoints_tangent: list[int]) tuple[numpy.ndarray[Any, numpy.dtype[numpy.float64]], numpy.ndarray[Any, numpy.dtype[numpy.float64]]]

Calculate the hardpoint compensation matrix.

Notes

<Axial actuators>

Translate the calculation from the CalcHPFCInfMat.m in ts_mtm2_matlab_tools.

The axial hardpoint compensation matrix (M) fulfills:

M * (x_hp, y_hp, 1) = (x_nhp, y_nhp, 1)

x_hp: x-position of hardpoint y_hp: y-position of hardpoint x_nhp: x-position of non-hardpoint y_nhp: y-position of non-hardpoint

The idea is to make the x-moment amd y-moment keep the same when distributes the force of axial hardpoints to other axial actuators. It is the same idea for tangential actuators with z-moment.

<Tangent links>

Assume the hardpoints are A1, A3, and A5. If they were active, the z-moment would be: 3 * fm * mirror_radius, where fm = (f1 + f3 + f5) / 3.

For the active tagent links: A2, A4, and A5 to maintain this z-moment while keeping the hardpoints to be passive, we have:

f2 = -(f5 - fm) + fm = 2 * fm - f5 = 2 / 3 * (f1 + f3 + f5) - f5 f4 = -(f1 - fm) + fm = 2 * fm - f1 = 2 / 3 * (f1 + f3 + f5) - f1 f6 = -(f3 - fm) + fm = 2 * fm - f3 = 2 / 3 * (f1 + f3 + f5) - f3

Then, we have:

f2 = 2 / 3 * f1 + 2 / 3 * f3 - 1 / 3 * f5 f4 = -1 / 3 * f1 + 2 / 3 * f3 + 2 / 3 * f5 f6 = 2 / 3 * f1 - 1 / 3 * f3 + 2 / 3 * f5

In the matrix form, it will be:

(f2, f4, f6).T = M * (f1, f3, f5).T

If the hardpoints were A2, A4, A6, we would have:

(f1, f3, f5).T = M ^ (-1) * (f2, f4, f6).T

Parameters

location_axial_actuatorlist

Location of the axial actuators: (x, y). This should be a 72 x 2 matrix.

hardpoints_axiallist

Three axial hardpoints. The order is from low to high, e.g. [5, 15, 25].

hardpoints_tangentlist

Three tangential hardpoints. This can only be [72, 74, 76] or [73, 75, 77]. The order is from low to high.

Returns

hd_comp_axialnumpy.ndarray

Axial hardpoint compensation matrix.

hd_comp_tangentnumpy.ndarray

Tangential hardpoint compensation matrix.

static calc_kinetic_decoupling_matrix(location_axial_actuator: list[list], hardpoints_axial: list[int], hardpoints_tangent: list[int], stiffness_matrix: ndarray[Any, dtype[float64]]) ndarray[Any, dtype[float64]]

Calculate the kinetic decoupling matrix.

Notes

Translate the calculation from the CalcHPFCInfMat.m in ts_mtm2_matlab_tools.

The unit of the element is the motor step (could be fraction, row) per Newton (column). This matrix is used to multiply with the desired actuator’s force changes to get the related amounts of motor’s step changes.

delta_force = M * delta_step => M^-1 = kdc to have: delta_step = kdc * delta_force

Parameters

location_axial_actuatorlist

Location of the axial actuators: (x, y). This should be a 72 x 2 matrix.

hardpoints_axiallist

Three axial hardpoints. The order is from low to high, e.g. [5, 15, 25].

hardpoints_tangentlist

Three tangential hardpoints. This can only be [72, 74, 76] or [73, 75, 77]. The order is from low to high.

stiffness_matrixnumpy.ndarray

Stiffness matrix of M2 mirror or surrogate.

Returns

numpy.ndarray

Kinetic decoupling matrix.

calc_look_up_forces(lut_angle: float | None = None, enable_lut_temperature: bool | None = None) None

Calculate look-up table (LUT) forces using current system state (position and temperature).

Parameters

lut_anglefloat or None, optional

Angle used to calculate the LUT forces of gravity component. If None, bypass the calculation. (the default is None)

enable_lut_temperaturebool or None, optional

Enable the temperature LUT calculation or not. If None, bypass the calculation. (the default is None)

static calc_temp_inv_matrix() ndarray[Any, dtype[float64]]

Calculate the temperature inversion matrix.

Based on the “LSST_M2_temperature_sensors_20171102.pdf”. The sensor map is at “doc/figure/temperature_sensor_map.jpg”.

Radial gradient: T(r) = Tr * r / R X gradient: T(x) = Tx * x / R = Tx * r * cos(theta) / R Y gradient: T(y) = Ty * y / R = Ty * r * sin(theta) / R Uniform bias: T(u) = Tu

The matrix is: [r/R, r/R * cos(theta), r/R * sin(theta), 1], and we have: matrix * [Tr, Tx, Ty, Tu].T = [T1, T2, …, T12].T

Returns

numpy.ndarray

Temperature inversion matrix.

static calculate_rigid_body_xy(radius: float, tangent_hardpoint_displacement: list[float], tangent_hardpoint_location: list[float]) tuple[float, float, numpy.ndarray[Any, numpy.dtype[numpy.float64]]]

Calculate the rigid body (x, y) position.

Notes

This is part of the calculation in HardPointToRigidBody.vi in ts_mtm2.

Parameters

radiusfloat

Radius of the cell in meter.

tangent_hardpoint_displacementlist

Displacement of the 3 tangent hardpoints in meter.

tangent_hardpoint_locationlist

Location of the 3 tangent hardpoints in radian.

Returns

mean_xfloat

X position in meter.

mean_yfloat

Y position in meter.

delta_xy_tangent_hardpointnumpy.ndarray

Delta (x, y) position compared with the mean (x, y) in meter.

static get_active_actuators(hardpoints_axial: list[int], hardpoints_tangent: list[int]) tuple[list[int], list[int]]

Get the active actuators.

Parameters

hardpoints_axiallist

Three axial hardpoints. The order is from low to high, e.g. [5, 15, 25].

hardpoints_tangentlist

Three tangential hardpoints. This can only be [72, 74, 76] or [73, 75, 77]. The order is from low to high.

Returns

active_actuators_axiallist

Axial active actuators.

active_actuators_tangentlist

Tangential active actuators.

Raises

ValueError

If the tangential hardpoints are wrong.

get_actuator_location_axial() list

Get the location of axial actuators.

Returns

list

Location (x, y) of the axial actuators in meter.

get_actuator_location_tangent() list

Get the location of tangent actuators.

Returns

list

Location of the tangential actuators in degree.

get_demanded_force(applied_force_axial: ndarray[Any, dtype[float64]] | None = None, applied_force_tangent: ndarray[Any, dtype[float64]] | None = None) ndarray[Any, dtype[float64]]

Get the demanded force in Newton.

Parameters

applied_force_axialnumpy.ndarray or None, optional

Axial forces to apply in Newton. If None use current setup. (the default is None.)

applied_force_tangentnumpy.ndarray or None, optional

Tangent forces to apply in Newton. If None use current setup. ( the default is None.)

Returns

numpy.ndarray

Array with the combined total force per actuator in Newton.

get_force_balance() dict

Get the data of force balance system. This contains the net forces (in Newton) and net moments (in Newton * meter).

Returns

force_balancedict

Data of the force balance system.

get_net_forces_total() dict

Get the total net forces in Newton.

Returns

dict

Total net forces in Newton.

get_net_moments_total() dict

Get the total net moments in Newton * meter.

Returns

dict

Total net moments in Newton * meter.

get_radius() float

Get the radius of the tangential actuators.

Returns

float

Radius of the tangential actuators in meter.

handle_forces(is_in_position: bool, plant: MockPlant | None = None, steps_hardpoints: ndarray[Any, dtype[int64]] | None = None) bool

Handle forces and update the hardpoint correction and measured forces.

Parameters

is_in_positionbool

Mirror is in position or not.

plantMockPlant or None

Plant model. If not None, the movement of plant model will be applied.

steps_hardpointsnumpy.ndarray [int] or None

Hardpoint steps of the rigid body movement. (the default is None)

Returns

in_positionbool

M2 assembly is in position or not.

static hardpoint_to_rigid_body(location_axial_actuator: list[list], location_tangent_link: list[float], radius: float, hardpoints: list[int], disp_hardpoint_current: list[float], disp_hardpoint_home: list[float]) tuple[float, float, float, float, float, float]

Calculate the rigid body position based on the hardpoint displacements.

Notes

Translate the calculation from the HardPointToRigidBody.vi in ts_mtm2.

Parameters

location_axial_actuatorlist [list]

Location of the axial actuators: (x, y) in meter. This should be a (NUM_ACTUATOR - NUM_TANGENT_LINK) x 2 matrix.

location_tangent_linklist

Location of the tangent links in degree. This should be a 1 x NUM_TANGENT_LINK array.

radiusfloat

Radius of the cell in meter.

hardpointslist

Six hardpoints. The order is from low to high.

disp_hardpoint_currentlist

Six current hardpoint displacements. The unit is meter.

disp_hardpoint_homelist

Six hardpoint displacements at the home position. The unit is meter.

Returns

xfloat

X position in meter.

yfloat

Y position in meter.

zfloat

Z position in meter.

rxfloat

X rotator in radian.

ryfloat

Y rotator in radian.

rzfloat

Z rotator in radian.

is_actuator_force_out_limit(applied_force_axial: ndarray[Any, dtype[float64]] | None = None, applied_force_tangent: ndarray[Any, dtype[float64]] | None = None, use_measured_force: bool = False) tuple[bool, list, list]

The actuator force is out of limit or not.

Notes

Remove the ‘use_measured_force’ after we implement the forward modeling in the control algorithm. At that time, the measured force should be consistent with the demanded force (with the consideration of hardpoint correction).

Parameters

applied_force_axialnumpy.ndarray or None, optional

Axial forces to apply in Newton. If None use current setup. (the default is None.)

applied_force_tangentnumpy.ndarray or None, optional

Tangent forces to apply in Newton. If None use current setup. ( the default is None.)

use_measured_forcebool, optional

Use the measured force to compare with the limit. (the default is False)

Returns

bool

True if the actuator force is out of limit. Otherwise, False.

list

Triggered retracted limit switches.

list

Triggered extended limit switches.

is_cell_temperature_high() bool

Cell temperature is high or not.

Returns

bool

True if the cell temperature is high. Otherwise, False.

load_file_cell_geometry(filepath: Path) None

Load the file of cell geometry.

Parameters

filepathpathlib.PosixPath

File path of cell geometry.

load_file_lut(filepath: Path) None

Load the look-up table (LUT) files.

Parameters

filepathpathlib.PosixPath

File path of LUT directory.

load_file_stiffness(filepath: Path) None

Load the file of stiffness matrix.

Parameters

filepathpathlib.PosixPath

File path of stiffness matrix.

reset_force_offsets() None

Reset the force offsets.

This will put the applied force to be zero.

static rigid_body_to_actuator_displacement(location_axial_actuator: list[list], location_tangent_link: list[float], radius: float, dx: float, dy: float, dz: float, drx: float, dry: float, drz: float) ndarray[Any, dtype[float64]]

Calculate the actuator displacements based on the rigid body position.

Notes

Translate the calculation from the RigidBodyToActuatorDisplacement.vi in ts_mtm2. For the “radius”, the original developer had the following comment:

An average of 5 of the 6 tangent location radius from the center of the M2 cell which is to be used by the rigid body to displacement calculation. Technically, it is not the B-ring radius and this should be changed in the future.

Parameters

location_axial_actuatorlist [list]

Location of the axial actuators: (x, y) in meter. This should be a (NUM_ACTUATOR - NUM_TANGENT_LINK) x 2 matrix.

location_tangent_linklist

Location of the tangent links in degree. This should be a 1 x NUM_TANGENT_LINK array.

radiusfloat

Radius of the cell in meter.

dxfloat

Delta x position in meter.

dyfloat

Delta y position in meter.

dzfloat

Delta z position in meter.

drxfloat

Delta x rotator in radian.

dryfloat

Delta y rotator in radian.

drzfloat

Delta z rotator in radian.

Returns

numpy.ndarray

All actuator displacements in meter.

set_hardpoint_compensation() None

Set the hardpoint compensation matrix.

set_kinetic_decoupling_matrix() None

Set the kinetic decoupling matrix.

set_measured_forces(force_axial: ndarray[Any, dtype[float64]], force_tangent: ndarray[Any, dtype[float64]]) None

Set the measured actuator forces.

Parameters

force_axialnumpy.ndarray

Axial force in Newton.

force_tangentnumpy.ndarray

Tangential force in Newton.

Raises

ValueError

When the input dimensions of forces are wrong.

simulate_temperature_and_update(temperature_rms: float = 0.05, max_temperature: float = 28.0, min_temperature: float = 0.0) None

Simulate the temperature change and update the internal value.

Parameters

temperature_rmsfloat, optional

Temperature rms variation in degree C. (the default is 0.05)

max_temperaturefloat, optional

Maximum temperature in degree C. (the default is 28.0)

min_temperaturefloat, optional

Minimum temperature in degree C. (the default is 0.0)

static transfer_function_to_biquadratic_filter(numerator: list[float], denominator: list[float], num_stage: int = 8) tuple[float, numpy.ndarray[Any, numpy.dtype[numpy.float64]]]

Transfer function to the biquadratic filters.

Notes

Translate the calculation from the bqd.m and sos2pqd.m in ts_mtm2_matlab_tools.

The reference is: https://en.wikipedia.org/wiki/Digital_biquad_filter

Compact biquadratic format:

1 + b11 z^-1 + b21 z^-2 1 + b12 z^-1 + b22 z^-2

H(z) = gain * (———————–) (———————–) …

1 + a11 z^-1 + a21 z^-2 1 + a12 z^-1 + a22 z^-2

1 + b1N z^-1 + b2N z^-2

(———————–)

1 + a1N z^-1 + a2N z^-2

Format of the coefficent output is: [a11 a21 b11 b21 a12 a22 b12 b22 … a1N a2N b1N b2N]

Parameters

numeratorlist

Numerator polynomial coefficients of the transfer function.

denominatorlist

Denominator polynomial coefficients of the transfer function.

num_stageint, optional

Number of the stage of biquadratic filters. (the default is 8)

Returns

gainfloat

Gain.

coefficientslist

Coefficients of the biquadratic filters.

update_hardpoints(hardpoints: list[int]) None

Update the hardpoints and related internal parameters.

Parameters

hardpointslist

List of the 0-based hardpoints. There are 6 actuators. The first three are the axial actuators and the latter three are the tangent links.