MockControlClosedLoop

class lsst.ts.m2com.MockControlClosedLoop

Bases: object

Mock closed-loop control.

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.

in_position_hardpointsbool

Hardpoints are in position or not.

Methods Summary

apply_forces(force_axial, force_tangent)

Apply the actuator forces.

calc_hp_comp_matrix(location_axial_actuator, ...)

Calculate the hardpoint compensation 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_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([force_rms, force_per_cycle])

Handle forces and check the actuators are in position or not based on the demanded forces, 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.

reset_force_offsets()

Reset the force offsets.

rigid_body_to_actuator_displacement(...)

Calculate the actuator displacements based on the rigid body position.

select_axial_hardpoints(...)

Select the axial hardpoints based on the specific axial hardpoint.

set_hardpoint_compensation()

Set the hardpoint compensation 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.

Methods Documentation

apply_forces(force_axial: list[float] | numpy.ndarray[Any, numpy.dtype[numpy.float64]], force_tangent: list[float] | numpy.ndarray[Any, numpy.dtype[numpy.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_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.

Parameters:
location_axial_actuatorlist [list]

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.

Raises:
ValueError

If the axial hardpoints are bad.

ValueError

If the tangential hardpoints are wrong.

Notes

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.

calc_look_up_forces(lut_angle: float) None

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

Parameters:
lut_anglefloat

Angle used to calculate the LUT forces of gravity component.

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.

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.

Notes

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

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: Optional[ndarray[Any, dtype[float64]]] = None, applied_force_tangent: Optional[ndarray[Any, dtype[float64]]] = 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(force_rms: float = 0.5, force_per_cycle: float = 5) bool

Handle forces and check the actuators are in position or not based on the demanded forces, hardpoint correction, and measured forces.

If the closed-loop control is running, the measured force will be updated based on the “force_per_cycle” as well to decrease the force error. This update will add a random error based on “force_rms”. Therefore, even in the convergend condition, the “in_position” might be False, which is an expected behavior for the real hardware.

This function makes sure the forces are inside range and compute the forces dynamics.

Parameters:
force_rmsfloat, optional

Force rms variation in Newton. (the default is 0.5)

force_per_cyclefloat, optional

Force per cycle to apply in Newton. (the default is 5)

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.

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.

Notes

Translate the calculation from the HardPointToRigidBody.vi in ts_mtm2.

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

The actuator force is out of limit or not.

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.

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).

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.

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.

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.

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.

static select_axial_hardpoints(location_axial_actuator: list[list], specific_axial_hardpoint: int) list

Select the axial hardpoints based on the specific axial hardpoint.

Parameters:
location_axial_actuatorlist [list]

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

specific_axial_hardpointint

Specific axial hardpoint.

Returns:
hardpointslist [int]

Selected 3 axial hardpoints that contains the specific axial hardpoint. The order is from low to high.

Notes

Translate the calculation from the OptAxHardpointSelect.m in ts_mtm2_matlab_tools.

The idea is to maximize the triangle constructed by 3 axial actuators, which means it should be closed to the equilateral triangle.

set_hardpoint_compensation() None

Set the hardpoint compensation 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)