Skip to content

Commit 33fe70c

Browse files
committed
Allow canceling an instruction
1 parent dafaedf commit 33fe70c

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed

include/ur_client_library/ur/instruction_executor.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,35 @@ class InstructionExecutor
9292
bool moveL(const urcl::Pose& target, const double acceleration = 1.4, const double velocity = 1.04,
9393
const double time = 0, const double blend_radius = 0);
9494

95+
/**
96+
* \brief Cancel the current motion.
97+
*
98+
* If no motion is running, false will be returned.
99+
* If a motion is running, it will be canceled and it will wait for a TRAJECTORY_CANCELED result
100+
* with a timeout of one second.
101+
*
102+
* If another result or no result is received, false will be returned.
103+
*/
104+
bool cancelMotion();
105+
106+
/**
107+
* \brief Check if a trajectory is currently running.
108+
*/
109+
bool isTrajectoryRunning() const
110+
{
111+
return trajectory_running_;
112+
}
113+
95114
private:
96115
void trajDoneCallback(const urcl::control::TrajectoryResult& result);
97116
void trajDisconnectCallback(const int filedescriptor);
98117
std::shared_ptr<urcl::UrDriver> driver_;
99118
std::atomic<bool> trajectory_running_ = false;
119+
std::atomic<bool> cancel_requested_ = false;
100120
std::mutex trajectory_result_mutex_;
121+
std::condition_variable trajectory_done_cv_;
101122
urcl::control::TrajectoryResult trajectory_result_;
102123
};
103124
} // namespace urcl
104125

105-
#endif // UR_CLIENT_LIBRARY_INSTRUCTION_EXECUTOR_H_INCLUDED
126+
#endif // UR_CLIENT_LIBRARY_INSTRUCTION_EXECUTOR_H_INCLUDED

src/ur/instruction_executor.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
// -- END LICENSE BLOCK ------------------------------------------------
3030

3131
#include "ur_client_library/ur/instruction_executor.h"
32+
#include <mutex>
3233
#include "ur_client_library/control/trajectory_point_interface.h"
3334
void urcl::InstructionExecutor::trajDoneCallback(const urcl::control::TrajectoryResult& result)
3435
{
36+
URCL_LOG_DEBUG("Trajectory result received: %s", control::trajectoryResultToString(result).c_str());
3537
std::unique_lock<std::mutex> lock(trajectory_result_mutex_);
3638
trajectory_result_ = result;
3739
trajectory_running_ = false;
@@ -40,6 +42,7 @@ void urcl::InstructionExecutor::trajDisconnectCallback(const int filedescriptor)
4042
{
4143
URCL_LOG_INFO("Trajectory disconnect");
4244
std::unique_lock<std::mutex> lock(trajectory_result_mutex_);
45+
trajectory_done_cv_.notify_all();
4346
if (trajectory_running_)
4447
{
4548
trajectory_result_ = urcl::control::TrajectoryResult::TRAJECTORY_RESULT_FAILURE;
@@ -86,17 +89,20 @@ bool urcl::InstructionExecutor::executeMotion(
8689
}
8790
}
8891
trajectory_running_ = true;
92+
cancel_requested_ = false;
8993

90-
while (trajectory_running_)
94+
while (trajectory_running_ && !cancel_requested_)
9195
{
92-
std::this_thread::sleep_for(std::chrono::milliseconds(100));
9396
driver_->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP);
97+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
9498
}
99+
if (!cancel_requested_)
95100
{
96101
std::unique_lock<std::mutex> lock(trajectory_result_mutex_);
97102
URCL_LOG_INFO("Trajectory done with result %s", control::trajectoryResultToString(trajectory_result_).c_str());
98103
return trajectory_result_ == urcl::control::TrajectoryResult::TRAJECTORY_RESULT_SUCCESS;
99104
}
105+
return false;
100106
}
101107
bool urcl::InstructionExecutor::moveJ(const urcl::vector6d_t& target, const double acceleration, const double velocity,
102108
const double time, const double blend_radius)
@@ -110,3 +116,19 @@ bool urcl::InstructionExecutor::moveL(const urcl::Pose& target, const double acc
110116
return executeMotion({ std::make_shared<control::MoveLPrimitive>(
111117
target, blend_radius, std::chrono::milliseconds(static_cast<int>(time * 1000)), acceleration, velocity) });
112118
}
119+
120+
bool urcl::InstructionExecutor::cancelMotion()
121+
{
122+
cancel_requested_ = true;
123+
if (trajectory_running_)
124+
{
125+
URCL_LOG_INFO("Cancel motion");
126+
driver_->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_CANCEL);
127+
std::unique_lock<std::mutex> lock(trajectory_result_mutex_);
128+
if (trajectory_done_cv_.wait_for(lock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout)
129+
{
130+
return trajectory_result_ == urcl::control::TrajectoryResult::TRAJECTORY_RESULT_CANCELED;
131+
}
132+
}
133+
return false;
134+
}

tests/test_instruction_executor.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,27 @@ TEST_F(InstructionExecutorTest, unfeasible_movej_target_results_in_failure)
219219
ASSERT_FALSE(executor_->moveJ({ -123, 0, 0, 0, 0, 0 }));
220220
}
221221

222+
TEST_F(InstructionExecutorTest, canceling_without_running_trajectory_returns_false)
223+
{
224+
ASSERT_FALSE(executor_->isTrajectoryRunning());
225+
ASSERT_FALSE(executor_->cancelMotion());
226+
}
227+
228+
TEST_F(InstructionExecutorTest, canceling_with_running_trajectory_succeeds)
229+
{
230+
ASSERT_TRUE(executor_->moveJ({ -1.59, -1.72, -2.2, -0.8, 1.6, 0.2 }, 2.0, 2.0));
231+
std::thread move_thread([this]() { executor_->moveJ({ -1.57, -1.6, 1.6, -0.7, 0.7, 2.7 }); });
232+
bool is_trajectory_running = false;
233+
std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
234+
while (!is_trajectory_running || std::chrono::steady_clock::now() > start + std::chrono::seconds(5))
235+
{
236+
is_trajectory_running = executor_->isTrajectoryRunning();
237+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
238+
}
239+
ASSERT_TRUE(executor_->cancelMotion());
240+
move_thread.join();
241+
}
242+
222243
TEST_F(InstructionExecutorTest, unfeasible_movel_target_results_in_failure)
223244
{
224245
// move to a feasible starting pose

0 commit comments

Comments
 (0)