Skip to content

Commit fecb175

Browse files
urfeexdomire8
andauthored
Parametrize reconnection time for UrDriver (#266)
It would be beneficial to allow reconfiguring the connection attempts and timeout of the UrDriver / RTDEClient. --------- Co-authored-by: Dominic Reber <[email protected]>
1 parent 9890ba7 commit fecb175

File tree

8 files changed

+99
-33
lines changed

8 files changed

+99
-33
lines changed

include/ur_client_library/primary/primary_client.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ class PrimaryClient
6666
* \param primary_consumer Primary consumer that should be removed from the list
6767
*/
6868
void removePrimaryConsumer(std::shared_ptr<comm::IConsumer<PrimaryPackage>> primary_consumer);
69-
void start();
69+
void start(const size_t max_connection_attempts = 0,
70+
const std::chrono::milliseconds reconnection_timeout = urcl::comm::TCPSocket::DEFAULT_RECONNECTION_TIME);
7071

7172
/*!
7273
* \brief Retrieves previously raised error codes from PrimaryClient. After calling this, recorded errors will be

include/ur_client_library/rtde/rtde_client.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ namespace rtde_interface
5353
{
5454
static const uint16_t MAX_RTDE_PROTOCOL_VERSION = 2;
5555
static const unsigned MAX_REQUEST_RETRIES = 5;
56-
static const unsigned MAX_INITIALIZE_ATTEMPTS = 10;
5756

5857
enum class UrRtdeRobotStatusBits
5958
{
@@ -131,14 +130,21 @@ class RTDEClient
131130
* \brief Sets up RTDE communication with the robot. The handshake includes negotiation of the
132131
* used protocol version and setting of input and output recipes.
133132
*
134-
* \param max_num_tries Maximum number of connection attempts before counting the connection as
133+
* \param max_connection_attempts Maximum number of (socket) connection attempts before counting the connection as
135134
* failed. Unlimited number of attempts when set to 0.
136-
* \param reconnection_time time in between connection attempts to the server
135+
* \param reconnection_timeout Time in between connection attempts to the socket
136+
* \param max_initialization_attempts Maximum number of initialization attempts before counting
137+
* the initialization as failed. Initialization can
138+
* fail given an established socket connection e.g. when the connected socket does not implement
139+
* an RTDE interface.
140+
* \param initialization_timeout Time in between initialization attempts of the RTDE interface
137141
*
138142
* \returns Success of the handshake
139143
*/
140-
bool init(const size_t max_num_tries = 0,
141-
const std::chrono::milliseconds reconnection_time = std::chrono::seconds(10));
144+
bool init(const size_t max_connection_attempts = 0,
145+
const std::chrono::milliseconds reconnection_timeout = comm::TCPSocket::DEFAULT_RECONNECTION_TIME,
146+
const size_t max_initialization_attempts = 3,
147+
const std::chrono::milliseconds initialization_timeout = std::chrono::seconds(1));
142148
/*!
143149
* \brief Triggers the robot to start sending RTDE data packages in the negotiated format.
144150
*

include/ur_client_library/ur/ur_driver.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#ifndef UR_CLIENT_LIBRARY_UR_UR_DRIVER_H_INCLUDED
2929
#define UR_CLIENT_LIBRARY_UR_UR_DRIVER_H_INCLUDED
3030

31+
#include <chrono>
3132
#include <functional>
3233

3334
#include "ur_client_library/rtde/rtde_client.h"
@@ -107,6 +108,30 @@ struct UrDriverConfiguration
107108
*/
108109
double servoj_lookahead_time = 0.03;
109110

111+
/*!
112+
* \brief Number of attempts to reconnect to sockets such as the primary or RTDE interface.
113+
*
114+
* If set to 0, the driver will try to reconnect indefinitely.
115+
*/
116+
size_t socket_reconnect_attempts = 0;
117+
118+
/*!
119+
* \brief Time in between connection attempts to sockets such as the primary or RTDE interface.
120+
*/
121+
std::chrono::milliseconds socket_reconnection_timeout = std::chrono::seconds(10);
122+
123+
/*!
124+
* \brief Number of attempts to initialize (given a successful socket connection) the RTDE interface.
125+
*
126+
* If set to 0, the driver will try to initialize the RTDE interface indefinitely.
127+
*/
128+
size_t rtde_initialization_attempts_ = 3;
129+
130+
/*!
131+
* \brief Time in between initialization attempts of the RTDE interface.
132+
*/
133+
std::chrono::milliseconds rtde_initialization_timeout_ = std::chrono::seconds(5);
134+
110135
bool non_blocking_read = false;
111136

112137
// TODO: Remove on 2027-05
@@ -873,6 +898,12 @@ class UrDriver
873898
std::unique_ptr<comm::URStream<primary_interface::PrimaryPackage>> primary_stream_;
874899
std::unique_ptr<comm::URStream<primary_interface::PrimaryPackage>> secondary_stream_;
875900

901+
size_t socket_connection_attempts_ = 0;
902+
std::chrono::milliseconds socket_reconnection_timeout_ = std::chrono::milliseconds(10000);
903+
904+
size_t rtde_initialization_attempts_ = 0;
905+
std::chrono::milliseconds rtde_initialization_timeout_ = std::chrono::milliseconds(10000);
906+
876907
double force_mode_gain_scale_factor_ = 0.5;
877908
double force_mode_damping_factor_ = 0.025;
878909

src/comm/tcp_socket.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,24 @@ bool TCPSocket::setup(const std::string& host, const int port, const size_t max_
109109

110110
freeaddrinfo(result);
111111

112-
if (max_num_tries > 0)
112+
if (!connected)
113113
{
114-
if (connect_counter++ >= max_num_tries)
114+
state_ = SocketState::Invalid;
115+
if (++connect_counter >= max_num_tries && max_num_tries > 0)
115116
{
116117
URCL_LOG_ERROR("Failed to establish connection for %s:%d after %d tries", host.c_str(), port, max_num_tries);
117-
state_ = SocketState::Invalid;
118118
return false;
119119
}
120-
}
121-
122-
if (!connected)
123-
{
124-
state_ = SocketState::Invalid;
125-
std::stringstream ss;
126-
ss << "Failed to connect to robot on IP " << host_name
127-
<< ". Please check that the robot is booted and reachable on " << host_name << ". Retrying in "
128-
<< std::chrono::duration_cast<std::chrono::duration<float>>(reconnection_time_resolved).count() << " seconds";
129-
URCL_LOG_ERROR("%s", ss.str().c_str());
130-
std::this_thread::sleep_for(reconnection_time_resolved);
120+
else
121+
{
122+
std::stringstream ss;
123+
ss << "Failed to connect to robot on IP " << host_name << ":" << port
124+
<< ". Please check that the robot is booted and reachable on " << host_name << ". Retrying in "
125+
<< std::chrono::duration_cast<std::chrono::duration<float>>(reconnection_time_resolved).count()
126+
<< " seconds.";
127+
URCL_LOG_ERROR("%s", ss.str().c_str());
128+
std::this_thread::sleep_for(reconnection_time_resolved);
129+
}
131130
}
132131
}
133132
setupOptions();

src/primary/primary_client.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ PrimaryClient::~PrimaryClient()
6060
pipeline_->stop();
6161
}
6262

