Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hwp site changes #541

Merged
merged 8 commits into from
Nov 22, 2023
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-ast
- id: check-yaml
Expand Down
11 changes: 5 additions & 6 deletions socs/agents/hwp_gripper/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,8 @@ def shutdown(self, session, params=None):
self.shutdown_mode = True
return True, 'Shutdown completed'

def grip_hwp(self, session, params=None):
"""grip_hwp()
def grip(self, session, params=None):
"""grip()

**Task** - Series of commands to automatically grip the HWP.
This will return grippers to their home position, then move them each
Expand Down Expand Up @@ -442,7 +442,8 @@ def run_and_append(func, *args, **kwargs):

# Reset alarms. If the warm-limit is hit, the alarm will be triggered
# and return_dict['result'] will be True
return_dict = run_and_append(self.client.reset, job='grip', check_shutdown=check_shutdown)
return_dict = run_and_append(self.client.reset, job='grip',
check_shutdown=check_shutdown)

if return_dict['result']:
# If the warm-limit is hit, move the actuator outwards bit
Expand Down Expand Up @@ -676,9 +677,7 @@ def main(args=None):
args=args)

agent, runner = ocs_agent.init_site_agent(args)
gripper_agent = HWPGripperAgent(agent, mcu_ip=args.mcu_ip,
control_port=args.control_port,
supervisor_id=args.supervisor_id)
gripper_agent = HWPGripperAgent(agent, args)
agent.register_task('init_connection', gripper_agent.init_connection,
startup=True)
agent.register_process('monitor_state', gripper_agent.monitor_state,
Expand Down
30 changes: 15 additions & 15 deletions socs/agents/hwp_pid/drivers/pid_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ class PID:

def __init__(self, ip, port, verb=False):
self.verb = verb
self.ip = ip
self.port = port
self.hex_freq = '00000'
self.direction = None
self.target = 0
# Need to setup connection before setting direction
self.conn = self._establish_connection(ip, int(port))
self.conn = self._establish_connection(self.ip, int(self.port))
self.set_direction('0')

@staticmethod
Expand All @@ -45,18 +47,15 @@ def _establish_connection(ip, port, timeout=5):

"""
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.settimeout(timeout)
# unit tests might fail on first connection attempt
attempts = 3
for attempt in range(attempts):
while True:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this being an infinite loop, since control is never passed back to the agent. Can we keep this to a finite number of attempts, and handle re-connection at the agent level?

try:
conn.connect((ip, port))
break
except ConnectionRefusedError:
except (ConnectionRefusedError, OSError) as e:
print(f"Failed to connect to device at {ip}:{port}")
print(f"Connection attempts remaining: {attempts-attempt-1}")
time.sleep(1)
conn.settimeout(timeout)

time.sleep(5)
return conn

@staticmethod
Expand Down Expand Up @@ -259,20 +258,21 @@ def send_message(self, msg):
str: Respnose from the controller.

"""
self.conn.sendall((msg + '\r\n').encode())
time.sleep(0.5) # Don't send messages too quickly
for attempt in range(2):
try:
self.conn.sendall((msg + '\r\n').encode())
time.sleep(0.5) # Don't send messages too quickly
data = self.conn.recv(4096).decode().strip()
break
except socket.timeout:
return data
except (socket.timeout, OSError) as e:
print("Caught timeout waiting for response from PID controller. "
+ "Trying again...")
time.sleep(1)
if attempt == 1:
raise RuntimeError(
'Response from PID controller timed out.')
return data
print("Resetting connection")
self.conn.close()
self.conn = self._establish_connection(self.ip, int(self.port))
return self.send_message(msg)

def return_messages(self, msg):
"""Decode list of responses from PID controller and return useful
Expand Down
92 changes: 54 additions & 38 deletions socs/agents/hwp_pmx/drivers/PMX_ethernet.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import socket
import time
from socket import AF_INET, SOCK_STREAM, socket

protection_status_key = [
'Over voltage',
Expand All @@ -21,26 +21,51 @@ class PMX:
"""

def __init__(self, ip, port):
self.sock = socket(AF_INET, SOCK_STREAM)
self.sock.connect((ip, port))
self.sock.settimeout(5)

self.ip = ip
self.port = port
self.wait_time = 0.01
self.buffer_size = 128
self.conn = self._establish_connection(self.ip, int(self.port))

def _establish_connection(self, ip, port, timeout=5):
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.settimeout(timeout)
while True:
try:
conn.connect((ip, port))
break
except (ConnectionRefusedError, OSError) as e:
print(f"Failed to connect to device at {ip}:{port}")
time.sleep(5)
return conn

def close(self):
self.sock.close()

def read(self):
return self.sock.recv(self.buffer_size).decode('utf-8')
self.conn.close()

def send_message(self, msg, read=True):
for attempt in range(2):
try:
self.conn.sendall(msg)
time.sleep(0.5)
if read:
data = self.conn.recv(self.buffer_size).decode('utf-8')
return data
return
except (socket.timeout, OSError) as e:
print("Caught timeout waiting for responce from PMX. Trying again...")
time.sleep(1)
if attempt == 1:
print("Resetting connection")
self.conn.close()
self.conn = self._establish_connection(self.ip, int(self.port))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as mentioned above, if there is no connection, establish_connection here will wait forever. Instead, this should throw an error after a finite amount of time.

return self.send_message(msg, read=read)

def wait(self):
time.sleep(self.wait_time)

def check_output(self):
""" Return the output status """
self.sock.sendall(b'output?\n')
val = int(self.read())
val = int(self.send_message(b'output?\n'))
msg = "Measured output state = "
states = {0: 'OFF', 1: 'ON'}
if val in states:
Expand All @@ -51,103 +76,95 @@ def check_output(self):

def check_error(self):
""" Check oldest error from error queues. Error queues store up to 255 errors """
self.sock.sendall(b':system:error?\n')
val = self.read()
val = self.send_message(b':system:error?\n')
code, msg = val.split(',')
code = int(code)
msg = msg[1:-2]
return msg, code

def clear_alarm(self):
""" Clear alarm """
self.sock.sendall(b'output:protection:clear\n')
self.send_message(b'output:protection:clear\n', read=False)

def turn_on(self):
""" Turn the PMX on """
self.sock.sendall(b'output 1\n')
self.send_message(b'output 1\n', read=False)
self.wait()
return self.check_output()

def turn_off(self):
""" Turn the PMX off """
self.sock.sendall(b'output 0\n')
self.send_message(b'output 0\n', read=False)
self.wait()
return self.check_output()

def check_current(self):
""" Check the current setting """
self.sock.sendall(b'curr?\n')
val = float(self.read())
val = float(self.send_message(b'curr?\n'))
msg = "Current setting = {:.3f} A".format(val)
return msg, val

def check_voltage(self):
""" Check the voltage setting """
self.sock.sendall(b'volt?\n')
val = float(self.read())
val = float(self.send_message(b'volt?\n'))
msg = "Voltage setting = {:.3f} V".format(val)
return msg, val

def meas_current(self):
""" Measure the current """
self.sock.sendall(b'meas:curr?\n')
val = float(self.read())
val = float(self.send_message(b'meas:curr?\n'))
msg = "Measured current = {:.3f} A".format(val)
return msg, val

def meas_voltage(self):
""" Measure the voltage """
self.sock.sendall(b'meas:volt?\n')
val = float(self.read())
val = float(self.send_message(b'meas:volt?\n'))
msg = "Measured voltage = {:.3f} V".format(val)
return msg, val

def set_current(self, curr):
""" Set the current """
self.sock.sendall(b'curr %a\n' % curr)
self.send_message(b'curr %a\n' % curr, read=False)
self.wait()
return self.check_current()

def set_voltage(self, vol):
""" Set the voltage """
self.sock.sendall(b'volt %a\n' % vol)
self.send_message(b'volt %a\n' % vol, read=False)
self.wait()
return self.check_voltage()

def check_source(self):
""" Check the source of PMX """
self.sock.sendall(b'volt:ext:sour?\n')
val = self.read()
val = self.send_message(b'volt:ext:sour?\n')
msg = "Source: " + val
return msg, val

def use_external_voltage(self):
""" Set PMX to use external voltage """
self.sock.sendall(b'volt:ext:sour volt\n')
self.send_message(b'volt:ext:sour volt\n', read=False)
self.wait()
return self.check_source()

def ign_external_voltage(self):
""" Set PMX to ignore external voltage """
self.sock.sendall(b'volt:ext:sour none\n')
self.send_message(b'volt:ext:sour none\n', read=False)
self.wait()
return self.check_source()

def set_current_limit(self, curr_lim):
""" Set the PMX current limit """
self.sock.sendall(b'curr:prot %a\n' % curr_lim)
self.send_message(b'curr:prot %a\n' % curr_lim)
BrianJKoopman marked this conversation as resolved.
Show resolved Hide resolved
self.wait()
self.sock.sendall(b'curr:prot?\n')
val = float(self.read())
val = float(self.send_message(b'curr:prot?\n'))
msg = "Current Limit: {:.3f} A".format(val)
return msg

def set_voltage_limit(self, vol_lim):
""" Set the PMX voltage limit """
self.sock.sendall(b'volt:prot %a\n' % vol_lim)
self.send_message(b'volt:prot %a\n' % vol_lim, read=False)
self.wait()
self.sock.sendall(b'volt:prot?\n')
val = float(self.read())
val = float(self.send_message(b'volt:prot?\n'))
msg = "Voltage Limit: {:.3f} V".format(val)
return msg

Expand All @@ -156,8 +173,7 @@ def check_prot(self):
Return:
val (int): protection status code
"""
self.sock.sendall(b'stat:ques?\n')
val = int(self.read())
val = int(self.send_message(b'stat:ques?\n'))
return val

def get_prot_msg(self, val):
Expand Down
Loading