Visual Servoing Platform  version 3.6.1 under development (2024-11-21)
vpRobotFlirPtu.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Interface for Flir Ptu Cpi robot.
33  *
34 *****************************************************************************/
35 
36 #include <visp3/core/vpConfig.h>
37 
38 #ifdef VISP_HAVE_FLIR_PTU_SDK
39 
40 #include <signal.h>
41 #include <stdexcept>
42 
43 extern "C" {
44 #include <cpi.h>
45 }
46 
52 #include <visp3/core/vpHomogeneousMatrix.h>
53 #include <visp3/robot/vpRobotFlirPtu.h>
54 
55 BEGIN_VISP_NAMESPACE
64 {
65  std::stringstream msg;
66  msg << "Stop the FLIR PTU by signal (" << signo << "): " << (char)7;
67  switch (signo) {
68  case SIGINT:
69  msg << "SIGINT (stop by ^C) ";
70  break;
71  case SIGSEGV:
72  msg << "SIGSEGV (stop due to a segmentation fault) ";
73  break;
74 #ifndef _WIN32
75  case SIGBUS:
76  msg << "SIGBUS (stop due to a bus error) ";
77  break;
78  case SIGKILL:
79  msg << "SIGKILL (stop by CTRL \\) ";
80  break;
81  case SIGQUIT:
82  msg << "SIGQUIT ";
83  break;
84 #endif
85  default:
86  msg << signo << std::endl;
87  }
88 
90 }
91 
96 {
97  // If you want to control the robot in Cartesian in a tool frame, set the corresponding transformation in m_eMc
98  // that is set to identity by default in the constructor.
99 
102 
103  // Set here the robot degrees of freedom number
104  nDof = 2; // Flir Ptu has 2 dof
105 }
106 
111  : m_eMc(), m_cer(nullptr), m_status(0), m_pos_max_tics(2), m_pos_min_tics(2), m_vel_max_tics(2), m_res(2),
112  m_connected(false), m_njoints(2), m_positioning_velocity(20.)
113 {
114  signal(SIGINT, vpRobotFlirPtu::emergencyStop);
115  signal(SIGSEGV, vpRobotFlirPtu::emergencyStop);
116 #ifndef _WIN32
117  signal(SIGBUS, vpRobotFlirPtu::emergencyStop);
118  signal(SIGKILL, vpRobotFlirPtu::emergencyStop);
119  signal(SIGQUIT, vpRobotFlirPtu::emergencyStop);
120 #endif
121 
122  init();
123 }
124 
129 {
130  stopMotion();
131  disconnect();
132 }
133 
134 /*
135  At least one of these function has to be implemented to control the robot with a
136  Cartesian velocity:
137  - get_eJe()
138  - get_fJe()
139 */
140 
148 {
149  vpMatrix eJe;
150  vpColVector q;
152  eJe.resize(6, 2);
153  eJe = 0;
154  eJe[3][0] = -sin(q[1]);
155  eJe[4][1] = -1;
156  eJe[5][0] = -cos(q[1]);
157  return eJe;
158 }
159 
167 
175 {
176  vpMatrix fJe;
177  vpColVector q;
179  fJe.resize(6, 2);
180  fJe = 0;
181  fJe[3][1] = -sin(q[1]);
182  fJe[4][1] = -cos(q[1]);
183  fJe[5][0] = -1;
184 
185  return fJe;
186 }
187 
195 
201 {
203  vpColVector q;
205  double c1 = cos(q[0]);
206  double c2 = cos(q[1]);
207  double s1 = sin(q[0]);
208  double s2 = sin(q[1]);
209 
210  fMe[0][0] = c1 * c2;
211  fMe[0][1] = s1;
212  fMe[0][2] = -c1 * s2;
213 
214  fMe[1][0] = -s1 * c2;
215  fMe[1][1] = c1;
216  fMe[1][2] = s1 * s2;
217 
218  fMe[2][0] = s2;
219  fMe[2][1] = 0;
220  fMe[2][2] = c2;
221 
222  return fMe;
223 }
224 
238 {
240  cVe.buildFrom(m_eMc.inverse());
241 
242  return cVe;
243 }
244 
245 /*
246  At least one of these function has to be implemented to control the robot:
247  - setCartVelocity()
248  - setJointVelocity()
249 */
250 
258 {
259  if (v.size() != 6) {
261  "Cannot send a velocity-skew vector in tool frame that is not 6-dim (%d)", v.size()));
262  }
263 
264  vpColVector v_e; // This is the velocity that the robot is able to apply in the end-effector frame
265  switch (frame) {
266  case vpRobot::TOOL_FRAME: {
267  // We have to transform the requested velocity in the end-effector frame.
268  // Knowing that the constant transformation between the tool frame and the end-effector frame obtained
269  // by extrinsic calibration is set in m_eMc we can compute the velocity twist matrix eVc that transform
270  // a velocity skew from tool (or camera) frame into end-effector frame
272  v_e = eVc * v;
273  break;
274  }
275 
278  v_e = v;
279  break;
280  }
282  case vpRobot::MIXT_FRAME:
283  // Out of the scope
284  break;
285  }
286 
287  // Implement your stuff here to send the end-effector velocity skew v_e
288  // - If the SDK allows to send cartesian velocities in the end-effector, it's done. Just wrap data in v_e
289  // - If the SDK allows to send cartesian velocities in the reference (or base) frame you have to implement
290  // the robot Jacobian in set_fJe() and call:
291  // vpColVector v = get_fJe().inverse() * v_e;
292  // At this point you have to wrap data in v that is the 6-dim velocity to apply to the robot
293  // - If the SDK allows to send only joint velocities you have to implement the robot Jacobian in set_eJe()
294  // and call:
295  // vpColVector qdot = get_eJe().inverse() * v_e;
296  // setJointVelocity(qdot);
297  // - If the SDK allows to send only a cartesian position trajectory of the end-effector position in the base frame
298  // called fMe (for fix frame to end-effector homogeneous transformation) you can transform the cartesian
299  // velocity in the end-effector into a displacement eMe using the exponetial map:
300  // double delta_t = 0.010; // in sec
301  // vpHomogenesousMatrix eMe = vpExponentialMap::direct(v_e, delta_t);
302  // vpHomogenesousMatrix fMe = getPosition(vpRobot::REFERENCE_FRAME);
303  // the new position to reach is than given by fMe * eMe
304  // vpColVector fpe(vpPoseVector(fMe * eMe));
305  // setPosition(vpRobot::REFERENCE_FRAME, fpe);
306 
307  std::cout << "Not implemented ! " << std::endl;
308  std::cout << "To implement me you need : " << std::endl;
309  std::cout << "\t to known the robot jacobian expressed in ";
310  std::cout << "the end-effector frame (eJe) " << std::endl;
311  std::cout << "\t the frame transformation between tool or camera frame ";
312  std::cout << "and end-effector frame (cMe)" << std::endl;
313 }
314 
320 {
321  if (!m_connected) {
322  disconnect();
323  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
324  }
325 
326  std::vector<int> vel_tics(2);
327 
328  for (int i = 0; i < 2; i++) {
329  vel_tics[i] = rad2tics(i, qdot[i]);
330  if (std::fabs(vel_tics[i]) > m_vel_max_tics[i]) {
331  disconnect();
332  throw(vpException(vpException::fatalError, "Cannot set joint %d velocity %f (deg/s). Out of limits [-%f, %f].", i,
333  vpMath::deg(qdot[i]), -tics2deg(i, m_vel_max_tics[i]), tics2deg(i, m_vel_max_tics[i])));
334  }
335  }
336 
337  if (cpi_ptcmd(m_cer, &m_status, OP_PAN_DESIRED_SPEED_SET, vel_tics[0]) ||
338  cpi_ptcmd(m_cer, &m_status, OP_TILT_DESIRED_SPEED_SET, vel_tics[1])) {
339  throw(vpException(vpException::fatalError, "Unable to set velocity."));
340  }
341 }
342 
351 {
354  "Cannot send a velocity to the robot. "
355  "Call setRobotState(vpRobot::STATE_VELOCITY_CONTROL) once before "
356  "entering your control loop.");
357  }
358 
359  vpColVector vel_sat(6);
360 
361  // Velocity saturation
362  switch (frame) {
363  // Saturation in cartesian space
364  case vpRobot::TOOL_FRAME:
367  case vpRobot::MIXT_FRAME: {
368  if (vel.size() != 6) {
370  "Cannot apply a Cartesian velocity that is not a 6-dim vector (%d)", vel.size()));
371  }
372  vpColVector vel_max(6);
373 
374  for (unsigned int i = 0; i < 3; i++)
375  vel_max[i] = getMaxTranslationVelocity();
376  for (unsigned int i = 3; i < 6; i++)
377  vel_max[i] = getMaxRotationVelocity();
378 
379  vel_sat = vpRobot::saturateVelocities(vel, vel_max, true);
380 
381  setCartVelocity(frame, vel_sat);
382  break;
383  }
384  // Saturation in joint space
385  case vpRobot::JOINT_STATE: {
386  if (vel.size() != static_cast<size_t>(nDof)) {
387  throw(vpException(vpException::dimensionError, "Cannot apply a joint velocity that is not a %d-dim vector (%d)",
388  nDof, vel.size()));
389  }
390  vpColVector vel_max(vel.size());
391 
392  // Since the robot has only rotation axis all the joint max velocities are set to getMaxRotationVelocity()
393  vel_max = getMaxRotationVelocity();
394 
395  vel_sat = vpRobot::saturateVelocities(vel, vel_max, true);
396 
397  setJointVelocity(vel_sat);
398  }
399  }
400 }
401 
402 /*
403  THESE FUNCTIONS ARE NOT MANDATORY BUT ARE USUALLY USEFUL
404 */
405 
411 {
412  if (!m_connected) {
413  disconnect();
414  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
415  }
416 
417  std::vector<int> pos_tics(2);
418 
419  if (cpi_ptcmd(m_cer, &m_status, OP_PAN_CURRENT_POS_GET, &pos_tics[0])) {
420  disconnect();
421  throw(vpException(vpException::fatalError, "Unable to query pan position."));
422  }
423  if (cpi_ptcmd(m_cer, &m_status, OP_TILT_CURRENT_POS_GET, &pos_tics[1])) {
424  disconnect();
425  throw(vpException(vpException::fatalError, "Unable to query pan position."));
426  }
427 
428  q.resize(2);
429  for (int i = 0; i < 2; i++) {
430  q[i] = tics2rad(i, pos_tics[i]);
431  }
432 }
433 
440 {
441  if (frame == JOINT_STATE) {
442  getJointPosition(q);
443  }
444  else {
445  std::cout << "Not implemented ! " << std::endl;
446  }
447 }
448 
455 {
456  if (frame != vpRobot::JOINT_STATE) {
457  std::cout << "FLIR PTU positioning is not implemented in this frame" << std::endl;
458  return;
459  }
460 
461  if (q.size() != 2) {
462  disconnect();
463  throw(vpException(vpException::fatalError, "FLIR PTU has only %d joints. Cannot set a position that is %d-dim.",
464  m_njoints, q.size()));
465  }
466  if (!m_connected) {
467  disconnect();
468  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
469  }
470 
471  double vmin = 0.01, vmax = 100.;
472  if (m_positioning_velocity < vmin || m_positioning_velocity > vmax) {
473  disconnect();
474  throw(
475  vpException(vpException::fatalError, "FLIR PTU Positioning velocity %f is not in range [%f, %f]", vmin, vmax));
476  }
477 
478  std::vector<int> pos_tics(2);
479 
480  for (int i = 0; i < 2; i++) {
481  pos_tics[i] = rad2tics(i, q[i]);
482  if (pos_tics[i] < m_pos_min_tics[i] || pos_tics[i] > m_pos_max_tics[i]) {
483  disconnect();
484  throw(vpException(vpException::fatalError, "Cannot set joint %d position %f (deg). Out of limits [%f, %f].", i,
485  vpMath::deg(q[i]), tics2deg(i, m_pos_min_tics[i]), tics2deg(i, m_pos_max_tics[i])));
486  }
487  }
488 
489  // Set desired speed wrt max pan/tilt speed
490  if (cpi_ptcmd(m_cer, &m_status, OP_PAN_DESIRED_SPEED_SET, (int)(m_vel_max_tics[0] * m_positioning_velocity / 100.)) ||
491  cpi_ptcmd(m_cer, &m_status, OP_TILT_DESIRED_SPEED_SET,
492  (int)(m_vel_max_tics[1] * m_positioning_velocity / 100.))) {
493  disconnect();
494  throw(vpException(vpException::fatalError, "Setting FLIR pan/tilt positioning velocity failed"));
495  }
496 
497  if (cpi_ptcmd(m_cer, &m_status, OP_PAN_DESIRED_POS_SET, pos_tics[0]) ||
498  cpi_ptcmd(m_cer, &m_status, OP_TILT_DESIRED_POS_SET, pos_tics[1])) {
499  disconnect();
500  throw(vpException(vpException::fatalError, "FLIR PTU failed to go to position %d, %d (deg).", vpMath::deg(q[0]),
501  vpMath::deg(q[1])));
502  }
503 
504  if (cpi_block_until(m_cer, nullptr, nullptr, OP_PAN_CURRENT_POS_GET, pos_tics[0]) ||
505  cpi_block_until(m_cer, nullptr, nullptr, OP_TILT_CURRENT_POS_GET, pos_tics[1])) {
506  disconnect();
507  throw(vpException(vpException::fatalError, "FLIR PTU failed to wait until position %d, %d reached (deg)",
508  vpMath::deg(q[0]), vpMath::deg(q[1])));
509  }
510 }
511 
518 {
519  (void)frame;
520  (void)q;
521  std::cout << "Not implemented ! " << std::endl;
522 }
523 
530 void vpRobotFlirPtu::connect(const std::string &portname, int baudrate)
531 {
532  char errstr[128];
533 
534  if (m_connected) {
535  disconnect();
536  }
537 
538  if (portname.empty()) {
539  disconnect();
540  throw(vpException(vpException::fatalError, "Port name is required to connect to FLIR PTU."));
541  }
542 
543  if ((m_cer = (struct cerial *)malloc(sizeof(struct cerial))) == nullptr) {
544  disconnect();
545  throw(vpException(vpException::fatalError, "Out of memory during FLIR PTU connection."));
546  }
547 
548  // Open a port
549  if (ceropen(m_cer, portname.c_str(), 0)) {
550 #if _WIN32
551  throw(vpException(vpException::fatalError, "Failed to open %s: %s.", portname.c_str(),
552  cerstrerror(m_cer, errstr, sizeof(errstr))));
553 #else
554  throw(vpException(vpException::fatalError, "Failed to open %s: %s.\nRun `sudo chmod a+rw %s`", portname.c_str(),
555  cerstrerror(m_cer, errstr, sizeof(errstr)), portname.c_str()));
556 #endif
557  }
558 
559  // Set baudrate
560  // ignore errors since not all devices are serial ports
561  cerioctl(m_cer, CERIAL_IOCTL_BAUDRATE_SET, &baudrate);
562 
563  // Flush any characters already buffered
564  cerioctl(m_cer, CERIAL_IOCTL_FLUSH_INPUT, nullptr);
565 
566  // Set two second timeout */
567  int timeout = 2000;
568  if (cerioctl(m_cer, CERIAL_IOCTL_TIMEOUT_SET, &timeout)) {
569  disconnect();
570  throw(vpException(vpException::fatalError, "cerial: timeout ioctl not supported."));
571  }
572 
573  // Sync and lock
574  int trial = 0;
575  do {
576  trial++;
577  } while (trial <= 3 && (cpi_resync(m_cer) || cpi_ptcmd(m_cer, &m_status, OP_NOOP)));
578  if (trial > 3) {
579  disconnect();
580  throw(vpException(vpException::fatalError, "Cannot communicate with FLIR PTU."));
581  }
582 
583  // Immediately execute commands (slave mode should be opt-in)
584  int rc;
585  if ((rc = cpi_ptcmd(m_cer, &m_status, OP_EXEC_MODE_SET, (cpi_enum)CPI_IMMEDIATE_MODE))) {
586  disconnect();
587  throw(vpException(vpException::fatalError, "Set Immediate Mode failed: %s", cpi_strerror(rc)));
588  }
589 
590  m_connected = true;
591 
592  getLimits();
593 }
594 
600 {
601  if (m_cer != nullptr) {
602  cerclose(m_cer);
603  free(m_cer);
604  m_cer = nullptr;
605  m_connected = false;
606  }
607 }
608 
613 {
614  if (!m_connected) {
615  disconnect();
616  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
617  }
618 
619  int status;
620 
621  if ((status = cpi_ptcmd(m_cer, &m_status, OP_PAN_MAX_POSITION, &m_pos_max_tics[0])) ||
622  (status = cpi_ptcmd(m_cer, &m_status, OP_PAN_MIN_POSITION, &m_pos_min_tics[0])) ||
623  (status = cpi_ptcmd(m_cer, &m_status, OP_TILT_MAX_POSITION, &m_pos_max_tics[1])) ||
624  (status = cpi_ptcmd(m_cer, &m_status, OP_TILT_MIN_POSITION, &m_pos_min_tics[1])) ||
625  (status = cpi_ptcmd(m_cer, &m_status, OP_PAN_UPPER_SPEED_LIMIT_GET, &m_vel_max_tics[0])) ||
626  (status = cpi_ptcmd(m_cer, &m_status, OP_TILT_UPPER_SPEED_LIMIT_GET, &m_vel_max_tics[1]))) {
627  disconnect();
628  throw(vpException(vpException::fatalError, "Failed to get limits (%d) %s.", status, cpi_strerror(status)));
629  }
630 
631  // Get the ptu resolution so we can convert the angles to ptu positions
632  if ((status = cpi_ptcmd(m_cer, &m_status, OP_PAN_RESOLUTION, &m_res[0])) ||
633  (status = cpi_ptcmd(m_cer, &m_status, OP_TILT_RESOLUTION, &m_res[1]))) {
634  disconnect();
635  throw(vpException(vpException::fatalError, "Failed to get resolution (%d) %s.", status, cpi_strerror(status)));
636  }
637 
638  for (size_t i = 0; i < 2; i++) {
639  m_res[i] /= 3600.; // Resolutions are in arc-seconds, but we want degrees
640  }
641 }
642 
650 {
651  if (!m_connected) {
652  disconnect();
653  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
654  }
655  vpColVector pan_pos_limits(2);
656  pan_pos_limits[0] = tics2rad(0, m_pos_min_tics[0]);
657  pan_pos_limits[1] = tics2rad(0, m_pos_max_tics[0]);
658 
659  return pan_pos_limits;
660 }
661 
669 {
670  if (!m_connected) {
671  disconnect();
672  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
673  }
674  vpColVector tilt_pos_limits(2);
675  tilt_pos_limits[0] = tics2rad(0, m_pos_min_tics[1]);
676  tilt_pos_limits[1] = tics2rad(0, m_pos_max_tics[1]);
677 
678  return tilt_pos_limits;
679 }
680 
688 {
689  if (!m_connected) {
690  disconnect();
691  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
692  }
693  vpColVector vel_max(2);
694  for (int i = 0; i < 2; i++) {
695  vel_max[i] = tics2rad(i, m_vel_max_tics[i]);
696  }
697  return vel_max;
698 }
699 
707 {
708  if (!m_connected) {
709  disconnect();
710  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
711  }
712  if (pan_limits.size() != 2) {
713  disconnect();
714  throw(vpException(vpException::fatalError, "Cannot set max position that is not a 2-dim vector."));
715  }
716  std::vector<int> pan_limits_tics(2);
717  for (int i = 0; i < 2; i++) {
718  pan_limits_tics[i] = rad2tics(i, pan_limits[i]);
719  }
720 
721  int status;
722  if ((status = cpi_ptcmd(m_cer, &m_status, OP_PAN_USER_MIN_POS_SET, pan_limits_tics[0])) ||
723  (status = cpi_ptcmd(m_cer, &m_status, OP_PAN_USER_MAX_POS_SET, pan_limits_tics[1]))) {
724  disconnect();
725  throw(vpException(vpException::fatalError, "Failed to set pan position limits (%d) %s.", status,
726  cpi_strerror(status)));
727  }
728 }
729 
737 {
738  if (!m_connected) {
739  disconnect();
740  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
741  }
742  if (tilt_limits.size() != 2) {
743  disconnect();
744  throw(vpException(vpException::fatalError, "Cannot set max position that is not a 2-dim vector."));
745  }
746  std::vector<int> tilt_limits_tics(2);
747  for (int i = 0; i < 2; i++) {
748  tilt_limits_tics[i] = rad2tics(i, tilt_limits[i]);
749  }
750 
751  int status;
752  if ((status = cpi_ptcmd(m_cer, &m_status, OP_TILT_USER_MIN_POS_SET, tilt_limits_tics[0])) ||
753  (status = cpi_ptcmd(m_cer, &m_status, OP_TILT_USER_MAX_POS_SET, tilt_limits_tics[1]))) {
754  disconnect();
755  throw(vpException(vpException::fatalError, "Failed to set tilt position limits (%d) %s.", status,
756  cpi_strerror(status)));
757  }
758 }
759 
767 
776 {
777  if (!m_connected) {
778  return getRobotState();
779  }
780 
781  switch (newState) {
782  case vpRobot::STATE_STOP: {
783  // Start primitive STOP only if the current state is Velocity
785  stopMotion();
786 
787  // Set the PTU to pure velocity mode
788  if (cpi_ptcmd(m_cer, &m_status, OP_SPEED_CONTROL_MODE_SET, (cpi_enum)CPI_CONTROL_INDEPENDENT)) {
789  throw(vpException(vpException::fatalError, "Unable to set control mode independent."));
790  }
791  }
792  break;
793  }
796  std::cout << "Change the control mode from velocity to position control.\n";
797  stopMotion();
798 
799  // Set the PTU to pure velocity mode
800  if (cpi_ptcmd(m_cer, &m_status, OP_SPEED_CONTROL_MODE_SET, (cpi_enum)CPI_CONTROL_INDEPENDENT)) {
801  throw(vpException(vpException::fatalError, "Unable to set control mode independent."));
802  }
803 
804  }
805  else {
806  // std::cout << "Change the control mode from stop to position
807  // control.\n";
808  }
809  break;
810  }
813  std::cout << "Change the control mode from stop to velocity control.\n";
814 
815  // Set the PTU to pure velocity mode
816  if (cpi_ptcmd(m_cer, &m_status, OP_SPEED_CONTROL_MODE_SET, (cpi_enum)CPI_CONTROL_PURE_VELOCITY)) {
817  throw(vpException(vpException::fatalError, "Unable to set velocity control mode."));
818  }
819  }
820  break;
821  }
822  default:
823  break;
824  }
825 
826  return vpRobot::setRobotState(newState);
827 }
828 
833 {
834  if (!m_connected) {
835  return;
836  }
837 
838  if (cpi_ptcmd(m_cer, &m_status, OP_RESET, nullptr)) {
839  throw(vpException(vpException::fatalError, "Unable to reset PTU."));
840  }
841 }
842 
847 {
849  return;
850  }
851 
852  if (!m_connected) {
853  return;
854  }
855 
856  if (cpi_ptcmd(m_cer, &m_status, OP_HALT, nullptr)) {
857  throw(vpException(vpException::fatalError, "Unable to stop PTU."));
858  }
859 }
860 
867 {
868  if (!m_connected) {
869  disconnect();
870  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
871  }
872 
873  char str[64];
874  if (cpi_ptcmd(m_cer, &m_status, OP_NET_IP_GET, (int)sizeof(str), nullptr, &str)) {
875  throw(vpException(vpException::fatalError, "Unable to get Network IP."));
876  }
877 
878  return (std::string(str));
879 }
880 
887 {
888  if (!m_connected) {
889  disconnect();
890  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
891  }
892 
893  char str[64];
894  if (cpi_ptcmd(m_cer, &m_status, OP_NET_GATEWAY_GET, (int)sizeof(str), nullptr, &str)) {
895  throw(vpException(vpException::fatalError, "Unable to get Network Gateway."));
896  }
897 
898  return (std::string(str));
899 }
900 
907 {
908  if (!m_connected) {
909  disconnect();
910  throw(vpException(vpException::fatalError, "FLIR PTU is not connected."));
911  }
912 
913  char str[64];
914  if (cpi_ptcmd(m_cer, &m_status, OP_NET_HOSTNAME_GET, (int)sizeof(str), nullptr, &str)) {
915  throw(vpException(vpException::fatalError, "Unable to get Network hostname."));
916  }
917 
918  return (std::string(str));
919 }
920 
929 int vpRobotFlirPtu::rad2tics(int axis, double rad) { return (static_cast<int>(vpMath::deg(rad) / m_res[axis])); }
930 
939 double vpRobotFlirPtu::tics2deg(int axis, int tics) { return (tics * m_res[axis]); }
940 
949 double vpRobotFlirPtu::tics2rad(int axis, int tics) { return vpMath::rad(tics2deg(axis, tics)); }
950 END_VISP_NAMESPACE
951 #elif !defined(VISP_BUILD_SHARED_LIBS)
952 // Work around to avoid warning: libvisp_robot.a(vpRobotFlirPtu.cpp.o) has
953 // no symbols
954 void dummy_vpRobotFlirPtu() { };
955 #endif
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:362
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1143
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ dimensionError
Bad dimension.
Definition: vpException.h:71
@ fatalError
Fatal error.
Definition: vpException.h:72
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
static double rad(double deg)
Definition: vpMath.h:129
static double deg(double rad)
Definition: vpMath.h:119
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
Error that can be emitted by the vpRobot class and its derivatives.
@ wrongStateError
Wrong robot state.
@ signalException
Signal exception returned after SIGINT (CTRL-C), SIGBUS, SIGSEGV, SIGSEGV (CTRL-),...
vpHomogeneousMatrix m_eMc
Constant transformation between end-effector and tool (or camera) frame.
std::vector< int > m_pos_max_tics
Pan min/max position in robot tics unit.
void connect(const std::string &portname, int baudrate=9600)
vpColVector getTiltPosLimits()
vpColVector getPanPosLimits()
double m_positioning_velocity
vpMatrix get_fJe()
std::string getNetworkGateway()
void getPosition(const vpRobot::vpControlFrameType frame, vpColVector &q) VP_OVERRIDE
std::vector< double > m_res
Pan/tilt tic resolution in deg.
void setPositioningVelocity(double velocity)
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel) VP_OVERRIDE
virtual ~vpRobotFlirPtu()
std::string getNetworkIP()
void setPosition(const vpRobot::vpControlFrameType frame, const vpColVector &q) VP_OVERRIDE
std::vector< int > m_vel_max_tics
Pan/tilt max velocity in robot tics unit.
void setCartVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &v)
struct cerial * m_cer
vpVelocityTwistMatrix get_cVe() const
void getJointPosition(vpColVector &q)
std::string getNetworkHostName()
void setJointVelocity(const vpColVector &qdot)
static void emergencyStop(int signo)
void setPanPosLimits(const vpColVector &pan_limits)
vpMatrix get_eJe()
std::vector< int > m_pos_min_tics
Tilt min/max position in robot tics unit.
vpColVector getPanTiltVelMax()
vpRobot::vpRobotStateType setRobotState(vpRobot::vpRobotStateType newState)
void getDisplacement(const vpRobot::vpControlFrameType frame, vpColVector &q) VP_OVERRIDE
vpMatrix get_fMe()
void setTiltPosLimits(const vpColVector &tilt_limits)
int nDof
number of degrees of freedom
Definition: vpRobot.h:104
vpMatrix eJe
robot Jacobian expressed in the end-effector frame
Definition: vpRobot.h:106
virtual vpRobotStateType getRobotState(void) const
Definition: vpRobot.h:155
static vpColVector saturateVelocities(const vpColVector &v_in, const vpColVector &v_max, bool verbose=false)
Definition: vpRobot.cpp:164
vpControlFrameType
Definition: vpRobot.h:77
@ REFERENCE_FRAME
Definition: vpRobot.h:78
@ JOINT_STATE
Definition: vpRobot.h:82
@ TOOL_FRAME
Definition: vpRobot.h:86
@ MIXT_FRAME
Definition: vpRobot.h:88
@ END_EFFECTOR_FRAME
Definition: vpRobot.h:83
static const double maxRotationVelocityDefault
Definition: vpRobot.h:101
vpRobotStateType
Definition: vpRobot.h:65
@ STATE_POSITION_CONTROL
Initialize the position controller.
Definition: vpRobot.h:68
@ STATE_VELOCITY_CONTROL
Initialize the velocity controller.
Definition: vpRobot.h:67
@ STATE_STOP
Stops robot motion especially in velocity and acceleration control.
Definition: vpRobot.h:66
static const double maxTranslationVelocityDefault
Definition: vpRobot.h:99
double getMaxRotationVelocity(void) const
Definition: vpRobot.cpp:274
vpMatrix fJe
robot Jacobian expressed in the robot reference frame available
Definition: vpRobot.h:110
virtual vpRobotStateType setRobotState(const vpRobot::vpRobotStateType newState)
Definition: vpRobot.cpp:202
double maxTranslationVelocity
Definition: vpRobot.h:98
double getMaxTranslationVelocity(void) const
Definition: vpRobot.cpp:252
double maxRotationVelocity
Definition: vpRobot.h:100
vpVelocityTwistMatrix & buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)