@@ -43,17 +43,37 @@ const std::string DEFAULT_ROBOT_IP = "192.168.56.101";
43
43
const std::string SCRIPT_FILE = " resources/external_control.urscript" ;
44
44
const std::string OUTPUT_RECIPE = " examples/resources/rtde_output_recipe.txt" ;
45
45
const std::string INPUT_RECIPE = " examples/resources/rtde_input_recipe.txt" ;
46
- const std::string CALIBRATION_CHECKSUM = " calib_12788084448423163542" ;
47
46
48
47
std::unique_ptr<UrDriver> g_my_driver;
49
48
std::unique_ptr<DashboardClient> g_my_dashboard;
50
49
vector6d_t g_joint_positions;
51
50
51
+ std::condition_variable g_program_running_cv;
52
+ std::mutex g_program_running_mutex;
53
+ bool g_program_running;
54
+
52
55
// We need a callback function to register. See UrDriver's parameters for details.
53
56
void handleRobotProgramState (bool program_running)
54
57
{
55
58
// Print the text in green so we see it better
56
59
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 ;
57
77
}
58
78
59
79
int main (int argc, char * argv[])
@@ -109,13 +129,13 @@ int main(int argc, char* argv[])
109
129
std::unique_ptr<ToolCommSetup> tool_comm_setup;
110
130
const bool headless = true ;
111
131
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
+ }
119
139
120
140
// Increment depends on robot version
121
141
double increment_constant = 0.0005 ;
@@ -130,62 +150,65 @@ int main(int argc, char* argv[])
130
150
bool passed_positive_part = false ;
131
151
URCL_LOG_INFO (" Start moving the robot" );
132
152
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 ();
133
158
while (!(passed_positive_part && passed_negative_part))
134
159
{
135
160
// Read latest RTDE package. This will block for a hard-coded timeout (see UrDriver), so the
136
161
// robot will effectively be in charge of setting the frequency of this loop.
137
162
// In a real-world application this thread should be scheduled with real-time priority in order
138
163
// to ensure that this is called in time.
139
164
std::unique_ptr<rtde_interface::DataPackage> data_pkg = g_my_driver->getDataPackage ();
140
- if (data_pkg)
165
+ if (! data_pkg)
141
166
{
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
+ }
149
177
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
+ }
155
183
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 )
166
189
{
167
- increment = -increment_constant;
168
- if (g_joint_positions[5 ] <= 0 )
169
- {
170
- passed_negative_part = true ;
171
- }
190
+ passed_positive_part = true ;
172
191
}
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 )
179
197
{
180
- URCL_LOG_ERROR (" Could not send joint command. Is the robot in remote control?" );
181
- return 1 ;
198
+ passed_negative_part = true ;
182
199
}
183
- URCL_LOG_DEBUG (" data_pkg:\n %s" , data_pkg->toString ().c_str ());
184
200
}
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)
186
207
{
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 ;
188
210
}
211
+ URCL_LOG_DEBUG (" data_pkg:\n %s" , data_pkg->toString ().c_str ());
189
212
}
190
213
g_my_driver->stopControl ();
191
214
URCL_LOG_INFO (" Movement done" );
0 commit comments