3636#include < ur_client_library/ur/ur_driver.h>
3737#include < ur_client_library/types.h>
3838
39+ #include < chrono>
3940#include < iostream>
4041#include < memory>
4142#include < math.h>
@@ -56,10 +57,15 @@ bool g_HEADLESS = true;
5657std::unique_ptr<ExampleRobotWrapper> g_my_robot;
5758
5859bool g_trajectory_running;
60+ std::condition_variable g_trajectory_result_cv;
61+ std::mutex g_trajectory_result_mutex;
5962control::TrajectoryResult g_trajectory_result;
6063void handleTrajectoryState (control::TrajectoryResult state)
6164{
65+ std::lock_guard<std::mutex> lk (g_trajectory_result_mutex);
66+ g_trajectory_result_cv.notify_one ();
6267 g_trajectory_result = state;
68+ URCL_LOG_INFO (" Received trajectory result %s" , control::trajectoryResultToString (state).c_str ());
6369 g_trajectory_running = false ;
6470}
6571
@@ -74,6 +80,12 @@ bool nearlyEqual(double a, double b, double eps = 1e-15)
7480 return c < eps || -c < eps;
7581}
7682
83+ bool waitForTrajectoryResult (std::chrono::milliseconds timeout)
84+ {
85+ std::unique_lock<std::mutex> lk (g_trajectory_result_mutex);
86+ return g_trajectory_result_cv.wait_for (lk, timeout) == std::cv_status::no_timeout;
87+ }
88+
7789class SplineInterpolationTest : public ::testing::Test
7890{
7991protected:
@@ -1085,6 +1097,52 @@ TEST_F(SplineInterpolationTest, physically_unfeasible_trajectory_quintic_spline)
10851097 }
10861098}
10871099
1100+ TEST_F (SplineInterpolationTest, switching_control_mode_without_trajectory_produces_no_result)
1101+ {
1102+ // We start by putting the robot into trajectory control mode
1103+ ASSERT_TRUE (
1104+ g_my_robot->ur_driver_ ->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP));
1105+
1106+ // Then we switch to idle
1107+ ASSERT_TRUE (g_my_robot->ur_driver_ ->writeKeepalive (RobotReceiveTimeout::sec (2 )));
1108+
1109+ EXPECT_FALSE (waitForTrajectoryResult (std::chrono::milliseconds (500 )));
1110+ }
1111+
1112+ TEST_F (SplineInterpolationTest, switching_control_mode_with_trajectory_produces_result)
1113+ {
1114+ g_my_robot->stopConsumingRTDEData ();
1115+ std::unique_ptr<rtde_interface::DataPackage> data_pkg;
1116+ g_my_robot->readDataPackage (data_pkg);
1117+
1118+ urcl::vector6d_t joint_positions_before;
1119+ ASSERT_TRUE (data_pkg->getData (" target_q" , joint_positions_before));
1120+
1121+ // Start consuming rtde packages to avoid pipeline overflows while testing that the control script aborts correctly
1122+ g_my_robot->startConsumingRTDEData ();
1123+ // Create a trajectory that cannot be executed within the robots limits
1124+ std::vector<urcl::vector6d_t > s_pos, s_vel, s_acc;
1125+ urcl::vector6d_t first_point = {
1126+ joint_positions_before[0 ], joint_positions_before[1 ], joint_positions_before[2 ],
1127+ joint_positions_before[3 ], joint_positions_before[4 ], joint_positions_before[5 ] + 0.5
1128+ };
1129+ s_pos.push_back (first_point);
1130+
1131+ urcl::vector6d_t zeros = { 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 };
1132+ s_vel.push_back (zeros);
1133+ s_acc.push_back (zeros);
1134+
1135+ std::vector<double > s_time = { 0.02 };
1136+ sendTrajectory (s_pos, s_vel, s_acc, s_time);
1137+ g_my_robot->ur_driver_ ->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP, -1 ,
1138+ RobotReceiveTimeout::off ());
1139+
1140+ // Then we switch to idle
1141+ ASSERT_TRUE (g_my_robot->ur_driver_ ->writeKeepalive (RobotReceiveTimeout::sec (2 )));
1142+
1143+ EXPECT_TRUE (waitForTrajectoryResult (std::chrono::milliseconds (500 )));
1144+ }
1145+
10881146int main (int argc, char * argv[])
10891147{
10901148 ::testing::InitGoogleTest (&argc, argv);
0 commit comments