Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpRobotBiclopsController.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Interface for the Biclops robot.
32  *
33  * Authors:
34  * Fabien Spindler
35  *
36  *****************************************************************************/
37 
38 #include <signal.h>
39 #include <string.h>
40 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
41 # include <unistd.h>
42 #endif
43 #include <visp3/core/vpConfig.h>
44 
45 #ifndef DOXYGEN_SHOULD_SKIP_THIS
46 #ifdef VISP_HAVE_BICLOPS
47 
48 /* Headers */
49 #include <visp3/robot/vpRobotBiclops.h>
50 #include <visp3/robot/vpRobotBiclopsController.h>
51 #include <visp3/robot/vpRobotException.h>
52 
53 //#define VP_DEBUG // Activate the debug mode
54 //#define VP_DEBUG_MODE 20 // Activate debug level 1 and 2
55 
56 #include <visp3/core/vpDebug.h>
57 
58 
59 
60 /* ----------------------------------------------------------------------- */
61 /* --- CONSTRUCTOR ------------------------------------------------------ */
62 /* ---------------------------------------------------------------------- */
63 
67 vpRobotBiclopsController::vpRobotBiclopsController()
68  : biclops(), axisMask(0), panAxis(NULL), tiltAxis(NULL), vergeAxis(NULL),
69  panProfile(), tiltProfile(), vergeProfile(), shm(), stopControllerThread_(false)
70 {
71  axisMask = Biclops::PanMask
72  + Biclops::TiltMask
73  /*+ Biclops::VergeMask*/; // add this if you want verge.
74 
75 
76  // Set Debug level depending on how much info you want to see about
77  // the inner workings of the API. Level 2 is highest with 0 being
78  // the default (i.e., no messages).
79  biclops.SetDebugLevel(0);
80 
81  // initialize the shared data structure
82  for (unsigned int i=0; i < vpBiclops::ndof; i ++) {
83  shm.status[i] = STOP;
84  shm.q_dot[i] = 0.;
85  shm.actual_q[i] = 0.;
86  shm.jointLimit[i] = false;
87  shm.status[i] = STOP;
88  }
89 }
90 
96 vpRobotBiclopsController::~vpRobotBiclopsController()
97 {
98 }
99 
113 void
114 vpRobotBiclopsController::init(const std::string &configfile)
115 {
116  vpDEBUG_TRACE (12, "Initialize biclops.");
117  bool binit = false;
118  for (int i=0; i<1; i++) {
119  try {
120  std::cout << "Try to initialize biclops head " << std::endl;
121  binit = biclops.Initialize(configfile.c_str());
122  usleep(100000);
123  if (binit) {
124  // Initialization completed successfully. Close the config file.
125  std::cout << "Initialization succeed...\n";
126  break;
127  }
128  else {
129  std::cout << "Initialization failed...\n";
130  }
131  }
132  catch(...)
133  {
134  std::cout << "Initialization failed..."<< std::endl;
135  }
136  }
137 
138  if (! binit) {
139  std::cout << "Cannot initialize biclops head. " << std::endl;
140  std::cout << "Check if the serial cable is connected." << std::endl;
141  std::cout << "Check if the robot is powered on." << std::endl;
142  std::cout << "Check if you try to open the good serial port." << std::endl;
143  std::cout << "Try to power off/on and restart..." << std::endl;
144 
146  "Cannot initialize biclops head.");
147 
148  }
149 
150 
151  vpDEBUG_TRACE(12, "Biclops initialized");
152 
153  // Get shortcut references to each axis.
154  panAxis = biclops.GetAxis(Biclops::Pan);
155  tiltAxis = biclops.GetAxis(Biclops::Tilt);
156  if ((axisMask & Biclops::VergeMask) != 0)
157  vergeAxis = biclops.GetAxis(Biclops::Verge);
158 
159 #ifdef VISP_HAVE_BICLOPS_AND_GET_HOMED_STATE_FUNCTION // new API
160  if (!panAxis -> GetHomedState() || !tiltAxis -> GetHomedState()) {
161  vpDEBUG_TRACE(12, "Biclops is not homed");
162  }
163 #else // old API
164  if (!panAxis -> IsAlreadyHomed() || !tiltAxis -> IsAlreadyHomed()) {
165  vpDEBUG_TRACE(12, "Biclops is not homed");
166  }
167 #endif
168 
169  //Execute the homing sequence for all axes.
170  vpDEBUG_TRACE(12, "Execute the homing sequence for all axes");
171  vpDEBUG_TRACE(12, "Execute the homing sequence for all axes");
172  if ( biclops.HomeAxes(axisMask))
173  vpDEBUG_TRACE(12, "Homing sequence succeed.");
174  else {
175  vpERROR_TRACE("Homing sequence failed. Program is stopped");
177  "Cannot open connection with biclops");
178  }
179 
180  // Get the currently defined (default) motion profiles.
181  // PMDAxisControl::Profile panProfile,tiltProfile,vergeProfile;
182  panAxis->GetProfile(panProfile);
183  tiltAxis->GetProfile(tiltProfile);
184  if ((axisMask & Biclops::VergeMask) != 0)
185  vergeAxis->GetProfile(vergeProfile);
186 }
187 
203 void
204 vpRobotBiclopsController::setPosition(const vpColVector & q,
205  const double percentVelocity )
206 {
207  if (q.getRows() != vpBiclops::ndof )
208  {
209  vpERROR_TRACE ("Bad dimension for positioning vector.");
211  "Bad dimension for positioning vector.");
212  }
213 
214  panAxis -> SetProfileMode(PMDTrapezoidalProfile);
215  tiltAxis -> SetProfileMode(PMDTrapezoidalProfile);
216 
217  // Create the list of axes we want to coordinate
218  PMDUtils::AxisList axisList;
219  axisList.push_back(panAxis);
220  axisList.push_back(tiltAxis);
221 
222 #ifdef VISP_HAVE_BICLOPS_AND_GET_HOMED_STATE_FUNCTION // new API
223  // Get the currently defined (default) motion profiles.
224  //PMDAxisControl::Profile panProfile,tiltProfile;
225  panAxis->GetProfile(panProfile);
226  tiltAxis->GetProfile(tiltProfile);
227 
228  // Set a position to move to by modifying the respective profiles.
229  // NOTE: profile values are in revolutions, so here we convert
230  // from degrees (divide by 360) for readability.
231  panProfile.pos = PMDUtils::RadsToRevs(q[0]);
232  panProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit
233  * percentVelocity / 100.);
234 
235  tiltProfile.pos = PMDUtils::RadsToRevs(q[1]);
236  tiltProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit
237  * percentVelocity / 100.);
238 
239  // Inform the controller of the new desired position.
240  panAxis->SetProfile(panProfile);
241  tiltAxis->SetProfile(tiltProfile);
242 
243 #else // old API
244 
245  PMDAxisControl::CountsProfile desired_profile;
246 
247  // Set a position to move to by modifying the respective profiles.
248  // NOTE: profile values are in revolutions, so here we convert
249  // from degrees (divide by 360) for readability.
250  panProfile.pos = PMDUtils::RadsToRevs(q[0]);
251  panProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit
252  * percentVelocity / 100.);
253 
254  vpDEBUG_TRACE(12, "Speed percent: %lf",
255  vpBiclops::speedLimit * percentVelocity / 100.);
256 
257  panAxis -> ProfileToCounts(panProfile, desired_profile);
258  vpCDEBUG(12) << "desired_profile.pos: " << desired_profile.pos << std::endl;
259  vpCDEBUG(12) << "desired_profile.vel: " << desired_profile.vel << std::endl;
260 
261  panAxis -> SetProfile(desired_profile);
262 
263  // Set a position to move to by modifying the respective profiles.
264  // NOTE: profile values are in revolutions, so here we convert
265  // from degrees (divide by 360) for readability.
266  tiltProfile.pos = PMDUtils::RadsToRevs(q[1]);
267  tiltProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit
268  * percentVelocity / 100.);
269 
270  tiltAxis -> ProfileToCounts(tiltProfile, desired_profile);
271  vpCDEBUG(12) << "desired_profile.pos: " << desired_profile.pos << std::endl;
272  vpCDEBUG(12) << "desired_profile.vel: " << desired_profile.vel << std::endl;
273 
274  tiltAxis -> SetProfile(desired_profile);
275 #endif
276 
277  // Coordinate motion
278  PMDUtils::Coordinate(axisList);
279  biclops.Move(Biclops::PanMask + Biclops::TiltMask/*, 0*/); //
280 
281 }
282 
292 void
293 vpRobotBiclopsController::setVelocity(const vpColVector & q_dot)
294 {
295  if (q_dot.getRows() != vpBiclops::ndof )
296  {
297  vpERROR_TRACE ("Bad dimension for velocity vector.");
299  "Bad dimension for velocity vector.");
300  }
301 
302 
303 #ifdef VISP_HAVE_BICLOPS_AND_GET_HOMED_STATE_FUNCTION // new API
304  // Get the currently defined (default) motion profiles.
305  //PMDAxisControl::Profile panProfile, tiltProfile;
306  panAxis->GetProfile(panProfile);
307  tiltAxis->GetProfile(tiltProfile);
308 
309  // Set a position to move to by modifying the respective profiles.
310  // NOTE: profile values are in revolutions, so here we convert
311  // from degrees (divide by 360) for readability.
312  panProfile.vel = PMDUtils::RadsToRevs(q_dot[0]);
313  tiltProfile.vel = PMDUtils::RadsToRevs(q_dot[1]);
314 
315  // Inform the controller of the new desired position.
316  panAxis->SetProfile(panProfile);
317  tiltAxis->SetProfile(tiltProfile);
318 
319  panAxis -> SetProfileMode(PMDVelocityContouringProfile);
320  tiltAxis -> SetProfileMode(PMDVelocityContouringProfile);
321 #else // old API
322  panAxis -> SetProfileMode(PMDVelocityContouringProfile);
323  tiltAxis -> SetProfileMode(PMDVelocityContouringProfile);
324 \
325  PMDAxisControl::CountsProfile desired_profile;
326 
327  // Set a position to move to by modifying the respective profiles.
328  // NOTE: profile values are in revolutions, so here we convert
329  // from degrees (divide by 360) for readability.
330  panProfile.vel = PMDUtils::RadsToRevs(q_dot[0]);
331 
332  panAxis -> ProfileToCounts(panProfile, desired_profile);
333  panAxis -> SetProfile(desired_profile);
334 
335  // Set a position to move to by modifying the respective profiles.
336  // NOTE: profile values are in revolutions, so here we convert
337  // from degrees (divide by 360) for readability.
338  tiltProfile.vel = PMDUtils::RadsToRevs(q_dot[1]);
339 
340  tiltAxis -> ProfileToCounts(tiltProfile, desired_profile);
341  tiltAxis -> SetProfile(desired_profile);
342 #endif
343  // Coordinate motion
344  biclops.Move(Biclops::PanMask + Biclops::TiltMask, 0); //
345 }
346 
355 vpRobotBiclopsController::getPosition()
356 {
357  vpDEBUG_TRACE (12, "Start vpRobotBiclopsController::getPosition() ");
359  PMDint32 panpos, tiltpos;
360 
361  panAxis -> GetPosition(panpos);
362  tiltAxis -> GetPosition(tiltpos);
363 
364  q[0] = PMDUtils::RevsToRads(panAxis ->CountsToUnits(panpos));
365  q[1] = PMDUtils::RevsToRads(tiltAxis->CountsToUnits(tiltpos));
366 
367  vpCDEBUG(11) << "++++++++ Mesure : " << q.t();
368  vpDEBUG_TRACE (12, "End vpRobotBiclopsController::getPosition()");
369 
370  return q;
371 }
372 
381 vpRobotBiclopsController::getActualPosition()
382 {
384  PMDint32 panpos, tiltpos;
385 
386  panAxis -> GetActualPosition(panpos);
387  tiltAxis -> GetActualPosition(tiltpos);
388 
389  q[0] = PMDUtils::RevsToRads(panAxis ->CountsToUnits(panpos));
390  q[1] = PMDUtils::RevsToRads(tiltAxis->CountsToUnits(tiltpos));
391 
392  return q;
393 }
394 
403 vpRobotBiclopsController::getVelocity()
404 {
406  PMDint32 pan_vel, tilt_vel;
407 
408  panAxis -> GetVelocity(pan_vel);
409  tiltAxis -> GetVelocity(tilt_vel);
410 
411  q_dot[0] = PMDUtils::RevsToRads(panAxis ->CountsToUnits(pan_vel));
412  q_dot[1] = PMDUtils::RevsToRads(tiltAxis->CountsToUnits(tilt_vel));
413 
414  return q_dot;
415 }
416 
425 vpRobotBiclopsController::getActualVelocity()
426 {
428  PMDint32 pan_vel, tilt_vel;
429 
430  panAxis -> GetActualVelocity(pan_vel);
431  tiltAxis -> GetActualVelocity(tilt_vel);
432 
433  q_dot[0] = PMDUtils::RevsToRads(panAxis ->CountsToUnits(pan_vel));
434  q_dot[1] = PMDUtils::RevsToRads(tiltAxis->CountsToUnits(tilt_vel));
435 
436  return q_dot;
437 }
438 
445 void
446 vpRobotBiclopsController::writeShm(shmType &shm_)
447 {
448  for(unsigned int i=0; i < vpBiclops::ndof; i ++) {
449  vpDEBUG_TRACE(13, "q_dot[%d]=%f", i, shm_.q_dot[i]);
450  }
451  memcpy(&this->shm, &shm_, sizeof(shmType));
452  //this->shm = shm_;
453  for(unsigned int i=0; i < vpBiclops::ndof; i ++) {
454  vpDEBUG_TRACE(13, "shm.q_dot[%d]=%f", i, shm.q_dot[i]);
455  }
456 }
457 
464 vpRobotBiclopsController::shmType
465 vpRobotBiclopsController::readShm()
466 {
467  shmType tmp_shm;
468 
469  for(unsigned int i=0; i < vpBiclops::ndof; i ++) {
470  vpDEBUG_TRACE(13, "shm.q_dot[%d]=%f", i, shm.q_dot[i]);
471  }
472  memcpy(&tmp_shm, &this->shm, sizeof(shmType));
473  //tmp_shm = shm;
474  for(unsigned int i=0; i < vpBiclops::ndof; i ++) {
475  vpDEBUG_TRACE(13, "tmp_shm.q_dot[%d]=%f", i, tmp_shm.q_dot[i]);
476  }
477 
478  return tmp_shm;
479 }
480 
481 #elif !defined(VISP_BUILD_SHARED_LIBS)
482 // Work arround to avoid warning: libvisp_robot.a(vpRobotBiclopsController.cpp.o) has no symbols
483 void dummy_vpRobotBiclopsController() {};
484 #endif
485 
486 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
487 
Error that can be emited by the vpRobot class and its derivates.
static const unsigned int ndof
Definition: vpBiclops.h:123
static const float speedLimit
Definition: vpBiclops.h:130
#define vpERROR_TRACE
Definition: vpDebug.h:391
vpRowVector t() const
#define vpCDEBUG(level)
Definition: vpDebug.h:502
unsigned int getRows() const
Return the number of rows of the 2D array.
Definition: vpArray2D.h:152
Implementation of column vector and the associated operations.
Definition: vpColVector.h:72
#define vpDEBUG_TRACE
Definition: vpDebug.h:478