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:
@@ -1094,6 +1106,52 @@ TEST_F(SplineInterpolationTest, physically_unfeasible_trajectory_quintic_spline)
10941106 }
10951107}
10961108
1109+ TEST_F (SplineInterpolationTest, switching_control_mode_without_trajectory_produces_no_result)
1110+ {
1111+ // We start by putting the robot into trajectory control mode
1112+ ASSERT_TRUE (
1113+ g_my_robot->ur_driver_ ->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP));
1114+
1115+ // Then we switch to idle
1116+ ASSERT_TRUE (g_my_robot->ur_driver_ ->writeKeepalive (RobotReceiveTimeout::sec (2 )));
1117+
1118+ EXPECT_FALSE (waitForTrajectoryResult (std::chrono::milliseconds (500 )));
1119+ }
1120+
1121+ TEST_F (SplineInterpolationTest, switching_control_mode_with_trajectory_produces_result)
1122+ {
1123+ g_my_robot->stopConsumingRTDEData ();
1124+ std::unique_ptr<rtde_interface::DataPackage> data_pkg;
1125+ g_my_robot->readDataPackage (data_pkg);
1126+
1127+ urcl::vector6d_t joint_positions_before;
1128+ ASSERT_TRUE (data_pkg->getData (" target_q" , joint_positions_before));
1129+
1130+ // Start consuming rtde packages to avoid pipeline overflows while testing that the control script aborts correctly
1131+ g_my_robot->startConsumingRTDEData ();
1132+ // Create a trajectory that cannot be executed within the robots limits
1133+ std::vector<urcl::vector6d_t > s_pos, s_vel, s_acc;
1134+ urcl::vector6d_t first_point = {
1135+ joint_positions_before[0 ], joint_positions_before[1 ], joint_positions_before[2 ],
1136+ joint_positions_before[3 ], joint_positions_before[4 ], joint_positions_before[5 ] + 0.5
1137+ };
1138+ s_pos.push_back (first_point);
1139+
1140+ urcl::vector6d_t zeros = { 0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 };
1141+ s_vel.push_back (zeros);
1142+ s_acc.push_back (zeros);
1143+
1144+ std::vector<double > s_time = { 0.02 };
1145+ sendTrajectory (s_pos, s_vel, s_acc, s_time);
1146+ g_my_robot->ur_driver_ ->writeTrajectoryControlMessage (urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP, -1 ,
1147+ RobotReceiveTimeout::off ());
1148+
1149+ // Then we switch to idle
1150+ ASSERT_TRUE (g_my_robot->ur_driver_ ->writeKeepalive (RobotReceiveTimeout::sec (2 )));
1151+
1152+ EXPECT_TRUE (waitForTrajectoryResult (std::chrono::milliseconds (500 )));
1153+ }
1154+
10971155int main (int argc, char * argv[])
10981156{
10991157 ::testing::InitGoogleTest (&argc, argv);
0 commit comments