@@ -43,17 +43,37 @@ const std::string DEFAULT_ROBOT_IP = "192.168.56.101";
4343const std::string SCRIPT_FILE = " resources/external_control.urscript" ;
4444const std::string OUTPUT_RECIPE = " examples/resources/rtde_output_recipe.txt" ;
4545const std::string INPUT_RECIPE = " examples/resources/rtde_input_recipe.txt" ;
46- const std::string CALIBRATION_CHECKSUM = " calib_12788084448423163542" ;
4746
4847std::unique_ptr<UrDriver> g_my_driver;
4948std::unique_ptr<DashboardClient> g_my_dashboard;
5049vector6d_t g_joint_positions;
5150
51+ std::condition_variable g_program_running_cv;
52+ std::mutex g_program_running_mutex;
53+ bool g_program_running;
54+
5255// We need a callback function to register. See UrDriver's parameters for details.
5356void handleRobotProgramState (bool program_running)
5457{
5558 // Print the text in green so we see it better
5659 std::cout << " \033 [1;32mProgram running: " << std::boolalpha << program_running << " \033 [0m\n " << std::endl;
60+ if (program_running)
61+ {
62+ std::lock_guard<std::mutex> lk (g_program_running_mutex);
63+ g_program_running = program_running;
64+ g_program_running_cv.notify_one ();
65+ }
66+ }
67+
68+ bool waitForProgramRunning (int milliseconds = 100 )
69+ {
70+ std::unique_lock<std::mutex> lk (g_program_running_mutex);
71+ if (g_program_running_cv.wait_for (lk, std::chrono::milliseconds (milliseconds)) == std::cv_status::no_timeout ||
72+ g_program_running == true )
73+ {
74+ return true ;
75+ }
76+ return false ;
5777}
5878
5979int main (int argc, char * argv[])
@@ -109,13 +129,13 @@ int main(int argc, char* argv[])
109129 std::unique_ptr<ToolCommSetup> tool_comm_setup;
110130 const bool headless = true ;
111131 g_my_driver.reset (new UrDriver (robot_ip, SCRIPT_FILE, OUTPUT_RECIPE, INPUT_RECIPE, &handleRobotProgramState, headless,
112- std::move (tool_comm_setup), CALIBRATION_CHECKSUM ));
113-
114- // Once RTDE communication is started, we have to make sure to read from the interface buffer, as
115- // otherwise we will get pipeline overflows. Therefor, do this directly before starting your main
116- // loop.
117-
118- g_my_driver-> startRTDECommunication ();
132+ std::move (tool_comm_setup)));
133+ // Make sure that external control script is running
134+ if (! waitForProgramRunning ())
135+ {
136+ URCL_LOG_ERROR ( " External Control script not running. " );
137+ return 1 ;
138+ }
119139
120140 // Increment depends on robot version
121141 double increment_constant = 0.0005 ;
@@ -130,62 +150,65 @@ int main(int argc, char* argv[])
130150 bool passed_positive_part = false ;
131151 URCL_LOG_INFO (" Start moving the robot" );
132152 urcl::vector6d_t joint_target = { 0 , 0 , 0 , 0 , 0 , 0 };
153+
154+ // Once RTDE communication is started, we have to make sure to read from the interface buffer, as
155+ // otherwise we will get pipeline overflows. Therefor, do this directly before starting your main
156+ // loop.
157+ g_my_driver->startRTDECommunication ();
133158 while (!(passed_positive_part && passed_negative_part))
134159 {
135160 // Read latest RTDE package. This will block for a hard-coded timeout (see UrDriver), so the
136161 // robot will effectively be in charge of setting the frequency of this loop.
137162 // In a real-world application this thread should be scheduled with real-time priority in order
138163 // to ensure that this is called in time.
139164 std::unique_ptr<rtde_interface::DataPackage> data_pkg = g_my_driver->getDataPackage ();
140- if (data_pkg)
165+ if (! data_pkg)
141166 {
142- // Read current joint positions from robot data
143- if (!data_pkg->getData (" actual_q" , g_joint_positions))
144- {
145- // This throwing should never happen unless misconfigured
146- std::string error_msg = " Did not find 'actual_q' in data sent from robot. This should not happen!" ;
147- throw std::runtime_error (error_msg);
148- }
167+ URCL_LOG_WARN (" Could not get fresh data package from robot" );
168+ return 1 ;
169+ }
170+ // Read current joint positions from robot data
171+ if (!data_pkg->getData (" actual_q" , g_joint_positions))
172+ {
173+ // This throwing should never happen unless misconfigured
174+ std::string error_msg = " Did not find 'actual_q' in data sent from robot. This should not happen!" ;
175+ throw std::runtime_error (error_msg);
176+ }
149177
150- if (first_pass)
151- {
152- joint_target = g_joint_positions;
153- first_pass = false ;
154- }
178+ if (first_pass)
179+ {
180+ joint_target = g_joint_positions;
181+ first_pass = false ;
182+ }
155183
156- // Open loop control. The target is incremented with a constant each control loop
157- if (passed_positive_part == false )
158- {
159- increment = increment_constant;
160- if (g_joint_positions[5 ] >= 2 )
161- {
162- passed_positive_part = true ;
163- }
164- }
165- else if (passed_negative_part == false )
184+ // Open loop control. The target is incremented with a constant each control loop
185+ if (passed_positive_part == false )
186+ {
187+ increment = increment_constant;
188+ if (g_joint_positions[5 ] >= 2 )
166189 {
167- increment = -increment_constant;
168- if (g_joint_positions[5 ] <= 0 )
169- {
170- passed_negative_part = true ;
171- }
190+ passed_positive_part = true ;
172191 }
173- joint_target[5 ] += increment;
174- // Setting the RobotReceiveTimeout time is for example purposes only. This will make the example running more
175- // reliable on non-realtime systems. Use with caution in productive applications.
176- bool ret = g_my_driver->writeJointCommand (joint_target, comm::ControlMode::MODE_SERVOJ,
177- RobotReceiveTimeout::millisec (100 ));
178- if (!ret)
192+ }
193+ else if (passed_negative_part == false )
194+ {
195+ increment = -increment_constant;
196+ if (g_joint_positions[5 ] <= 0 )
179197 {
180- URCL_LOG_ERROR (" Could not send joint command. Is the robot in remote control?" );
181- return 1 ;
198+ passed_negative_part = true ;
182199 }
183- URCL_LOG_DEBUG (" data_pkg:\n %s" , data_pkg->toString ().c_str ());
184200 }
185- else
201+ joint_target[5 ] += increment;
202+ // Setting the RobotReceiveTimeout time is for example purposes only. This will make the example running more
203+ // reliable on non-realtime systems. Use with caution in productive applications.
204+ bool ret = g_my_driver->writeJointCommand (joint_target, comm::ControlMode::MODE_SERVOJ,
205+ RobotReceiveTimeout::millisec (100 ));
206+ if (!ret)
186207 {
187- URCL_LOG_WARN (" Could not get fresh data package from robot" );
208+ URCL_LOG_ERROR (" Could not send joint command. Is the robot in remote control?" );
209+ return 1 ;
188210 }
211+ URCL_LOG_DEBUG (" data_pkg:\n %s" , data_pkg->toString ().c_str ());
189212 }
190213 g_my_driver->stopControl ();
191214 URCL_LOG_INFO (" Movement done" );
0 commit comments