Robot Crashing During Tele-Op

Hello, I had a robot crash during tele-op using a Stretch Body script on a Stretch RE1. It seems the dynamiters have disconnected but when I run robot.startup() (after calling robot = stretch_body.robot.Robot()) again, the robot runs fine. I am wondering if there would be a way to restart the robot automatically when this happens, perhaps with a try and catch. This was the following output:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 500, in read
    raise SerialException(
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/dynamixel_X_chain.py", line 132, in pull_status
    pos = self.sync_read(self.readers['pos'])
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/dynamixel_X_chain.py", line 209, in sync_read
    result = reader.txRxPacket()
  File "/home/jehan/.local/lib/python3.8/site-packages/dynamixel_sdk/group_sync_read.py", line 119, in txRxPacket
    return self.rxPacket()
  File "/home/jehan/.local/lib/python3.8/site-packages/dynamixel_sdk/group_sync_read.py", line 102, in rxPacket
    self.data_dict[dxl_id], result, _ = self.ph.readRx(self.port, dxl_id, self.data_length)
  File "/home/jehan/.local/lib/python3.8/site-packages/dynamixel_sdk/protocol2_packet_handler.py", line 536, in readRx
    rxpacket, result = self.rxPacket(port)
  File "/home/jehan/.local/lib/python3.8/site-packages/dynamixel_sdk/protocol2_packet_handler.py", line 257, in rxPacket
    rxpacket.extend(port.readPort(wait_length - rx_length))
  File "/home/jehan/.local/lib/python3.8/site-packages/dynamixel_sdk/port_handler.py", line 78, in readPort
    return self.ser.read(length)
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 509, in read
    raise SerialException('read failed: {}'.format(e))
serial.serialutil.SerialException: read failed: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/robot.py", line 40, in run
    self.robot._pull_status_dynamixel()
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/robot.py", line 367, in _pull_status_dynamixel
    self.end_of_arm.pull_status()
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/dynamixel_X_chain.py", line 196, in pull_status
    self.port_handler.ser.reset_output_buffer()
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 604, in reset_output_buffer
    termios.tcflush(self.fd, termios.TCOFLUSH)
termios.error: (5, 'Input/output error')
IOError(5): Input/output error
[ERROR] [hello-motor-arm]: SerialException: /dev/hello-motor-arm : write failed: [Errno 5] Input/output error
[ERROR] [wacc]: SerialException: /dev/hello-wacc : write failed: [Errno 5] Input/output error
[WARNING] [stretch_gripper]: Dynamixel communication error on stretch_gripper: 
Traceback (most recent call last):
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/dynamixel_hello_XL430.py", line 252, in pull_status
    x = self.motor.get_pos()
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/dynamixel_XL430.py", line 582, in get_pos
    self.handle_comm_result('XL430_ADDR_PRESENT_POSITION', dxl_comm_result, dxl_error)
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/dynamixel_XL430.py", line 239, in handle_comm_result
    raise DynamixelCommError
stretch_body.dynamixel_XL430.DynamixelCommError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/jehan/IntanTCP/RobotControl/UDPServerControlRobot.py", line 100, in <module>
    main()
  File "/home/jehan/IntanTCP/RobotControl/UDPServerControlRobot.py", line 93, in main
    gesture_command(gesture, increment=float(increment))
  File "/home/jehan/IntanTCP/RobotControl/UDPServerControlRobot.py", line 50, in gesture_command
    robot.end_of_arm.move_by(joint, direct * increment)
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/end_of_arm.py", line 61, in move_by
    self.motors[joint].move_by(x_r, v_r, a_r)
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/stretch_gripper.py", line 54, in move_by
    self.pull_status() #Ensure up to date
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/stretch_gripper.py", line 60, in pull_status
    DynamixelHelloXL430.pull_status(self,data)
  File "/home/jehan/.local/lib/python3.8/site-packages/stretch_body/dynamixel_hello_XL430.py", line 295, in pull_status
    self.motor.port_handler.ser.reset_output_buffer()
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 604, in reset_output_buffer
    termios.tcflush(self.fd, termios.TCOFLUSH)
termios.error: (5, 'Input/output error')

Hi @jehan, you could try a bash script that restarts your Python script whenever it hits an exception. For example, create a file called “forever.sh” with the following:

until python3 main.py; do
    echo 'Program main.py crashed. Restarting in 1 second.'
    sleep 1
done

Replace “main.py” with the name of your program, and call the script using bash forever.sh.