Skip to content

Commit 6dd501f

Browse files
authored
Improve socket connection robustness in external_control.urscript (UniversalRobots#453)
**Summary** This PR strengthens the socket connection logic in _external_control.urscript_ to make driver startup more reliable and fault‑tolerant. Issue related: UniversalRobots#439 **What’s changed** Added a _connect_socket_with_retry()_ helper with configurable attempts and delay. Enforced the required connection order: - _trajectory_socket_ - _script_command_socket_ - _reverse_socket (must be last)_ Implemented a loop that retries only the sockets that are not yet connected (no redundant reconnects). Added a popup notification when any connection attempt fails. **Why** Ensures stable behavior during driver startup under transient network conditions. Avoids unnecessary reconnection attempts once a socket is successfully established. Avoids the program to run although the sockets haven't been connected.
1 parent c2e7fe5 commit 6dd501f

1 file changed

Lines changed: 67 additions & 4 deletions

File tree

resources/external_control.urscript

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -831,13 +831,76 @@ thread script_commands():
831831
end
832832
end
833833

834+
###
835+
# @brief Attempts to open a socket connection multiple times until success or max attempts are reached.
836+
#
837+
# Tries to establish a TCP socket connection to the specified host and port using the provided names.
838+
# Between attempts, the function waits for a fixed duration (dt). If a connection is established
839+
# before reaching the maximum number of attempts, the function returns True, otherwise it returns False.
840+
#
841+
# @param host string The target server IP or hostname to connect to.
842+
# @param port number The TCP port number on the server.
843+
# @param name string The name used to identify the socket in URScript.
844+
# @param max_attempts number Maximum number of connection attempts (default: 5).
845+
# @param dt number Delay in seconds between attempts (default: 0.2 s).
846+
#
847+
# @returns bool True if the socket was successfully opened, False otherwise.
848+
###
849+
def connect_socket_with_retry(host, port, name, max_attempts=5, dt=0.2):
850+
attempt = 0
851+
while attempt < max_attempts:
852+
if socket_open(host, port, name):
853+
textmsg("Successfully connected to ", name)
854+
return True
855+
end
856+
sleep(dt)
857+
attempt = attempt + 1
858+
end
859+
return False
860+
end
861+
834862
# HEADER_END
835863

836864
# NODE_CONTROL_LOOP_BEGINS
837-
socket_open("{{SERVER_IP_REPLACE}}", {{TRAJECTORY_SERVER_PORT_REPLACE}}, "trajectory_socket")
838-
socket_open("{{SERVER_IP_REPLACE}}", {{SCRIPT_COMMAND_SERVER_PORT_REPLACE}}, "script_command_socket")
839-
# This socket should be opened last as it tells the driver when it has control over the robot
840-
socket_open("{{SERVER_IP_REPLACE}}", {{SERVER_PORT_REPLACE}}, "reverse_socket")
865+
866+
# Attempt to establish the three required socket connections, if at least one socket is still disconnected,
867+
# a popup is shown and the loop continues until all three flags are True.
868+
traj_flag = False
869+
com_flag = False
870+
rev_flag = False
871+
while not (traj_flag and com_flag and rev_flag):
872+
if not traj_flag:
873+
traj_flag = connect_socket_with_retry("{{SERVER_IP_REPLACE}}", {{TRAJECTORY_SERVER_PORT_REPLACE}}, "trajectory_socket")
874+
end
875+
876+
if traj_flag and not com_flag:
877+
com_flag = connect_socket_with_retry("{{SERVER_IP_REPLACE}}", {{SCRIPT_COMMAND_SERVER_PORT_REPLACE}}, "script_command_socket")
878+
end
879+
880+
if traj_flag and com_flag and not rev_flag:
881+
rev_flag = connect_socket_with_retry("{{SERVER_IP_REPLACE}}", {{SERVER_PORT_REPLACE}}, "reverse_socket")
882+
end
883+
884+
if not (traj_flag and com_flag and rev_flag):
885+
error_str = str_cat(
886+
str_cat("Trajectory socket ({{TRAJECTORY_SERVER_PORT_REPLACE}}) connected: ", traj_flag), str_cat(
887+
str_cat("<br/>Script command socket ({{SCRIPT_COMMAND_SERVER_PORT_REPLACE}}) connected: ", com_flag), str_cat(
888+
str_cat("<br/>Reverse socket ({{SERVER_PORT_REPLACE}}) connected: ", rev_flag),
889+
"<br/><br/>Please check that the external control end at {{SERVER_IP_REPLACE}} is running correctly. Press 'Continue' to retry.")))
890+
891+
if traj_flag:
892+
socket_close("trajectory_socket")
893+
traj_flag = False
894+
end
895+
896+
if com_flag:
897+
socket_close("script_command_socket")
898+
com_flag = False
899+
end
900+
901+
popup(error_str, title="Error connecting to remote", blocking=True, error=True)
902+
end
903+
end
841904

842905
control_mode = MODE_UNINITIALIZED
843906
thread_move = 0

0 commit comments

Comments
 (0)