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]}]
cancel_shutdown()[source]

Task - Take the gripper agent out of shutdown mode

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'}