MockControlClosedLoop¶
- class lsst.ts.m2com.MockControlClosedLoop(is_mirror: bool = False)¶
Bases:
object
Mock closed-loop control.
Parameters¶
- is_mirror
bool
, optional Is mirror or not. If not, the surrogate is applied. (the default is False)
Attributes¶
- is_running
bool
The closed-loop control is running or not.
- temperature
dict
Temperature of mirror in degree C.
- axial_forces
dict
Forces of the axial actuators in Newton.
- tangent_forces
dict
Forces of the tangent actuators in Newton.
- hardpoints
list
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_home
list
Displacement of the hardpoints at the home position. The unit is meter.
- control_loop
MockControlLoop
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.
Calculate the force control filter parameters in biquadratic filters.
calc_hp_comp_matrix
(location_axial_actuator, ...)Calculate the hardpoint compensation 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).
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 the location of axial actuators.
Get the location of tangent actuators.
get_demanded_force
([applied_force_axial, ...])Get the demanded force in Newton.
Get the data of force balance system.
Get the total net forces in Newton.
Get the total net moments in Newton * meter.
Get the radius of the tangential actuators.
handle_forces
(is_in_position[, plant, ...])Handle forces and update the hardpoint correction and measured forces.
Calculate the rigid body position based on the hardpoint displacements.
is_actuator_force_out_limit
([...])The actuator force is out of limit or not.
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 the force offsets.
Calculate the actuator displacements based on the rigid body position.
Set the hardpoint compensation matrix.
Set the kinetic decoupling matrix.
set_measured_forces
(force_axial, force_tangent)Set the measured actuator forces.
Simulate the temperature change and update the internal value.
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_axial
list
ornumpy.ndarray
Force of the axial actuators in Newton.
- force_tangent
list
ornumpy.ndarray
Force of the tangent actuators in Newton.
Raises¶
RuntimeError
When the maximum force limits reached.
- force_axial
- 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_mirror
bool
, optional Is mirror or not. If not, the surrogate is applied. (the default is True)
- control_frequency
float
, optional Frequency of the control loop in Hz. (the default is 20.0)
- bypass_delay
bool
, optional Bypass the command delay or not. (the default is False)
- num_degree
int
, optional Number of the degree in the transfer function. (the default is 5)
Returns¶
- numerator_transfer_function
list
Numerator of the transfer function from the high degree to low degree.
- is_mirror
- 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¶
- numerator
list
or None, optional Numerator polynomial coefficients of the transfer function. If None, the linear transfer is assumed (aka. [1.0]). (the default is None)
- denominator
list
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.
- numerator
- 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_mirror
bool
, optional Is mirror or not. If not, the surrogate is applied. (the default is True)
- numerator
list
or None, optional Numerator polynomial coefficients of the transfer function. If None, the linear transfer is assumed (aka. [1.0]). (the default is None)
- denominator
list
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.
- coefficients
list
Coefficients of the force control filter parameters.
- is_mirror
- 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_actuator
list
Location of the axial actuators: (x, y). This should be a 72 x 2 matrix.
- hardpoints_axial
list
Three axial hardpoints. The order is from low to high, e.g. [5, 15, 25].
- hardpoints_tangent
list
Three tangential hardpoints. This can only be [72, 74, 76] or [73, 75, 77]. The order is from low to high.
Returns¶
- hd_comp_axial
numpy.ndarray
Axial hardpoint compensation matrix.
- hd_comp_tangent
numpy.ndarray
Tangential hardpoint compensation matrix.
- location_axial_actuator
- 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_actuator
list
Location of the axial actuators: (x, y). This should be a 72 x 2 matrix.
- hardpoints_axial
list
Three axial hardpoints. The order is from low to high, e.g. [5, 15, 25].
- hardpoints_tangent
list
Three tangential hardpoints. This can only be [72, 74, 76] or [73, 75, 77]. The order is from low to high.
- stiffness_matrix
numpy.ndarray
Stiffness matrix of M2 mirror or surrogate.
Returns¶
numpy.ndarray
Kinetic decoupling matrix.
- location_axial_actuator
- 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_angle
float
or None, optional Angle used to calculate the LUT forces of gravity component. If None, bypass the calculation. (the default is None)
- enable_lut_temperature
bool
or None, optional Enable the temperature LUT calculation or not. If None, bypass the calculation. (the default is None)
- lut_angle
- 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¶
- radius
float
Radius of the cell in meter.
- tangent_hardpoint_displacement
list
Displacement of the 3 tangent hardpoints in meter.
- tangent_hardpoint_location
list
Location of the 3 tangent hardpoints in radian.
Returns¶
- mean_x
float
X position in meter.
- mean_y
float
Y position in meter.
- delta_xy_tangent_hardpoint
numpy.ndarray
Delta (x, y) position compared with the mean (x, y) in meter.
- radius
- static get_active_actuators(hardpoints_axial: list[int], hardpoints_tangent: list[int]) tuple[list[int], list[int]] ¶
Get the active actuators.
Parameters¶
- hardpoints_axial
list
Three axial hardpoints. The order is from low to high, e.g. [5, 15, 25].
- hardpoints_tangent
list
Three tangential hardpoints. This can only be [72, 74, 76] or [73, 75, 77]. The order is from low to high.
Returns¶
- active_actuators_axial
list
Axial active actuators.
- active_actuators_tangent
list
Tangential active actuators.
Raises¶
ValueError
If the tangential hardpoints are wrong.
- hardpoints_axial
- 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_axial
numpy.ndarray
orNone
, optional Axial forces to apply in Newton. If
None
use current setup. (the default is None.)- applied_force_tangent
numpy.ndarray
orNone
, 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.
- applied_force_axial
- 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_balance
dict
Data of the force balance system.
- force_balance
- 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_position
bool
Mirror is in position or not.
- plant
MockPlant
or None Plant model. If not None, the movement of plant model will be applied.
- steps_hardpoints
numpy.ndarray
[int
] or None Hardpoint steps of the rigid body movement. (the default is None)
Returns¶
- in_position
bool
M2 assembly is in position or not.
- is_in_position
- 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_actuator
list [list]
Location of the axial actuators: (x, y) in meter. This should be a (NUM_ACTUATOR - NUM_TANGENT_LINK) x 2 matrix.
- location_tangent_link
list
Location of the tangent links in degree. This should be a 1 x NUM_TANGENT_LINK array.
- radius
float
Radius of the cell in meter.
- hardpoints
list
Six hardpoints. The order is from low to high.
- disp_hardpoint_current
list
Six current hardpoint displacements. The unit is meter.
- disp_hardpoint_home
list
Six hardpoint displacements at the home position. The unit is meter.
Returns¶
- x
float
X position in meter.
- y
float
Y position in meter.
- z
float
Z position in meter.
- rx
float
X rotator in radian.
- ry
float
Y rotator in radian.
- rz
float
Z rotator in radian.
- location_axial_actuator
- 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_axial
numpy.ndarray
orNone
, optional Axial forces to apply in Newton. If
None
use current setup. (the default is None.)- applied_force_tangent
numpy.ndarray
orNone
, optional Tangent forces to apply in Newton. If
None
use current setup. ( the default is None.)- use_measured_force
bool
, 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.
- applied_force_axial
- 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¶
- filepath
pathlib.PosixPath
File path of cell geometry.
- filepath
- load_file_lut(filepath: Path) None ¶
Load the look-up table (LUT) files.
Parameters¶
- filepath
pathlib.PosixPath
File path of LUT directory.
- filepath
- load_file_stiffness(filepath: Path) None ¶
Load the file of stiffness matrix.
Parameters¶
- filepath
pathlib.PosixPath
File path of stiffness matrix.
- filepath
- 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_actuator
list [list]
Location of the axial actuators: (x, y) in meter. This should be a (NUM_ACTUATOR - NUM_TANGENT_LINK) x 2 matrix.
- location_tangent_link
list
Location of the tangent links in degree. This should be a 1 x NUM_TANGENT_LINK array.
- radius
float
Radius of the cell in meter.
- dx
float
Delta x position in meter.
- dy
float
Delta y position in meter.
- dz
float
Delta z position in meter.
- drx
float
Delta x rotator in radian.
- dry
float
Delta y rotator in radian.
- drz
float
Delta z rotator in radian.
Returns¶
numpy.ndarray
All actuator displacements in meter.
- location_axial_actuator
- 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_axial
numpy.ndarray
Axial force in Newton.
- force_tangent
numpy.ndarray
Tangential force in Newton.
Raises¶
ValueError
When the input dimensions of forces are wrong.
- force_axial
- 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_rms
float
, optional Temperature rms variation in degree C. (the default is 0.05)
- max_temperature
float
, optional Maximum temperature in degree C. (the default is 28.0)
- min_temperature
float
, optional Minimum temperature in degree C. (the default is 0.0)
- temperature_rms
- 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¶
- numerator
list
Numerator polynomial coefficients of the transfer function.
- denominator
list
Denominator polynomial coefficients of the transfer function.
- num_stage
int
, optional Number of the stage of biquadratic filters. (the default is 8)
Returns¶
- gain
float
Gain.
- coefficients
list
Coefficients of the biquadratic filters.
- is_mirror