63-
void PrimaryClient::start()
63+
void PrimaryClient::start(const size_t max_num_tries, const std::chrono::milliseconds reconnection_time)
6464
{
6565
URCL_LOG_INFO("Starting primary client pipeline");
66-
pipeline_->init();
66+
pipeline_->init(max_num_tries, reconnection_time);
6767
pipeline_->run();
6868
}
6969

src/rtde/rtde_client.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828

2929
#include "ur_client_library/rtde/rtde_client.h"
3030
#include "ur_client_library/exceptions.h"
31+
#include "ur_client_library/log.h"
3132
#include <algorithm>
33+
#include <chrono>
3234

3335
namespace urcl
3436
{
@@ -74,26 +76,34 @@ RTDEClient::~RTDEClient()
7476
disconnect();
7577
}
7678

77-
bool RTDEClient::init(const size_t max_num_tries, const std::chrono::milliseconds reconnection_time)
79+
bool RTDEClient::init(const size_t max_connection_attempts, const std::chrono::milliseconds reconnection_timeout,
80+
const size_t max_initialization_attempts, const std::chrono::milliseconds initialization_timeout)
7881
{
82+
if (max_initialization_attempts <= 0)
83+
{
84+
throw UrException("The number of initialization attempts has to be greater than 0.");
85+
}
86+
7987
if (client_state_ > ClientState::UNINITIALIZED)
8088
{
8189
return true;
8290
}
8391

8492
unsigned int attempts = 0;
85-
while (attempts < MAX_INITIALIZE_ATTEMPTS)
93+
while (attempts < max_initialization_attempts)
8694
{
87-
setupCommunication(max_num_tries, reconnection_time);
95+
setupCommunication(max_connection_attempts, reconnection_timeout);
8896
if (client_state_ == ClientState::INITIALIZED)
8997
return true;
9098

91-
URCL_LOG_ERROR("Failed to initialize RTDE client, retrying in 10 seconds");
92-
std::this_thread::sleep_for(std::chrono::seconds(10));
93-
attempts++;
99+
if (++attempts < max_initialization_attempts)
100+
{
101+
URCL_LOG_ERROR("Failed to initialize RTDE client, retrying in %d seconds", initialization_timeout.count() / 1000);
102+
std::this_thread::sleep_for(initialization_timeout);
103+
}
94104
}
95105
std::stringstream ss;
96-
ss << "Failed to initialize RTDE client after " << MAX_INITIALIZE_ATTEMPTS << " attempts";
106+
ss << "Failed to initialize RTDE client after " << max_initialization_attempts << " attempts";
97107
throw UrException(ss.str());
98108
}
99109

