@@ -46,18 +46,26 @@ const std::string DEFAULT_ROBOT_IP = "192.168.56.101";
4646const std::string SCRIPT_FILE = " resources/external_control.urscript" ;
4747const std::string OUTPUT_RECIPE = " examples/resources/rtde_output_recipe.txt" ;
4848const std::string INPUT_RECIPE = " examples/resources/rtde_input_recipe.txt" ;
49- const std::string CALIBRATION_CHECKSUM = " calib_12788084448423163542" ;
5049
5150std::unique_ptr<UrDriver> g_my_driver;
5251std::unique_ptr<DashboardClient> g_my_dashboard;
53- bool g_tool_contact_result_triggered;
52+ std::atomic< bool > g_tool_contact_result_triggered;
5453control::ToolContactResult g_tool_contact_result;
54+ std::atomic<bool > g_program_running;
55+ std::condition_variable g_program_running_cv;
56+ std::mutex g_program_running_mutex;
5557
5658// We need a callback function to register. See UrDriver's parameters for details.
5759void handleRobotProgramState (bool program_running)
5860{
5961 // Print the text in green so we see it better
6062 std::cout << " \033 [1;32mProgram running: " << std::boolalpha << program_running << " \033 [0m\n " << std::endl;
63+ g_program_running = program_running;
64+ if (program_running)
65+ {
66+ std::lock_guard<std::mutex> lk (g_program_running_mutex);
67+ g_program_running_cv.notify_one ();
68+ }
6169}
6270
6371void handleToolContactResult (control::ToolContactResult result)
@@ -68,6 +76,17 @@ void handleToolContactResult(control::ToolContactResult result)
6876 g_tool_contact_result_triggered = true ;
6977}
7078
79+ bool waitForProgramRunning (int milliseconds = 100 )
80+ {
81+ std::unique_lock<std::mutex> lk (g_program_running_mutex);
82+ if (g_program_running_cv.wait_for (lk, std::chrono::milliseconds (milliseconds)) == std::cv_status::no_timeout ||
83+ g_program_running == true )
84+ {
85+ return true ;
86+ }
87+ return false ;
88+ }
89+
7190int main (int argc, char * argv[])
7291{
7392 urcl::setLogLevel (urcl::LogLevel::INFO);
@@ -121,68 +140,43 @@ int main(int argc, char* argv[])
121140 URCL_LOG_ERROR (" Could not send BrakeRelease command" );
122141 return 1 ;
123142 }
124-
125143 // Now the robot is ready to receive a program
144+
126145 std::unique_ptr<ToolCommSetup> tool_comm_setup;
127146 const bool headless = true ;
128147 g_my_driver.reset (new UrDriver (robot_ip, SCRIPT_FILE, OUTPUT_RECIPE, INPUT_RECIPE, &handleRobotProgramState, headless,
129- std::move (tool_comm_setup), CALIBRATION_CHECKSUM));
130-
148+ std::move (tool_comm_setup)));
149+ if (!waitForProgramRunning (1000 ))
150+ {
151+ std::cout << " Program did not start running. Is the robot in remote control?" << std::endl;
152+ return 1 ;
153+ }
131154 g_my_driver->registerToolContactResultCallback (&handleToolContactResult);
132-
133- // Once RTDE communication is started, we have to make sure to read from the interface buffer, as
134- // otherwise we will get pipeline overflows. Therefor, do this directly before starting your main
135- // loop.
136- g_my_driver->startRTDECommunication ();
155+ g_my_driver->startToolContact ();
137156
138157 // This will move the robot downward in the z direction of the base until a tool contact is detected or seconds_to_run
139158 // is reached
140- std::chrono::duration<double > time_done (0 );
141- std::chrono::duration<double > timeout (second_to_run);
142- vector6d_t tcp_speed = { 0.0 , 0.0 , -0.02 , 0.0 , 0.0 , 0.0 };
143- auto stopwatch_last = std::chrono::steady_clock::now ();
144- auto stopwatch_now = stopwatch_last;
145- g_my_driver->startToolContact ();
146-
147- while (true )
159+ const vector6d_t tcp_speed = { 0.0 , 0.0 , -0.02 , 0.0 , 0.0 , 0.0 };
160+ auto start_time = std::chrono::system_clock::now ();
161+ while (second_to_run.count () < 0 || (std::chrono::system_clock::now () - start_time) < second_to_run)
148162 {
149- // Read latest RTDE package. This will block for a hard-coded timeout (see UrDriver), so the
150- // robot will effectively be in charge of setting the frequency of this loop.
151- // In a real-world application this thread should be scheduled with real-time priority in order
152- // to ensure that this is called in time.
153- std::unique_ptr<rtde_interface::DataPackage> data_pkg = g_my_driver->getDataPackage ();
154- if (data_pkg)
163+ // Setting the RobotReceiveTimeout time is for example purposes only. This will make the example running more
164+ // reliable on non-realtime systems. Use with caution in productive applications.
165+ bool ret =
166+ g_my_driver->writeJointCommand (tcp_speed, comm::ControlMode::MODE_SPEEDL, RobotReceiveTimeout::millisec (100 ));
167+ if (!ret)
155168 {
156- // Setting the RobotReceiveTimeout time is for example purposes only. This will make the example running more
157- // reliable on non-realtime systems. Use with caution in productive applications.
158- bool ret =
159- g_my_driver->writeJointCommand (tcp_speed, comm::ControlMode::MODE_SPEEDL, RobotReceiveTimeout::millisec (100 ));
160- if (!ret)
161- {
162- URCL_LOG_ERROR (" Could not send joint command. Is the robot in remote control?" );
163- return 1 ;
164- }
165-
166- if (g_tool_contact_result_triggered)
167- {
168- URCL_LOG_INFO (" Tool contact result triggered. Received tool contact result %i." ,
169- toUnderlying (g_tool_contact_result));
170- break ;
171- }
172-
173- if (time_done > timeout && second_to_run.count () != 0 )
174- {
175- URCL_LOG_INFO (" Timed out before reaching tool contact." );
176- break ;
177- }
169+ URCL_LOG_ERROR (" Could not send joint command. Is the robot in remote control?" );
170+ return 1 ;
178171 }
179- else
172+
173+ if (g_tool_contact_result_triggered)
180174 {
181- URCL_LOG_WARN (" Could not get fresh data package from robot" );
175+ URCL_LOG_INFO (" Tool contact detected" );
176+ break ;
182177 }
183-
184- stopwatch_now = std::chrono::steady_clock::now ();
185- time_done += stopwatch_now - stopwatch_last;
186- stopwatch_last = stopwatch_now;
187178 }
179+ URCL_LOG_INFO (" Timed out before reaching tool contact." );
180+ g_my_driver->stopControl ();
181+ return 0 ;
188182}
0 commit comments