AUV-Coop-Assembly
Master Thesis for Robotics Engineering. Cooperative peg-in-hole assembly with two underwater vehicles guided by vision
coordinator.cpp
1 #include "header/coordinator.h"
2 
3 
4 int main(int argc, char **argv){
5 
6  if (argc < 3){
7  std::cout << "[COORDINATOR] Please insert the two robots name"
8  << std::endl;
9  return -1;
10  }
11  std::string robotNameA = argv[1];
12  std::string robotNameB = argv[2];
13  std::string pathLog;
14  if (LOG && (argc > 3)){ //if flag log setted to 1 and path log is given
15  pathLog = argv[3];
16  }
17 
18  bool readyBothRob = false;
19 
20  ros::init (argc, argv, "Coordinator");
21  std::cout << "[COORDINATOR] Start" << std::endl;
22  ros::NodeHandle nh;
23 
24  // world interface needed to find peg position to calculate barX_t (reference that brings tool in goal)
25  std::string toolName = "g500_A/pegHead";
26  std::string toolName2 = "g500_B/pegHead";
27  WorldInterface worldInterface("COORDINATOR");
28  worldInterface.waitReady(toolName);
29  worldInterface.waitReady(toolName2);
30  Eigen::Matrix4d wTt;
31  worldInterface.getwT(&wTt, toolName);
32 
33 
34 
36  //double goalLinearVectTool[] = {-0.27, -0.102, 2.124};
37  double goalLinearVectToolTrue[] = {0.9999999999999999, -9.999999999999998, 8.378840300977453};
38  double goalLinearVectTool[] = {0.9999999999999999, -9.999999999999998, 8.378840300977453}; //with error
39 
40  std::vector<double> eulRadTrue = {0, 0, -1.443185307179587}; //true angular
41  std::vector<double> eulRad = {0, 0, -1.443185307179587}; //with error on z: 0.1rad ~ 6deg
42 
43  Eigen::Matrix4d wTgoalTool_eigen = Eigen::Matrix4d::Identity();
44 
46 // wTgoalTool_eigen.topLeftCorner<3,3>() << 0, 1, 0,
47 // -1, 0, 0,
48 // 0, 0, 1;
49  //wTgoalTool_eigen.topLeftCorner<3,3>() = wTt.topLeftCorner<3,3>(); //actual goal = actual rotation
50  wTgoalTool_eigen.topLeftCorner<3,3>() = FRM::eul2Rot(eulRad);
51 
52  //to get inside the hole of 0.2m:
53  Eigen::Vector3d v_inside;
54  //v_inside << 0.40, 0.18, 0; //rigth big hole + error
55  v_inside << 0.20, 0, 0;
56  Eigen::Vector3d w_inside = FRM::eul2Rot(eulRadTrue) * v_inside;
57 
59  wTgoalTool_eigen(0, 3) = goalLinearVectTool[0] + w_inside(0);
60  wTgoalTool_eigen(1, 3) = goalLinearVectTool[1] + w_inside(1);
61  wTgoalTool_eigen(2, 3) = goalLinearVectTool[2] + w_inside(2);
62 
63  Eigen::Matrix4d wTgoalTool_ideal; //the perfect goal for log purpose
64  wTgoalTool_ideal.topLeftCorner<3,3>() = FRM::eul2Rot(eulRadTrue);
65  wTgoalTool_ideal(0, 3) = goalLinearVectToolTrue[0] + w_inside(0);
66  wTgoalTool_ideal(1, 3) = goalLinearVectToolTrue[1] + w_inside(1);
67  wTgoalTool_ideal(2, 3) = goalLinearVectToolTrue[2] + w_inside(2);
68 
69 
70 
71  CoordInterfaceCoord coordInterface(nh, robotNameA, robotNameB);
72  Eigen::Matrix<double, VEHICLE_DOF, 1> nonCoopCartVelA_eigen;
73  Eigen::Matrix<double, VEHICLE_DOF, VEHICLE_DOF> admisVelToolA_eigen;
74  Eigen::Matrix<double, VEHICLE_DOF, 1> nonCoopCartVelB_eigen;
75  Eigen::Matrix<double, VEHICLE_DOF, VEHICLE_DOF> admisVelToolB_eigen;
76  Eigen::Matrix<double, VEHICLE_DOF, 1> refTool;
77  Eigen::Matrix<double, VEHICLE_DOF, 1> coopVelToolFeasible;
78  Eigen::Vector3d forcePegTip;
79  Eigen::Vector3d torquePegTip;
80  double changeMagnitude = 0.0005; //gain for change the goals according to force arrived
81  //double changeMagnitudeAng = 0.0001;
82 
84  Logger logger;
85  if (pathLog.size() > 0){
86  logger = Logger("Coordinator", pathLog);
87  logger.createDirectoryForNode();
88  }
89 
90 
91  /************ WAIT FOR VISION ROBOT AND TAKE HOLE POSE FROM IT *******************************/
92  if (VISION_ON){ //if active, also change goal must be active
93 
94  double msVisio = 100;
95  boost::asio::io_service ioVisio;
96  std::cout << "[COORDINATOR] Wating for Vision Robot giving Hole's Pose...\n";
97 
98  VisionInterfaceCoord visionInterface(nh, "COORDINATOR");
99  while (0 != visionInterface.getHoleTransform(&(wTgoalTool_eigen))){
100  boost::asio::deadline_timer loopRater(ioVisio, boost::posix_time::milliseconds(msVisio));
101  ros::spinOnce();
102  loopRater.wait(); //wait for msVisio millisec
103  }
104 
105  std::cout <<"[COORDINATOR] arrived wThole: " << wTgoalTool_eigen << "\n";
106 
107  // it is overwritten previous wTgoal, but
108  // vision give wThole, the goal is inside of 20 cm of it
109  // note that w_inside is calculated from ideal wRhole
110  wTgoalTool_eigen(0, 3) += w_inside(0);
111  wTgoalTool_eigen(1, 3) += w_inside(1);
112  wTgoalTool_eigen(2, 3) += w_inside(2);
113 
114  }
115 
116  /************************************************************************************************/
117 
118 
119 
120  /*********************************** MAIN LOOP*****************************************************/
121 
122  int ms = MS_CONTROL_LOOP;
123  boost::asio::io_service io;
124 
125  while(ros::ok()){
126 
127  while(!(readyBothRob)){ //wait until both ready, meanwhile publish false to make no robot start
128  boost::asio::deadline_timer loopRater(io, boost::posix_time::milliseconds(ms));
129  coordInterface.publishStartBoth(false);
130  coordInterface.publishUpdatedGoal(wTgoalTool_eigen);
131 
132  readyBothRob = coordInterface.getReadyBothRob();
133  ros::spinOnce();
134  loopRater.wait();
135  }
136 
137  std::cout << "[COORDINATOR] Now both robot are ready" << std::endl;
138 
139  while(readyBothRob){
140  boost::asio::deadline_timer loopRater(io, boost::posix_time::milliseconds(ms));
141  coordInterface.publishStartBoth(true);
142 
143  worldInterface.getwT(&wTt, toolName);
144 
146  if (CHANGE_GOAL){ //if active, calculate and modify joint command accordingly
147 
148  coordInterface.getForceTorque(&forcePegTip, &torquePegTip);
149  //std::cout << "force:\n" << forcePegTip << "\n torques:\n" << torquePegTip << "\n";
150 
151  if (forcePegTip.norm() > 0 || torquePegTip.norm() > 0) {
152  wTgoalTool_eigen = changeGoalLin(changeMagnitude, forcePegTip, wTgoalTool_eigen);
153  //wTgoalTool_eigen = changeGoalAng(changeMagnitudeAng, forcePegTip, wTt.topLeftCorner<3,3>(), wTgoalTool_eigen);
154 
155 
156  coordInterface.publishUpdatedGoal(wTgoalTool_eigen);
157 
159  //std::cout << "Goal modified:\n";
160  //std::cout << wTgoalTool_eigen;
161  //std::cout << "\n\n";
162  }
163  }
165 
166  //if at least one did not arrive, repeat loop, but call each get only once (this is done inside methods class interface)
167  int returned = 1;
168  while (returned > 0){
169  returned = coordInterface.getMatricesFromRobs(&nonCoopCartVelA_eigen, &nonCoopCartVelB_eigen, &admisVelToolA_eigen, &admisVelToolB_eigen);
170  if (returned == -1){
171  std::cout << "[COORDINATOR] ERROR in the dimension of mesage arrived from robots" << std::endl;
172  return -1;
173  }
174  if (returned == -2){
175  std::cout << "[COORDINATOR] ERROR in the name of robots" << std::endl;
176  return -1;
177  }
178 
179  boost::asio::deadline_timer loopRater(io, boost::posix_time::milliseconds(1));
180  ros::spinOnce();
181  loopRater.wait();
182  }
183 
184 
185 // std::cout << nonCoopCartVelA_eigen << "\n\n";
186 // std::cout << admisVelToolA_eigen << "\n\n";
187 // std::cout << nonCoopCartVelB_eigen << "\n\n";
188 // std::cout << admisVelToolB_eigen << "\n\n";
189 
190  worldInterface.getwT(&wTt, toolName);
191  refTool = calculateRefTool(wTgoalTool_eigen, wTt);
192  coopVelToolFeasible = execCoordAlgo(nonCoopCartVelA_eigen, admisVelToolA_eigen,
193  nonCoopCartVelB_eigen, admisVelToolB_eigen,
194  refTool, &logger);
195 
196  std::cout << "Cooperative Tool Velocity\n[x y z w_x w_y w_z]:\n" << coopVelToolFeasible << "\n";
197 
198  coordInterface.publishCoopVel(coopVelToolFeasible);
199 
200 
202 
203  CMAT::TransfMatrix wTtool_cmat = CONV::matrix_eigen2cmat(wTt);
204  CMAT::TransfMatrix wTgoalTool_ideal_cmat = CONV::matrix_eigen2cmat(wTgoalTool_ideal);
205  CMAT::Vect6 errorSwapped = CMAT::CartError(wTgoalTool_ideal_cmat, wTtool_cmat);//ang;lin
206  // ang and lin must be swapped because in yDot and jacob linear part is before
207 
208  Eigen::Matrix<double, VEHICLE_DOF, 1> error;
209  error(0) = errorSwapped(4);
210  error(1) = errorSwapped(5);
211  error(2) = errorSwapped(6);
212  error(3) = errorSwapped(1);
213  error(4) = errorSwapped(2);
214  error(5) = errorSwapped(3);
215  if (pathLog.size() != 0){
216  Eigen::Matrix4d wTt2;
217  worldInterface.getwT(&wTt2, toolName2);
218  //logger.logCartError(wTt, wTt2, "stressTool");
219  logger.logNumbers(wTgoalTool_eigen, "wTgoal");
220  logger.logNumbers(wTt, "wTt");
221  logger.logNumbers(error, "realgoal_Tool_error");
222  }
223 
224  readyBothRob = coordInterface.getReadyBothRob();
225  ros::spinOnce();
226  loopRater.wait();
227  }
228 
229  std::cout << "[COORDINATOR] Now one robot is not ready anymore" << std::endl;
230 
231  }
232 
233 }
234 
235 Eigen::Matrix<double, VEHICLE_DOF, 1> execCoordAlgo(
236  Eigen::Matrix<double, VEHICLE_DOF, 1> nonCoopCartVelA_eigen,
237  Eigen::Matrix<double, VEHICLE_DOF, VEHICLE_DOF> admisVelToolA_eigen,
238  Eigen::Matrix<double, VEHICLE_DOF, 1> nonCoopCartVelB_eigen,
239  Eigen::Matrix<double, VEHICLE_DOF, VEHICLE_DOF> admisVelToolB_eigen,
240  Eigen::Matrix<double, VEHICLE_DOF, 1> refTool,
241  Logger* logger){
242 
243  double muZero = 1; //this is only to not divide by zero?
244 
245  // weights to understand the "difficulty" each robot has in following the ideal reference(refTool)
246  double muA = muZero + ((refTool-nonCoopCartVelA_eigen).norm());
247  double muB = muZero + ((refTool-nonCoopCartVelB_eigen).norm());
248 
249  //xHatDot_tool
250  Eigen::Matrix<double, VEHICLE_DOF, 1> coopVelTool;
251  coopVelTool = (1 / (muA + muB)) *
252  ( (muA * nonCoopCartVelA_eigen) + (muB * nonCoopCartVelB_eigen) );
253 
254  // C
255  Eigen::Matrix<double, VEHICLE_DOF, VEHICLE_DOF> constraintMat;
256  constraintMat = (admisVelToolA_eigen - admisVelToolB_eigen);
257 
258  //xTildeDot_tool
259  Eigen::Matrix<double, VEHICLE_DOF, 1> coopVelToolFeasible;
260  Eigen::Matrix<double, VEHICLE_DOF, VEHICLE_DOF> eye =
261  Eigen::Matrix<double, VEHICLE_DOF, VEHICLE_DOF>::Identity();
262 
263  coopVelToolFeasible = ( eye - (FRM::pseudoInverse(constraintMat) * constraintMat) )
264  * coopVelTool;
265 
266  if (logger != NULL){
267  logger->logNumbers(muA, "weightA");
268  logger->logNumbers(muB, "weightB");
269  logger->logNumbers(coopVelTool, "notFeasibleCoopVel");
270  logger->logNumbers(nonCoopCartVelA_eigen, "nonCoopVelg500_A");
271  logger->logNumbers(nonCoopCartVelB_eigen, "nonCoopVelg500_B");
272  logger->logNumbers(coopVelToolFeasible, "coopVel");
273  logger->logNumbers(refTool, "idealTool");
274  }
275 
276  return coopVelToolFeasible;
277 }
278 
279 
280 Eigen::Matrix<double, VEHICLE_DOF, 1> calculateRefTool(Eigen::Matrix4d wTgoaltool_eigen,
281  Eigen::Matrix4d wTtool_eigen){
282 
283  CMAT::TransfMatrix wTgoaltool_cmat = CONV::matrix_eigen2cmat(wTgoaltool_eigen);
284  CMAT::TransfMatrix wTtool_cmat = CONV::matrix_eigen2cmat(wTtool_eigen);
285 
286  //double gain = 0.5; GAIN E SATURAZ??
287  CMAT::Vect6 errorSwapped = CMAT::CartError(wTgoaltool_cmat, wTtool_cmat);//ang;lin
288  // ang and lin must be swapped because in yDot and jacob linear part is before
289 
290 
291  Eigen::Matrix<double, VEHICLE_DOF, 1> reference;
292  double gainLin = 0.05;
293  double gainAng = 0.08;
294  reference(0) = gainLin*errorSwapped(4);
295  reference(1) = gainLin*errorSwapped(5);
296  reference(2) = gainLin*errorSwapped(6);
297  reference(3) = gainAng*errorSwapped(1);
298  reference(4) = gainAng*errorSwapped(2);
299  reference(5) = gainAng*errorSwapped(3);
300 
301 
302  reference.topRows(3) = FRM::saturateVectorEigen(reference.topRows(3), 0.1);
303  reference.bottomRows(3) = FRM::saturateVectorEigen(reference.bottomRows(3), 0.1);
304 
305 
306  return reference;
307 
308 }
309 
310 Eigen::Matrix4d changeGoalLin(double gain, Eigen::Vector3d forcePegTip, Eigen::Matrix4d wTgoalTool_eigen){
311 
312  if (forcePegTip(1) != 0 || forcePegTip(2) != 0) {
313  Eigen::Vector3d tchange;
314  Eigen::Vector3d wChange;
315 
316  tchange << gain*forcePegTip;
317  tchange(0) = 0; //nullified modification on x axis (x axis of tool)
318  wChange = wTgoalTool_eigen.topLeftCorner<3,3>() * tchange;
319  wChange = FRM::saturateVectorEigen(wChange, 0.0007); //orig 0.0005
320 
321  wTgoalTool_eigen.topRightCorner<3,1>() += wChange;
322  }
323 
324  return wTgoalTool_eigen;
325 }
326 
327 
328 
329 
330 
333 Eigen::Matrix4d changeGoalAng(double gain, Eigen::Vector3d torquePegTip,
334  Eigen::Matrix3d wRt_eigen, Eigen::Matrix4d wTgoalTool_eigen){
335 
337  if (torquePegTip(1) != 0 || torquePegTip(2) != 0) {
338 
339  double dt = 0.1; //frequency of arrived sensor info is 10 hz
340  Eigen::Vector3d w_angVel; //angular vel of new goal respect old goal projected on frame old goal
341  //torquePegTip(0) = 0; //nullified modification on x axis (x axis of tool)
342 
343  //integrating torque (it should be multiplied by dt first (integration)
344  // but I "include" dt in the gain. So gain must be less than dt. Multiply also for gain and not
345  // only by dt is necessary to reduce the intensity of the torque (as done in previous function for forces)
346  w_angVel = gain * (wRt_eigen * torquePegTip); //torque is respect to the tool
347  w_angVel = FRM::saturateVectorEigen(w_angVel, 0.0001);
348 
349  CMAT::RotMatrix wRg_cmat = CONV::matrix_eigen2cmat(wTgoalTool_eigen.topLeftCorner<3,3>());
350  //Strap down: Out = e^[wdt^] * gRnewg_0_cmat
351  CMAT::RotMatrix wRnewg = wRg_cmat.StrapDown(CONV::matrix_eigen2cmat(w_angVel), dt);
352 
354 // std::cout << "DEBug:\n torquePegTip:\n" << torquePegTip << "\n w_angVel\n:" << w_angVel << "\n wRnewg:\n";
355 // wRnewg.PrintMtx();
356 // std::cout << "angleAxis: \n";
357 // CMAT::Vect3 vec = CONV::matrix_eigen2cmat(w_angVel);
358 // vec.AngleAxis().PrintMtx();
359 // std::cout << std::endl;
360 
361  wTgoalTool_eigen.topLeftCorner<3,3>() = CONV::matrix_cmat2eigen(wRnewg);
362  }
363 
364  return wTgoalTool_eigen;
365 }
366 
367 
369 //Eigen::Matrix4d changeGoalAng(double gain, Eigen::Vector3d torquePegTip,
370 // Eigen::Matrix3d wRt_eigen, Eigen::Matrix4d wTgoalTool_eigen){
371 
372 // /// angular part TO ASK IF RIGHT TODO
373 // if (torquePegTip(1) != 0 || torquePegTip(2) != 0) {
374 
375 // double dt = 0.1; //frequency of arrived sensor info is 10 hz
376 // Eigen::Matrix3d gRt = (wTgoalTool_eigen.topLeftCorner<3,3>().transpose()) * (wRt_eigen);
377 // Eigen::Vector3d g_angVel; //angular vel of new goal respect old goal projected on frame old goal
378 
379 // torquePegTip(0) = 0; //nullified modification on x axis (x axis of tool)
380 
381 // //integrating torque (it should be multiplied by dt first (integration)
382 // // but I "include" dt in the gain. So gain must be less than dt. Multiply also for gain and not
383 // // only by dt is necessary to reduce the intensity of the torque (as done in previous function for forces)
384 // g_angVel << gain*(gRt * torquePegTip); //torque is respect to the tool
385 // g_angVel = FRM::saturateVectorEigen(g_angVel, 0.005);
386 
387 // // the rot between goal and new goal is an identity BEFORE the application of angular vel
388 // CMAT::RotMatrix gRnewg_0_cmat = CMAT::Matrix::Eye(3);
389 
390 // //Strap down: Out = e^[wdt^] * gRnewg_0_cmat
391 // CMAT::RotMatrix gRnewg_1_cmat = gRnewg_0_cmat.StrapDown(CONV::matrix_eigen2cmat(g_angVel), dt);
392 
393 // ///debug
394 // std::cout << "DEBug:\n torquePegTip:\n" << torquePegTip << "\ng_angVel\n:" << g_angVel << "\ngRnewg_1_cmat:\n";
395 // gRnewg_1_cmat.PrintMtx();
396 // std::cout << std::endl;
397 
398 // wTgoalTool_eigen.topLeftCorner<3,3>() = wTgoalTool_eigen.topLeftCorner<3,3>() *
399 // CONV::matrix_cmat2eigen(gRnewg_1_cmat);
400 // }
401 
402 // return wTgoalTool_eigen;
403 //}
Definition: logger.h:16
The VisionInterfaceCoord class. It is the coordinator interface which take the hole estimated pose fr...
The CoordInterfaceCoord class.
The WorldInterface class to get position from world to anything else.