@@ -241,7 +251,7 @@ void RTDEClient::queryURControlVersion()
241251
else
242252
{
243253
std::stringstream ss;
244-
ss << "Did not receive protocol negotiation answer from robot. Message received instead: " << std::endl
254+
ss << "Did not receive URControl version from robot. Message received instead: " << std::endl
245255
<< package->toString() << ". Retrying...";
246256
num_retries++;
247257
URCL_LOG_WARN("%s", ss.str().c_str());

src/ur/ur_driver.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ void UrDriver::init(const UrDriverConfiguration& config)
6060
servoj_lookahead_time_ = config.servoj_lookahead_time;
6161
handle_program_state_ = config.handle_program_state;
6262
in_headless_mode_ = config.headless_mode;
63+
socket_connection_attempts_ = config.socket_reconnect_attempts;
64+
socket_reconnection_timeout_ = config.socket_reconnection_timeout;
65+
rtde_initialization_attempts_ = config.rtde_initialization_attempts_;
66+
rtde_initialization_timeout_ = config.rtde_initialization_timeout_;
6367

6468
URCL_LOG_DEBUG("Initializing urdriver");
6569
URCL_LOG_DEBUG("Initializing RTDE client");
@@ -70,7 +74,7 @@ void UrDriver::init(const UrDriverConfiguration& config)
7074
new comm::URStream<primary_interface::PrimaryPackage>(robot_ip_, urcl::primary_interface::UR_PRIMARY_PORT));
7175
secondary_stream_.reset(
7276
new comm::URStream<primary_interface::PrimaryPackage>(robot_ip_, urcl::primary_interface::UR_SECONDARY_PORT));
73-
secondary_stream_->connect();
77+
secondary_stream_->connect(socket_connection_attempts_, socket_reconnection_timeout_);
7478

7579
primary_client_.reset(new urcl::primary_interface::PrimaryClient(robot_ip_, notifier_));
7680

@@ -691,7 +695,8 @@ void UrDriver::resetRTDEClient(const std::string& output_recipe_filename, const
691695

692696
void UrDriver::initRTDE()
693697
{
694-
if (!rtde_client_->init())
698+
if (!rtde_client_->init(socket_connection_attempts_, socket_reconnection_timeout_, rtde_initialization_attempts_,
699+
rtde_initialization_timeout_))
695700
{
696701
throw UrException("Initialization of RTDE client went wrong.");
697702
}
@@ -706,7 +711,7 @@ void UrDriver::setupReverseInterface(const uint32_t reverse_port)
706711

707712
void UrDriver::startPrimaryClientCommunication()
708713
{
709-
primary_client_->start();
714+
primary_client_->start(socket_connection_attempts_, socket_reconnection_timeout_);
710715
}
711716

712717
std::deque<urcl::primary_interface::ErrorCode> UrDriver::getErrorCodes()

tests/test_ur_driver.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
#include <ur_client_library/ur/dashboard_client.h>
3434
#include <thread>
35+
#include "ur_client_library/log.h"
3536
#define private public
3637
#include <ur_client_library/ur/ur_driver.h>
3738
#include <ur_client_library/example_robot_wrapper.h>
@@ -268,6 +269,19 @@ TEST_F(UrDriverTest, read_error_code)
268269
EXPECT_TRUE(g_my_robot->dashboard_client_->commandUnlockProtectiveStop());
269270
}
270271

272+
TEST(UrDriverInitTest, setting_connection_limits_works_correctly)
273+
{
274+
UrDriverConfiguration config;
275+
config.socket_reconnect_attempts = 1;
276+
config.socket_reconnection_timeout = std::chrono::milliseconds(200);
277+
config.robot_ip = "192.168.56.100"; // That IP address should not exist on the test network
278+
config.input_recipe_file = INPUT_RECIPE;
279+
config.output_recipe_file = OUTPUT_RECIPE;
280+
config.headless_mode = g_HEADLESS;
281+
282+
EXPECT_THROW(UrDriver ur_driver(config), UrException);
283+
}
284+
271285
// TODO we should add more tests for the UrDriver class.
272286

273287
int main(int argc, char* argv[])

0 commit comments

Comments
 (0)