HWP Gripper Agent
Agent which controls and monitor’s the HWP’s set of three LEY32C-30 linear actuators.
usage: python3 agent.py [-h] [--mcu-ip MCU_IP] [--control-port CONTROL_PORT]
[--warm-grip-distance WARM_GRIP_DISTANCE WARM_GRIP_DISTANCE WARM_GRIP_DISTANCE]
[--adjustment-distance ADJUSTMENT_DISTANCE ADJUSTMENT_DISTANCE ADJUSTMENT_DISTANCE]
[--supervisor-id SUPERVISOR_ID]
[--no-data-warn-time NO_DATA_WARN_TIME]
[--no-data-shutdown-time NO_DATA_SHUTDOWN_TIME]
Agent Options
- --mcu-ip
IP of Gripper Beaglebone
- --control-port
Port for actuator control as set by the Beaglebone code
Default: 8041
- --warm-grip-distance
Nominal distance for warm grip position (mm). This needsto be multiple of 0.1
Default: [10.0, 10.0, 10.0]
- --adjustment-distance
Adjustment distance to compensate the misalignment of limit switches (mm). This needs to be multiple of 0.1
Default: [0, 0, 0]
- --supervisor-id
Instance ID for HWP Supervisor agent
- --no-data-warn-time
Time (seconds) since last supervisor-ok signal to wait before issuing a warning
Default: 60
- --no-data-shutdown-time
Time (seconds) since last supervisor-ok signal to wait before entering shutdown mode
Default: 300
Configuration File Examples
Below are configuration examples for the ocs config file and for running the Agent in a docker container.
OCS Site Config
An example site-config-file block:
{'agent-class': 'HWPGripperAgent',
'instance-id': 'hwp-gripper',
'arguments': [ '--mcu_ip', '10.10.10.115',
'--control_port', 8041,
'--warm-grip-distance, 9.2, 10.6, 9.8,
'--adjustment-distance, 0., 0., 0.,
'--supervisor-id', 'hwp-supervisor',
'--no-data-warn-time', 60,
'--no-data-shutdown-time', 300, # 5 minutes
]
},
Docker Compose
An example docker-compose configuration:
ocs-hwp-gripper:
image: simonsobs/socs:latest
hostname: ocs-docker
network_mode: "host"
volumes:
- ${OCS_CONFIG_DIR}:/config:ro
environment:
- INSTANCE_ID=hwp-gripper
Description
This agent communicates with the gripper server in sobonelib, and has operations to move actuators, home actuators, check if they are in-position, etc.
This agent has two long-running processes, one to regularly query the gripper server for the gripper-state, and the other to regularly check the hwp-supervisor for the overall HWP state.
Shutdown mode
If there is something wrong with the HWP, due to power or network outages, or cryogenic issues, it is no longer safe to operate the gripper, as we may not have an accurate understanding of whether or not the HWP is spinning. If the hwp-supervisor issues a shutdown signal, or if a sufficiently long time passes where the agent is unable to connect to the supervisor, the agent enters a shutdown mode in which potentially dangerous operations are blocked.
Shutdown-mode can be cancelled by manually restarting the agent, or by running
the cancel_shutdown
task, which will allow you to operate the grippers.
Agent API
- class socs.agents.hwp_gripper.agent.HWPGripperAgent(agent, args)[source]
Agent for controlling/monitoring the HWP’s three LEY32C-30 linear actuators. This interfaces with the GripperServer running on the beaglebone microcontroller (https://github.com/simonsobs/sobonelib/blob/main/hwp_gripper/control/gripper_server.py).
This agent will issue commands to the microcontroller via OCS, and publish gripper position and limit switch states to grafana.
- Parameters:
agent (ocs.ocs_agent.OCSAgent) – Agent instance
args (argparse.Namespace) – Parsed command line arguments namespace.
- init_connection()[source]
Task - Initialize connection to the GripperServer on the BeagleBone micro-controller
- power(state=True)[source]
Task - If turning on, will power on the linear actuators and disengage brakes. If turning off, will cut power to the linear actuators and engage brakes.
- Parameters:
state (bool) – State to set the actuator power to.
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["SVON turned on in Control.ON()", "Turned off BRAKE for axis 1 in Control.BRAKE()", "Turned off BRAKE for axis 2 in Control.BRAKE()", "Turned off BRAKE for axis 3 in Control.BRAKE()", "Successfully turned off BRAKE for axis 1 in Control.BRAKE()", "Successfully turned off BRAKE for axis 2 in Control.BRAKE()", "Successfully turned off BRAKE for axis 3 in Control.BRAKE()", "Disengaged brakes in Control.ON()"]}
- brake(state=True, actuator=0)[source]
Task - Controls actuator brakes
- Parameters:
state (bool) – State to set the actuator brake to. Takes bool input
actuator (int) – Actuator number. Takes input of 0-3 with 1-3 controlling and individual actuator and 0 controlling all three
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["Turned off BRAKE for axis 1 in Control.BRAKE()", "Successfully turned off BRAKE for axis 1 in Control.BRAKE()"]}
- move(mode='push', actuator=1, distance=0)[source]
Task - Move an actuator a specific distance. If the HWP is spinning, this task will not run.
- Parameters:
mode (str) – Movement mode. Takes inputs of ‘pos’ (positioning) or ‘push’ (pushing)
actuator (int) – Actuator number 1-3
distance (float) – Distance to move (mm). Takes positive and negative numbers for ‘pos’ mode. Takes only positive numbers for ‘push’ mode. Value should be a multiple of 0.1.
Notes
Positioning mode is used when you want to position the actuators without gripping the rotor. Pushing mode is used when you want the grip the rotor.
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["Control.STEP() operation finished for step 1", "MOVE in Gripper.MOVE() completed successfully"]}
- home()[source]
Task - Homes and recalibrates the position of the actuators
Note
This action must be done first after a power cycle. Otherwise the controller will throw an error.
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["SVON turned on in Control.ON()", "'HOME' operation finished in Control.HOME()", "HOME operation in Gripper.HOME() completed"]}
- inp()[source]
Task - Queries whether the actuators are in a known position. This tells you whether the windows software has detected that the actuator has been homed.
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': []}
- alarm()[source]
Task - Queries the actuator controller alarm state
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["ALARM = False"]}
- reset()[source]
Task - Resets the current active controller alarm
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["Ignored Control.ALARM_GROUP(). No ALARM detected", "RESET aborted in Gripper.RESET() due to no detected alarm"]}
- act(actuator=1)[source]
Task - Queries whether an actuator is connected
- Parameters:
actuator (int) – Actuator number 1-3
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["Actuator 1 is in state 1"]}
- is_cold(value=False)[source]
Task - Set the limit switches to warm/cold grip configuration
- Parameters:
value (bool) – Set to warm grip (False) or cold grip (True)
Notes
Configures the software to query the correct set of limit switches. Warm grip configuration enables both warm and cold limit switches. Cold grip configuration enables only cold limit switches. The maximum extension of the actuators depends on the cryostat temperature.
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["Received request to change is_cold to True", "is_cold successfully changed"]}
- force(value=False)[source]
Task - Enable or disable force mode in the GripperServer, which will ignore limit switch information.
- Parameters:
value (bool) – Use limit switch information (False) or ignore limit switch information (True)
Notes
By default the code is configured to prevent actuator movement if on of the limit switches has been triggered. This function can be called to forcibly move the actuators even with a limit switch trigger.
The most recent data collected is stored in session data in the structure:
>>> response.session['response'] {'result': True, 'log': ["Received request to change force to True", "force successfully changed"]}
- shutdown()[source]
Task - Series of commands executed during a shutdown. This will enable shutdown mode, which locks out other agent operations.
Notes
This function is called once a shutdown trigger has been given.
- grip()[source]
Task - Series of commands to automatically warm grip the HWP. This assumes that HWP is cold. This will return grippers to their home position, then move them each inwards incrementally until warm limit switches are tiggered. If the HWP is spinning, this will not run. If this fails to grip hwp, this will return grippers to their home position.
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['responses'] [{'result': True, 'log': [.., .., etc]}, .. {'result': True, 'log': [.., .., etc]}]
- ungrip()[source]
Task - Series of commands to automatically ungrip the HWP. This will return grippers to their home position, and retract grippers as much as possible.
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session['responses'] [{'result': True, 'log': [.., .., etc]}, .. {'result': True, 'log': [.., .., etc]}]
- monitor_state()[source]
Process - Process to monitor the gripper state
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session {'last_updated': 1649085992.719602, 'state': {'last_packet_received': 1649085992.719602, 'jxc_setup': False, 'jxc_svon': False, 'jxc_busy': False, 'jxc_seton': False, 'jxc_inp': False, 'jxc_svre': False, 'jxc_alarm': False, 'jxc_out': 0, 'act{axis}_pos': 0, 'act{axis}_limit_warm_grip_state': False, 'act{axis}_limit_cold_grip_state': False, 'act{axis}_emg': False, 'act{axis}_brake': True}}
- monitor_supervisor(no_data_warn_time=60, no_data_shutdown_time=300)[source]
Process - Monitor the hwp-supervisor state. If supervisor sends shutdown signal, or if communication wtih supervisor is dropped for longer than
no_data_shutdown_time
, this will begin agent shutdown and disable access to other dangerous gripper operations.- Parameters:
no_data_warn_time (int) – Time in seconds to wait after communication failure before generating a warning
no_data_shutdown_time (int) – Time in seconds to wait after communication failure before initiating shutdown
Notes
The most recent data collected is stored in session data in the structure:
>>> response.session {'time': 1649085992.719602, 'gripper_action': 'ok'}