Katana.cpp
Go to the documentation of this file.
1 /*
2  * UOS-ROS packages - Robot Operating System code by the University of Osnabrück
3  * Copyright (C) 2010 University of Osnabrück
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * Katana.cpp
20  *
21  * Created on: 06.12.2010
22  * Author: Martin Günther <mguenthe@uos.de>
23  * Co-Author: Henning Deeken <hdeeken@uos.de>
24  */
25 
26 #include "katana/Katana.h"
27 
28 namespace katana
29 {
30 
33 {
34  ros::NodeHandle nh;
35  ros::NodeHandle pn("~");
36  motor_status_.resize(NUM_MOTORS);
37 
38  /* ********* get parameters ********* */
39 
40  // general parameters
41  std::string config_file_path;
42  bool use_serial;
43 
44  bool has_path = pn.getParam("config_file_path", config_file_path);
45  if (!has_path) {
46  ROS_ERROR("Required parameter config_file_path could not be found on param server!");
47  return;
48  }
49 
50  pn.param("use_serial", use_serial, false);
51 
52  converter = new KNIConverter(config_file_path);
53 
54  // parameters for TCP/IP connection
55  std::string ip;
56  int tcpip_port;
57 
58  pn.param<std::string> ("ip", ip, "192.168.1.1");
59  pn.param("port", tcpip_port, 5566);
60 
61  // parameters for serial connection
62  int serial_port;
63 
64  pn.param("serial_port", serial_port, 0);
65  if (serial_port < 0 || serial_port > 9)
66  {
67  ROS_ERROR("serial_port must be in the range [0-9]!");
68  return;
69  }
70 
71  try
72  {
73  /* ********* open device ********* */
74  if (use_serial)
75  {
76  ROS_INFO("trying to connect to katana (serial port: /dev/ttyS%d) ...", serial_port);
77 
78  TCdlCOMDesc serial_config;
79  serial_config.port = serial_port; // serial port number (0-9 for /dev/ttyS[0-9])
80  serial_config.baud = 57600; // baud rate of port
81  serial_config.data = 8; // data bits
82  serial_config.parity = 'N'; // parity bit
83  serial_config.stop = 1; // stop bit
84  serial_config.rttc = 300; // read total timeout
85  serial_config.wttc = 0; // write total timeout
86 
87  device = new CCdlCOM(serial_config);
88  ROS_INFO("success: serial connection to Katana opened");
89  }
90  else
91  {
92  ROS_INFO("trying to connect to katana (TCP/IP) on %s:%d...", ip.c_str(), tcpip_port);
93  char* nonconst_ip = strdup(ip.c_str());
94  device = new CCdlSocket(nonconst_ip, tcpip_port);
95  free(nonconst_ip);
96  ROS_INFO("success: TCP/IP connection to Katana opened");
97  }
98 
99  /* ********* init protocol ********* */
100  protocol = new CCplSerialCRC();
101  ROS_INFO("success: protocol class instantiated");
102 
103  protocol->init(device); //fails if no response from Katana
104  ROS_INFO("success: communication with Katana initialized");
105 
106  /* ********* init robot ********* */
107  kni.reset(new CLMBase());
108  kni->create(config_file_path.c_str(), protocol);
109  ROS_INFO("success: katana initialized");
110  }
111  catch (Exception &e)
112  {
113  ROS_ERROR("Exception during initialization: '%s'", e.message().c_str());
114  return;
115  }
116 
117  setLimits();
118 
119  /* ********* calibrate ********* */
120  calibrate();
121  ROS_INFO("success: katana calibrated");
122 
123  refreshEncoders();
124 
125  // boost::thread worker_thread(&Katana::test_speed, this);
126 
127  /* ********* services ********* */
128  switch_motors_off_srv_ = nh.advertiseService("switch_motors_off", &Katana::switchMotorsOff, this);
129  switch_motors_on_srv_ = nh.advertiseService("switch_motors_on", &Katana::switchMotorsOn, this);
130  test_speed_srv_ = nh.advertiseService("test_speed", &Katana::testSpeedSrv, this);
131 }
132 
134 {
135  // protocol and device are members of kni, so we should be
136  // the last ones using it before deleting them
137  assert(kni.use_count() == 1);
138 
139  kni.reset(); // delete kni, so protocol and device won't be used any more
140  delete protocol;
141  delete device;
142  delete converter;
143 }
144 
145 void Katana::setLimits(void) {
146  for (size_t i = 0; i < NUM_MOTORS; i++) {
147  // These two settings probably only influence KNI functions like moveRobotToEnc(),
148  // openGripper() and so on, and not the spline trajectories. We still set them
149  // just to be sure.
150  kni->setMotorAccelerationLimit(i, KNI_MAX_ACCELERATION);
151  kni->setMotorVelocityLimit(i, KNI_MAX_VELOCITY);
152  }
153 }
154 
156 {
157  try
158  {
159  boost::recursive_mutex::scoped_lock lock(kni_mutex);
160  CMotBase* motors = kni->GetBase()->GetMOT()->arr;
161 
162  kni->GetBase()->recvMPS(); // refresh all pvp->pos at once
163 
164  // Using recvMPS() instead of recvPVP() makes our updates 6 times
165  // faster, since we only need one KNI call instead of 6. The KNI
166  // needs exactly 40 ms for every update call.
167 
168  for (size_t i = 0; i < NUM_MOTORS; i++)
169  {
170  // motors[i].recvPVP(); // refresh pvp->pos, pvp->vel and pvp->msf for single motor; throws ParameterReadingException
171  const TMotPVP* pvp = motors[i].GetPVP();
172 
173  double current_angle = converter->angle_enc2rad(i, pvp->pos);
174  double time_since_update = (ros::Time::now() - last_encoder_update_).toSec();
175 
176  if (last_encoder_update_ == ros::Time(0.0) || time_since_update == 0.0)
177  {
178  motor_velocities_[i] = 0.0;
179  }
180  else
181  {
182  motor_velocities_[i] = (current_angle - motor_angles_[i]) / time_since_update;
183  }
184  // // only necessary when using recvPVP():
185  // motor_velocities_[i] = vel_enc2rad(i, pvp->vel) * (-1); // the -1 is because the KNI is inconsistent about velocities
186 
187  motor_angles_[i] = current_angle;
188  }
189 
190  // // This is an ugly workaround, but apparently the velocities returned by the
191  // // Katana are wrong by a factor of exactly 0.5 for motor 2 and a factor of -1
192  // // for motor 4. This is only necessary when using recvPVP() to receive the
193  // // velocities directly from the KNI.
194  // motor_velocities_[2] *= 0.5;
195  // motor_velocities_[4] *= -1.0;
196 
198  }
199  catch (const WrongCRCException &e)
200  {
201  ROS_ERROR("WrongCRCException: Two threads tried to access the KNI at once. This means that the locking in the Katana node is broken. (exception in refreshEncoders(): %s)", e.message().c_str());
202  }
203  catch (const ReadNotCompleteException &e)
204  {
205  ROS_ERROR("ReadNotCompleteException: Another program accessed the KNI. Please stop it and restart the Katana node. (exception in refreshEncoders(): %s)", e.message().c_str());
206  }
207  catch (const ParameterReadingException &e)
208  {
209  ROS_ERROR("ParameterReadingException: Could not receive PVP (Position Velocity PWM) parameters from a motor (exception in refreshEncoders(): %s)", e.message().c_str());
210  }
211  catch (const FirmwareException &e)
212  {
213  // This can happen when the arm collides with something (red LED).
214  // The message returned by the Katana in this case is:
215  // FirmwareException : 'move buffer error (axis 1)'
216  ROS_ERROR("FirmwareException: Did the arm collide with something (red LED)? (exception in refreshEncoders(): %s)", e.message().c_str());
217  }
218  catch (const Exception &e)
219  {
220  ROS_ERROR("Unhandled exception in refreshEncoders(): %s", e.message().c_str());
221  }
222  catch (...)
223  {
224  ROS_ERROR("Unhandled exception in refreshEncoders()");
225  }
226 }
227 
229 {
230  try
231  {
232  boost::recursive_mutex::scoped_lock lock(kni_mutex);
233  CMotBase* motors = kni->GetBase()->GetMOT()->arr;
234 
235  kni->GetBase()->recvGMS(); // refresh all pvp->msf at once
236 
237  for (size_t i = 0; i < NUM_MOTORS; i++)
238  {
239  const TMotPVP* pvp = motors[i].GetPVP();
240 
241  motor_status_[i] = pvp->msf;
242  // MSF_MECHSTOP = 1, //!< mechanical stopper reached, new: unused (default value)
243  // MSF_MAXPOS = 2, //!< max. position was reached, new: unused
244  // MSF_MINPOS = 4, //!< min. position was reached, new: calibrating
245  // MSF_DESPOS = 8, //!< in desired position, new: fixed, state holding
246  // MSF_NORMOPSTAT = 16, //!< trying to follow target, new: moving (polymb not full)
247  // MSF_MOTCRASHED = 40, //!< motor has crashed, new: collision (MG: this means that the motor has reached a collision limit (e.g., after executing a invalid spline) and has to be reset using unBlock())
248  // MSF_NLINMOV = 88, //!< non-linear movement ended, new: poly move finished
249  // MSF_LINMOV = 152, //!< linear movement ended, new: moving poly, polymb full
250  // MSF_NOTVALID = 128 //!< motor data not valid
251 
252  /*
253  * Das Handbuch zu Katana4D sagt (zu ReadAxisState):
254  * 0 = off (ausgeschaltet)
255  * 8 = in gewünschter Position (Roboter fixiert)
256  * 24 = im "normalen Bewegungsstatus"; versucht die gewünschte Position zu erreichen
257  * 40 = wegen einer Kollision gestoppt
258  * 88 = die Linearbewegung ist beendet
259  * 128 = ungültige Achsendaten (interne Kommunikationsprobleme)
260  */
261  }
262  }
263  catch (const WrongCRCException &e)
264  {
265  ROS_ERROR("WrongCRCException: Two threads tried to access the KNI at once. This means that the locking in the Katana node is broken. (exception in refreshMotorStatus(): %s)", e.message().c_str());
266  }
267  catch (const ReadNotCompleteException &e)
268  {
269  ROS_ERROR("ReadNotCompleteException: Another program accessed the KNI. Please stop it and restart the Katana node. (exception in refreshMotorStatus(): %s)", e.message().c_str());
270  }
271  catch (const Exception &e)
272  {
273  ROS_ERROR("Unhandled exception in refreshMotorStatus(): %s", e.message().c_str());
274  }
275  catch (...)
276  {
277  ROS_ERROR("Unhandled exception in refreshMotorStatus()");
278  }
279 }
280 
286 bool Katana::executeTrajectory(boost::shared_ptr<SpecifiedTrajectory> traj, boost::function<bool ()> isPreemptRequested)
287 {
288  assert(traj->size() > 0);
289 
290  try
291  {
292  // ------- wait until all motors idle
293  ros::Rate idleWait(10);
294  while (!allMotorsReady())
295  {
297  ROS_DEBUG("Motor status: %d, %d, %d, %d, %d, %d", motor_status_[0], motor_status_[1], motor_status_[2], motor_status_[3], motor_status_[4], motor_status_[5]);
298 
299  // ------- check if motors are blocked
300  // it is important to do this inside the allMotorsReady() loop, otherwise we
301  // could get stuck in a deadlock if the motors crash while we wait for them to
302  // become ready
303  if (someMotorCrashed())
304  {
305  ROS_WARN("Motors are crashed before executing trajectory! Unblocking...");
306 
307  boost::recursive_mutex::scoped_lock lock(kni_mutex);
308  kni->unBlock();
309  }
310 
311  idleWait.sleep();
312  }
313 
315  //{
316  // assert(traj->at(0).splines.size() == NUM_JOINTS);
317  //
318  // boost::recursive_mutex::scoped_lock lock(kni_mutex);
319  // std::vector<int> encoders;
320  //
321  // for (size_t i = 0; i < NUM_JOINTS; i++) {
322  // encoders.push_back(converter->angle_rad2enc(i, traj->at(0).splines[i].coef[0]));
323  // }
324  //
325  // std::vector<int> current_encoders = kni->getRobotEncoders(true);
326  // ROS_INFO("current encoders: %d %d %d %d %d", current_encoders[0], current_encoders[1], current_encoders[2], current_encoders[3], current_encoders[4]);
327  // ROS_INFO("target encoders: %d %d %d %d %d", encoders[0], encoders[1], encoders[2], encoders[3], encoders[4]);
328  //
329  // kni->moveRobotToEnc(encoders, false);
330  // ros::Duration(2.0).sleep();
331  //}
332 
333  // ------- wait until start time
334  ros::Time start_time = ros::Time(traj->at(0).start_time);
335  double time_until_start = (start_time - ros::Time::now()).toSec();
336 
337  if (fabs(traj->at(0).start_time) > 0.01 && time_until_start < -0.01)
338  {
339  // only print warning if traj->at(0).start_time != 0 (MoveIt usually doesn't set start time)
340  ROS_WARN("Trajectory started %f s too late! Scheduled: %f, started: %f", -time_until_start, start_time.toSec(), ros::Time::now().toSec());
341  }
342  else if (time_until_start > 0.0)
343  {
344  ROS_DEBUG("Sleeping %f seconds until scheduled start of trajectory", time_until_start);
345  ros::Time::sleepUntil(start_time);
346  }
347 
348  // ------- start trajectory
349  boost::recursive_mutex::scoped_lock lock(kni_mutex);
350 
351  // fix start times: set the trajectory start time to now(); since traj is a shared pointer,
352  // this fixes the current_trajectory_ in joint_trajectory_action_controller, which synchronizes
353  // the "state" publishing to the actual start time (more or less)
354  double delay = ros::Time::now().toSec() - traj->at(0).start_time;
355  for (size_t i = 0; i < traj->size(); i++)
356  {
357  traj->at(i).start_time += delay;
358  }
359 
360  for (size_t i = 0; i < traj->size(); i++)
361  {
362  Segment seg = traj->at(i);
363  if (seg.splines.size() != joint_names_.size())
364  {
365  ROS_ERROR("Wrong number of joints in specified trajectory (was: %zu, expected: %zu)!", seg.splines.size(), joint_names_.size());
366  }
367 
368  // set and start movement
369  int activityflag = 0;
370  if (i == (traj->size() - 1))
371  {
372  // last spline, start movement
373  activityflag = 1; // no_next
374  }
375  else if (seg.start_time - traj->at(0).start_time < 0.4)
376  {
377  // more splines following, do not start movement yet
378  activityflag = 2; // no_start
379  }
380  else
381  {
382  // more splines following, start movement
383  activityflag = 0;
384  }
385 
386  std::vector<short> polynomial;
387  short s_time = round(seg.duration * KNI_TO_ROS_TIME);
388  if (s_time <= 0)
389  s_time = 1;
390 
391  for (size_t j = 0; j < seg.splines.size(); j++)
392  {
393  // some parts taken from CLMBase::movLM2P
394  polynomial.push_back(s_time); // duration
395 
396  polynomial.push_back(converter->angle_rad2enc(j, seg.splines[j].target_position)); // target position
397 
398  // the four spline coefficients
399  // the actual position, round
400  polynomial.push_back(round(converter->angle_rad2enc(j, seg.splines[j].coef[0]))); // p0
401 
402  // shift to be firmware compatible and round
403  polynomial.push_back(round(64 * converter->vel_rad2enc(j, seg.splines[j].coef[1]))); // p1
404  polynomial.push_back(round(1024 * converter->acc_rad2enc(j, seg.splines[j].coef[2]))); // p2
405  polynomial.push_back(round(32768 * converter->jerk_rad2enc(j, seg.splines[j].coef[3]))); // p3
406  }
407 
408  // gripper: hold current position
409  polynomial.push_back(s_time); // duration
410  polynomial.push_back(converter->angle_rad2enc(5, motor_angles_[5])); // target position (angle)
411  polynomial.push_back(converter->angle_rad2enc(5, motor_angles_[5])); // p0
412  polynomial.push_back(0); // p1
413  polynomial.push_back(0); // p2
414  polynomial.push_back(0); // p3
415 
416  ROS_DEBUG("setAndStartPolyMovement(%d): ", activityflag);
417 
418  for (size_t k = 5; k < polynomial.size(); k += 6)
419  {
420  ROS_DEBUG(" time: %d target: %d p0: %d p1: %d p2: %d p3: %d",
421  polynomial[k-5], polynomial[k-4], polynomial[k-3], polynomial[k-2], polynomial[k-1], polynomial[k]);
422  }
423 
424  kni->setAndStartPolyMovement(polynomial, false, activityflag);
425  }
426  return true;
427  }
428  catch (const WrongCRCException &e)
429  {
430  ROS_ERROR("WrongCRCException: Two threads tried to access the KNI at once. This means that the locking in the Katana node is broken. (exception in executeTrajectory(): %s)", e.message().c_str());
431  }
432  catch (const ReadNotCompleteException &e)
433  {
434  ROS_ERROR("ReadNotCompleteException: Another program accessed the KNI. Please stop it and restart the Katana node. (exception in executeTrajectory(): %s)", e.message().c_str());
435  }
436  catch (const FirmwareException &e)
437  {
438  // TODO: find out what the real cause of this is when it happens again
439  // the message returned by the Katana is:
440  // FirmwareException : 'StopperThread: collision on axis: 1 (axis N)'
441  ROS_ERROR("FirmwareException: Motor collision? Perhaps we tried to send a trajectory that the arm couldn't follow. (exception in executeTrajectory(): %s)", e.message().c_str());
442  }
443  catch (const Exception &e)
444  {
445  ROS_ERROR("Unhandled exception in executeTrajectory(): %s", e.message().c_str());
446  }
447  catch (...)
448  {
449  ROS_ERROR("Unhandled exception in executeTrajectory()");
450  }
451  return false;
452 }
453 
455 {
456  boost::recursive_mutex::scoped_lock lock(kni_mutex);
457  kni->flushMoveBuffers();
458  kni->freezeRobot();
459 }
460 
461 bool Katana::moveJoint(int motorIndex, double desiredAngle)
462 {
463  if (desiredAngle < motor_limits_[motorIndex].min_position || motor_limits_[motorIndex].max_position < desiredAngle)
464  {
465  ROS_ERROR("Desired angle %f is out of range [%f, %f]", desiredAngle, motor_limits_[motorIndex].min_position, motor_limits_[motorIndex].max_position);
466  return false;
467  }
468 
469  try
470  {
471  boost::recursive_mutex::scoped_lock lock(kni_mutex);
472  kni->moveMotorToEnc(motorIndex, converter->angle_rad2enc(motorIndex, desiredAngle), false, 100);
473  return true;
474  }
475  catch (const WrongCRCException &e)
476  {
477  ROS_ERROR("WrongCRCException: Two threads tried to access the KNI at once. This means that the locking in the Katana node is broken. (exception in moveJoint(): %s)", e.message().c_str());
478  }
479  catch (const ReadNotCompleteException &e)
480  {
481  ROS_ERROR("ReadNotCompleteException: Another program accessed the KNI. Please stop it and restart the Katana node. (exception in moveJoint(): %s)", e.message().c_str());
482  }
483  catch (const Exception &e)
484  {
485  ROS_ERROR("Unhandled exception in moveJoint(): %s", e.message().c_str());
486  }
487  catch (...)
488  {
489  ROS_ERROR("Unhandled exception in moveJoint()");
490  }
491  return false;
492 }
493 
495 {
496  for (size_t i = 0; i < NUM_MOTORS; i++)
497  {
498  if (motor_status_[i] == MSF_MOTCRASHED)
499  return true;
500  }
501 
502  return false;
503 }
504 
506 {
507  for (size_t i = 0; i < NUM_JOINTS; i++)
508  {
509  if ((motor_status_[i] != MSF_DESPOS) && (motor_status_[i] != (MSF_NLINMOV)))
510  return false;
511  }
512 
513  return true;
514 }
515 
517 {
518  for (size_t i = 0; i < NUM_MOTORS; i++)
519  {
520  if ((motor_status_[i] != MSF_DESPOS) && (motor_status_[i] != (MSF_NLINMOV)))
521  return false;
522  }
523 
524  return true;
525 }
526 
527 /* ******************************** helper functions ******************************** */
528 
532 short inline Katana::round(const double x)
533 {
534  if (x >= 0)
535  return (short)(x + 0.5);
536  else
537  return (short)(x - 0.5);
538 }
539 
541 {
542  // private function only called in constructor, so no locking required
543  bool calibrate = false;
544  const int encoders = 100;
545 
546  kni->unBlock();
547 
548  // check if gripper collides in both cases (open and close gripper)
549  // note MG: "1" is not the gripper!
550  kni->enableCrashLimits();
551 
552  try
553  {
554  kni->moveMotorByEnc(1, encoders);
555  ROS_INFO("no calibration required");
556  }
557  catch (...)
558  {
559  ROS_INFO("first calibration collision... ");
560  try
561  {
562  kni->moveMotorByEnc(1, -encoders);
563  ROS_INFO("no calibration required");
564  }
565  catch (...)
566  {
567  ROS_INFO("second calibration collision: calibration required");
568  calibrate = true;
569  }
570  }
571 
572  if (calibrate)
573  {
574  kni->disableCrashLimits();
575  kni->calibrate();
576  kni->enableCrashLimits();
577  }
578 }
579 
584 bool Katana::switchMotorsOff(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
585 {
586  ROS_WARN("Switching all motors off!");
587  boost::recursive_mutex::scoped_lock lock(kni_mutex);
588  kni->switchRobotOff();
589  return true;
590 }
591 
592 bool Katana::switchMotorsOn(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
593 {
594  ROS_INFO("Switching all motors back on.");
595  boost::recursive_mutex::scoped_lock lock(kni_mutex);
596  kni->switchRobotOn();
597  return true;
598 }
599 
600 bool Katana::testSpeedSrv(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
601 {
602  testSpeed();
603  return true;
604 }
605 
607 {
608  ros::Rate idleWait(5);
609  std::vector<double> pos1_angles(NUM_MOTORS);
610  std::vector<double> pos2_angles(NUM_MOTORS);
611 
612  // these are safe values, i.e., no self-collision is possible
613  pos1_angles[0] = 2.88;
614  pos2_angles[0] = -3.02;
615 
616  pos1_angles[1] = 0.15;
617  pos2_angles[1] = 2.16;
618 
619  pos1_angles[2] = 1.40;
620  pos2_angles[2] = -2.21;
621 
622  pos1_angles[3] = 0.50;
623  pos2_angles[3] = -2.02;
624 
625  pos1_angles[4] = 2.86;
626  pos2_angles[4] = -2.98;
627 
628  pos1_angles[5] = -0.44;
629  pos2_angles[5] = 0.30;
630 
631  for (size_t i = 0; i < NUM_MOTORS; i++)
632  {
633  int pos1_encoders = (int)converter->angle_rad2enc(i, pos1_angles[i]);
634  int pos2_encoders = (int)converter->angle_rad2enc(i, pos2_angles[i]);
635 
636  int accel = kni->getMotorAccelerationLimit(i);
637  int max_vel = kni->getMotorVelocityLimit(i);
638 
639  ROS_INFO("Motor %zu - acceleration: %d (= %f), max speed: %d (=%f)", i, accel, 2.0 * converter->acc_enc2rad(i, accel), max_vel, converter->vel_enc2rad(i, max_vel));
640  ROS_INFO("KNI encoders: %d, %d", kni->GetBase()->GetMOT()->arr[i].GetEncoderMinPos(), kni->GetBase()->GetMOT()->arr[i].GetEncoderMaxPos());
641  ROS_INFO("moving to encoders: %d, %d", pos1_encoders, pos2_encoders);
642  ROS_INFO("current encoders: %d", kni->getMotorEncoders(i, true));
643 
644  ROS_INFO("Moving to min");
645  {
646  boost::recursive_mutex::scoped_lock lock(kni_mutex);
647  kni->moveMotorToEnc(i, pos1_encoders);
648  }
649 
650  do
651  {
652  idleWait.sleep();
654  } while (!allMotorsReady());
655 
656  ROS_INFO("Moving to max");
657  {
658  boost::recursive_mutex::scoped_lock lock(kni_mutex);
659  kni->moveMotorToEnc(i, pos2_encoders);
660  }
661 
662  do
663  {
664  idleWait.sleep();
666  } while (!allMotorsReady());
667  }
668 
669  // Result:
670  // Motor 0 - acceleration: 2 (= -4.908739), max speed: 180 (=-2.208932)
671  // Motor 1 - acceleration: 2 (= -2.646220), max speed: 180 (=-1.190799)
672  // Motor 2 - acceleration: 2 (= 5.292440), max speed: 180 (=2.381598)
673  // --> wrong! the measured values are more like 2.6, 1.2
674  //
675  // Motor 3 - acceleration: 2 (= -4.908739), max speed: 180 (=-2.208932)
676  // Motor 4 - acceleration: 2 (= -4.908739), max speed: 180 (=-2.208932)
677  // Motor 5 - acceleration: 2 (= 1.597410), max speed: 180 (=0.718834)
678  // (TODO: the gripper duration can be calculated from this)
679 }
680 
681 }
virtual bool executeTrajectory(boost::shared_ptr< SpecifiedTrajectory > traj, boost::function< bool()> isPreemptRequested)
Definition: Katana.cpp:286
ros::ServiceServer switch_motors_off_srv_
Definition: Katana.h:80
double vel_enc2rad(int index, short encoders)
KNIConverter * converter
Definition: Katana.h:75
virtual void freezeRobot()
Definition: Katana.cpp:454
static const double KNI_TO_ROS_TIME
KNI time is in 10 milliseconds (most of the time), ROS time is in seconds.
boost::recursive_mutex kni_mutex
Definition: Katana.h:72
virtual void refreshMotorStatus()
Definition: Katana.cpp:228
virtual ~Katana()
Definition: Katana.cpp:133
double acc_rad2enc(int index, double acc)
std::string message() const
ros::ServiceServer switch_motors_on_srv_
Definition: Katana.h:81
CCdlBase * device
Definition: Katana.h:85
MSF_MOTCRASHED
virtual void setLimits(void)
Definition: Katana.cpp:145
const TMotPVP * GetPVP()
CCplSerialCRC * protocol
Definition: Katana.h:84
ros::Time last_encoder_update_
Definition: Katana.h:87
CLMBase()
void refreshEncoders()
Definition: Katana.cpp:155
std::vector< TMotStsFlg > motor_status_
Definition: Katana.h:73
static bool sleepUntil(const Time &end)
MSF_NLINMOV
std::vector< double > motor_angles_
const size_t NUM_MOTORS
The number of motors in the katana (= all 5 "real" joints + the gripper)
static const int KNI_MAX_ACCELERATION
acceleration limit = 1 or 2 [enc / (10 ms)^2]
virtual bool init(CCdlBase *_device, byte _kataddr=24)
bool switchMotorsOn(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: Katana.cpp:592
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
std::vector< double > motor_velocities_
#define ROS_WARN(...)
std::vector< std::string > joint_names_
virtual void testSpeed()
Definition: Katana.cpp:606
ros::ServiceServer test_speed_srv_
Definition: Katana.h:82
std::vector< moveit_msgs::JointLimits > motor_limits_
double angle_rad2enc(int index, double angle)
#define ROS_INFO(...)
bool param(const std::string &param_name, T &param_val, const T &default_val) const
static const int KNI_MAX_VELOCITY
velocity limit <= 180 [enc / 10 ms]
double angle_enc2rad(int index, int encoders)
bool switchMotorsOff(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: Katana.cpp:584
short pos
boost::shared_ptr< CLMBase > kni
Definition: Katana.h:71
bool sleep()
virtual bool moveJoint(int jointIndex, double turningAngle)
Definition: Katana.cpp:461
TMotStsFlg msf
double vel_rad2enc(int index, double vel)
bool getParam(const std::string &key, std::string &s) const
virtual bool allMotorsReady()
Definition: Katana.cpp:516
virtual bool allJointsReady()
Definition: Katana.cpp:505
static Time now()
const size_t NUM_JOINTS
The number of joints in the katana (= only the 5 "real" joints)
virtual bool someMotorCrashed()
Definition: Katana.cpp:494
std::vector< Spline > splines
double acc_enc2rad(int index, short encoders)
bool testSpeedSrv(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
Definition: Katana.cpp:600
#define ROS_ERROR(...)
short round(const double x)
Definition: Katana.cpp:532
MSF_DESPOS
std::vector< int > encoders
double jerk_rad2enc(int index, double jerk)
void calibrate()
Definition: Katana.cpp:540
#define ROS_DEBUG(...)


katana
Author(s): Martin Günther
autogenerated on Fri Jun 7 2019 22:06:58