Skip to content

Commit f8b9763

Browse files
committed
Use exceptions instead of booleans to handle failures in commands
This should make using this easier and debug information / stack traces should be more explicit.
1 parent ce26863 commit f8b9763

File tree

6 files changed

+76
-36
lines changed

6 files changed

+76
-36
lines changed

include/ur_client_library/exceptions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,13 @@ class TimeoutException : public UrException
120120
{
121121
public:
122122
explicit TimeoutException() = delete;
123+
explicit TimeoutException(const std::string& text, std::chrono::milliseconds timeout) : std::runtime_error(text)
124+
{
125+
std::stringstream ss;
126+
ss << text << "(Configured timeout: " << timeout.count() / 1000.0 << " sec)";
127+
text_ = ss.str();
128+
}
129+
123130
explicit TimeoutException(const std::string& text, timeval timeout) : std::runtime_error(text)
124131
{
125132
std::stringstream ss;

include/ur_client_library/helpers.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,18 @@ static inline int sched_get_priority_max(int policy)
6565
namespace urcl
6666
{
6767
bool setFiFoScheduling(pthread_t& thread, const int priority);
68-
bool waitFor(std::function<bool()> condition, const std::chrono::milliseconds timeout,
68+
69+
/*!
70+
* \brief Wait for a condition to be true.
71+
*
72+
* This function will wait for a condition to be true. The condition is checked in intervals of \p check_interval.
73+
* If the condition is not met after \p timeout, the function will throw a urcl::TimeoutException.
74+
*
75+
* \param condition The condition to be checked.
76+
* \param timeout The maximum time to wait for the condition to be true.
77+
* \param check_interval The interval in which the condition is checked.
78+
*/
79+
void waitFor(std::function<bool()> condition, const std::chrono::milliseconds timeout,
6980
const std::chrono::milliseconds check_interval = std::chrono::milliseconds(50));
7081
} // namespace urcl
7182
#endif // ifndef UR_CLIENT_LIBRARY_HELPERS_H_INCLUDED

include/ur_client_library/primary/primary_client.h

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ class PrimaryClient
9797
* passed by.
9898
* \param timeout The maximum time to wait for the robot to confirm the power on command.
9999
*
100-
* \returns true on successful power on, false otherwise.
100+
* \throws urcl::UrException if the command cannot be sent to the robot.
101+
* \throws urcl::TimeoutException if the robot doesn't power on within the given timeout.
101102
*/
102-
bool commandPowerOn(const bool validate = true, const std::chrono::milliseconds timeout = std::chrono::seconds(30));
103+
void commandPowerOn(const bool validate = true, const std::chrono::milliseconds timeout = std::chrono::seconds(30));
103104

104105
/*!
105106
* \brief Commands the robot to power off.
@@ -108,9 +109,10 @@ class PrimaryClient
108109
* passed by.
109110
* \param timeout The maximum time to wait for the robot to confirm the power off command.
110111
*
111-
* \returns true on successful power off, false otherwise.
112+
* \throws urcl::UrException if the command cannot be sent to the robot.
113+
* \throws urcl::TimeoutException if the robot doesn't power off within the given timeout.
112114
*/
113-
bool commandPowerOff(const bool validate = true, const std::chrono::milliseconds timeout = std::chrono::seconds(30));
115+
void commandPowerOff(const bool validate = true, const std::chrono::milliseconds timeout = std::chrono::seconds(30));
114116

115117
/*!
116118
* \brief Commands the robot to release the brakes
@@ -119,9 +121,11 @@ class PrimaryClient
119121
* passed by.
120122
* \param timeout The maximum time to wait for the robot to confirm it is running.
121123
*
122-
* \returns true on successful brake release, false otherwise.
124+
* \throws urcl::UrException if the command cannot be sent to the robot.
125+
* \throws urcl::TimeoutException if the robot doesn't release the brakes within the given
126+
* timeout.
123127
*/
124-
bool commandBrakeRelease(const bool validate = true,
128+
void commandBrakeRelease(const bool validate = true,
125129
const std::chrono::milliseconds timeout = std::chrono::seconds(30));
126130

127131
/*!

src/helpers.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
*/
2727
//----------------------------------------------------------------------
2828

29+
#include <ur_client_library/exceptions.h>
2930
#include <ur_client_library/helpers.h>
3031
#include <ur_client_library/log.h>
3132

@@ -101,19 +102,19 @@ bool setFiFoScheduling(pthread_t& thread, const int priority)
101102
#endif
102103
}
103104

104-
bool waitFor(std::function<bool()> condition, const std::chrono::milliseconds timeout,
105+
void waitFor(std::function<bool()> condition, const std::chrono::milliseconds timeout,
105106
const std::chrono::milliseconds check_interval)
106107
{
107108
auto start_time = std::chrono::system_clock::now();
108109
while (std::chrono::system_clock::now() - start_time < timeout)
109110
{
110111
if (condition())
111112
{
112-
return true;
113+
return;
113114
}
114115
URCL_LOG_DEBUG("Waiting for condition to be met...");
115116
std::this_thread::sleep_for(check_interval);
116117
}
117-
return false;
118+
throw urcl::TimeoutException("Timeout while waiting for condition to be met", timeout);
118119
}
119120
} // namespace urcl

src/primary/primary_client.cpp

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <ur_client_library/primary/primary_client.h>
3232
#include <ur_client_library/primary/robot_message.h>
3333
#include <ur_client_library/primary/robot_state.h>
34+
#include "ur_client_library/exceptions.h"
3435

3536
namespace urcl
3637
{
@@ -160,44 +161,62 @@ bool PrimaryClient::checkCalibration(const std::string& checksum)
160161
return kin_info->toHash() == checksum;
161162
}
162163

163-
bool PrimaryClient::commandPowerOn(const bool validate, const std::chrono::milliseconds timeout)
164+
void PrimaryClient::commandPowerOn(const bool validate, const std::chrono::milliseconds timeout)
164165
{
165166
if (!sendScript("power on"))
166167
{
167-
return false;
168+
throw UrException("Failed to send power on command to robot");
168169
}
169170

170171
if (validate)
171172
{
172-
return waitFor([this]() { return getRobotMode() == RobotMode::IDLE; }, timeout);
173+
try
174+
{
175+
waitFor([this]() { return getRobotMode() == RobotMode::IDLE; }, timeout);
176+
}
177+
catch (const TimeoutException& ex)
178+
{
179+
throw TimeoutException("Robot did not power on within the given timeout", timeout);
180+
}
173181
}
174-
return true;
175182
}
176183

177-
bool PrimaryClient::commandPowerOff(const bool validate, const std::chrono::milliseconds timeout)
184+
void PrimaryClient::commandPowerOff(const bool validate, const std::chrono::milliseconds timeout)
178185
{
179186
if (!sendScript("power off"))
180187
{
181-
return false;
188+
throw UrException("Failed to send power off command to robot");
182189
}
183190
if (validate)
184191
{
185-
return waitFor([this]() { return getRobotMode() == RobotMode::POWER_OFF; }, timeout);
192+
try
193+
{
194+
waitFor([this]() { return getRobotMode() == RobotMode::POWER_OFF; }, timeout);
195+
}
196+
catch (const std::exception&)
197+
{
198+
throw TimeoutException("Robot did not power off within the given timeout", timeout);
199+
}
186200
}
187-
return true;
188201
}
189202

190-
bool PrimaryClient::commandBrakeRelease(const bool validate, const std::chrono::milliseconds timeout)
203+
void PrimaryClient::commandBrakeRelease(const bool validate, const std::chrono::milliseconds timeout)
191204
{
192205
if (!sendScript("set robotmode run"))
193206
{
194-
return false;
207+
throw UrException("Failed to send brake release command to robot");
195208
}
196209
if (validate)
197210
{
198-
return waitFor([this]() { return getRobotMode() == RobotMode::RUNNING; }, timeout);
211+
try
212+
{
213+
waitFor([this]() { return getRobotMode() == RobotMode::RUNNING; }, timeout);
214+
}
215+
catch (const std::exception&)
216+
{
217+
throw TimeoutException("Robot did not release the brakes within the given timeout", timeout);
218+
}
199219
}
200-
return true;
201220
}
202221

203222
} // namespace primary_interface

tests/test_primary_client.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <chrono>
3636
#include <memory>
3737
#include <thread>
38+
#include "ur_client_library/exceptions.h"
3839
#include "ur_client_library/helpers.h"
3940

4041
using namespace urcl;
@@ -83,24 +84,21 @@ TEST_F(PrimaryClientTest, add_and_remove_consumer)
8384
TEST_F(PrimaryClientTest, test_power_cycle_commands)
8485
{
8586
EXPECT_NO_THROW(client_->start());
86-
EXPECT_TRUE(client_->commandPowerOff());
87-
EXPECT_TRUE(client_->commandPowerOn());
88-
EXPECT_TRUE(client_->commandBrakeRelease());
89-
EXPECT_TRUE(client_->commandPowerOff());
90-
EXPECT_TRUE(client_->commandBrakeRelease());
91-
EXPECT_TRUE(client_->commandPowerOff());
87+
EXPECT_NO_THROW(client_->commandPowerOff());
88+
EXPECT_NO_THROW(client_->commandPowerOn());
89+
EXPECT_NO_THROW(client_->commandBrakeRelease());
90+
EXPECT_NO_THROW(client_->commandPowerOff());
91+
EXPECT_NO_THROW(client_->commandBrakeRelease());
92+
EXPECT_NO_THROW(client_->commandPowerOff());
9293

9394
// provoke a timeout
94-
EXPECT_FALSE(client_->commandBrakeRelease(true, std::chrono::milliseconds(1)));
95+
EXPECT_THROW(client_->commandBrakeRelease(true, std::chrono::milliseconds(1)), urcl::TimeoutException);
9596

9697
auto timeout = std::chrono::seconds(30);
97-
waitFor([this]() { return client_->getRobotMode() == RobotMode::RUNNING; }, timeout);
98-
EXPECT_EQ(client_->getRobotMode(), RobotMode::RUNNING);
98+
EXPECT_NO_THROW(waitFor([this]() { return client_->getRobotMode() == RobotMode::RUNNING; }, timeout));
9999

100-
EXPECT_TRUE(client_->commandPowerOff(false));
101-
waitFor([this]() { return client_->getRobotMode() == RobotMode::POWER_OFF; }, timeout);
102-
103-
EXPECT_EQ(client_->getRobotMode(), RobotMode::POWER_OFF);
100+
EXPECT_NO_THROW(client_->commandPowerOff(false));
101+
EXPECT_NO_THROW(waitFor([this]() { return client_->getRobotMode() == RobotMode::POWER_OFF; }, timeout));
104102
}
105103

106104
TEST_F(PrimaryClientTest, test_uninitialized_primary_client)
@@ -122,4 +120,4 @@ int main(int argc, char* argv[])
122120
}
123121

124122
return RUN_ALL_TESTS();
125-
}
123+
}

0 commit comments

Comments
 (0)