Visual Servoing Platform  version 3.6.1 under development (2023-10-20)
vpRobotBiclopsController.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
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 https://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 
34 #include <signal.h>
35 #include <string.h>
36 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
37 #include <unistd.h>
38 #endif
39 #include <visp3/core/vpConfig.h>
40 
41 #ifndef DOXYGEN_SHOULD_SKIP_THIS
42 #ifdef VISP_HAVE_BICLOPS
43 
44 /* Headers */
45 #include <visp3/robot/vpRobotBiclops.h>
46 #include <visp3/robot/vpRobotBiclopsController.h>
47 #include <visp3/robot/vpRobotException.h>
48 
49 //#define VP_DEBUG // Activate the debug mode
50 //#define VP_DEBUG_MODE 20 // Activate debug level 1 and 2
51 
52 #include <visp3/core/vpDebug.h>
53 
54 vpRobotBiclopsController::vpRobotBiclopsController()
55  : m_biclops(), m_axisMask(0), m_panAxis(NULL), m_tiltAxis(NULL), m_vergeAxis(NULL), m_panProfile(), m_tiltProfile(),
56  m_vergeProfile(), m_shm(), m_stopControllerThread(false)
57 {
58  m_axisMask = Biclops::PanMask + Biclops::TiltMask; //+ Biclops::VergeMask*/; // add this if you want verge.
59 
60  // Set Debug level depending on how much info you want to see about
61  // the inner workings of the API. Level 2 is highest with 0 being
62  // the default (i.e., no messages).
63  m_biclops.SetDebugLevel(0);
64 
65  // initialize the shared data structure
66  for (unsigned int i = 0; i < vpBiclops::ndof; i++) {
67  m_shm.status[i] = STOP;
68  m_shm.q_dot[i] = 0.;
69  m_shm.actual_q[i] = 0.;
70  m_shm.jointLimit[i] = false;
71  m_shm.status[i] = STOP;
72  }
73 }
74 
75 vpRobotBiclopsController::~vpRobotBiclopsController() { }
76 
77 void vpRobotBiclopsController::init(const std::string &configfile)
78 {
79  vpDEBUG_TRACE(12, "Initialize Biclops.");
80  bool binit = false;
81  for (int i = 0; i < 1; i++) {
82  try {
83  std::cout << "Try to initialize Biclops head " << std::endl;
84  binit = m_biclops.Initialize(configfile.c_str());
85  usleep(100000);
86  if (binit) {
87  // Initialization completed successfully. Close the config file.
88  std::cout << "Initialization succeed...\n";
89  break;
90  }
91  else {
92  std::cout << "Initialization failed...\n";
93  }
94  }
95  catch (...) {
96  std::cout << "Initialization failed..." << std::endl;
97  }
98  }
99 
100  if (!binit) {
101  std::cout << "Cannot initialize Biclops head. " << std::endl;
102  std::cout << "Check if the serial cable is connected." << std::endl;
103  std::cout << "Check if the robot is powered on." << std::endl;
104  std::cout << "Check if you try to open the good serial port." << std::endl;
105  std::cout << "Try to power off/on and restart..." << std::endl;
106 
107  throw vpRobotException(vpRobotException::notInitializedError, "Cannot initialize Biclops head.");
108  }
109 
110  vpDEBUG_TRACE(12, "Biclops initialized");
111 
112  // Get shortcut references to each axis.
113  m_panAxis = m_biclops.GetAxis(Biclops::Pan);
114  m_tiltAxis = m_biclops.GetAxis(Biclops::Tilt);
115  if ((m_axisMask & Biclops::VergeMask) != 0)
116  m_vergeAxis = m_biclops.GetAxis(Biclops::Verge);
117 
118 #ifdef VISP_HAVE_BICLOPS_AND_GET_HOMED_STATE_FUNCTION // new API
119  if (!m_panAxis->GetHomedState() || !m_tiltAxis->GetHomedState()) {
120  vpDEBUG_TRACE(12, "Biclops is not homed");
121  }
122 #else // old API
123  if (!m_panAxis->IsAlreadyHomed() || !m_tiltAxis->IsAlreadyHomed()) {
124  vpDEBUG_TRACE(12, "Biclops is not homed");
125  }
126 #endif
127 
128  // Execute the homing sequence for all axes.
129  vpDEBUG_TRACE(12, "Execute the homing sequence for all axes");
130  vpDEBUG_TRACE(12, "Execute the homing sequence for all axes");
131  if (m_biclops.HomeAxes(m_axisMask))
132  vpDEBUG_TRACE(12, "Homing sequence succeed.");
133  else {
134  vpERROR_TRACE("Homing sequence failed. Program is stopped");
135  throw vpRobotException(vpRobotException::constructionError, "Cannot open connection with Biclops");
136  }
137 
138  // Get the currently defined (default) motion profiles.
139  // PMDAxisControl::Profile m_panProfile,m_tiltProfile,m_vergeProfile;
140  m_panAxis->GetProfile(m_panProfile);
141  m_tiltAxis->GetProfile(m_tiltProfile);
142  if ((m_axisMask & Biclops::VergeMask) != 0)
143  m_vergeAxis->GetProfile(m_vergeProfile);
144 }
145 
146 void vpRobotBiclopsController::setPosition(const vpColVector &q, double percentVelocity)
147 {
148  if (q.getRows() != vpBiclops::ndof) {
149  vpERROR_TRACE("Bad dimension for positioning vector.");
150  throw vpRobotException(vpRobotException::lowLevelError, "Bad dimension for positioning vector.");
151  }
152 
153  m_panAxis->SetProfileMode(PMDTrapezoidalProfile);
154  m_tiltAxis->SetProfileMode(PMDTrapezoidalProfile);
155 
156  // Create the list of axes we want to coordinate
157  PMDUtils::AxisList axisList;
158  axisList.push_back(m_panAxis);
159  axisList.push_back(m_tiltAxis);
160 
161 #ifdef VISP_HAVE_BICLOPS_AND_GET_HOMED_STATE_FUNCTION // new API
162  // Get the currently defined (default) motion profiles.
163  // PMDAxisControl::Profile m_panProfile,m_tiltProfile;
164  m_panAxis->GetProfile(m_panProfile);
165  m_tiltAxis->GetProfile(m_tiltProfile);
166 
167  // Set a position to move to by modifying the respective profiles.
168  // NOTE: profile values are in revolutions, so here we convert
169  // from degrees (divide by 360) for readability.
170  m_panProfile.pos = PMDUtils::RadsToRevs(q[0]);
171  m_panProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit * percentVelocity / 100.);
172 
173  m_tiltProfile.pos = PMDUtils::RadsToRevs(q[1]);
174  m_tiltProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit * percentVelocity / 100.);
175 
176  // Inform the controller of the new desired position.
177  m_panAxis->SetProfile(m_panProfile);
178  m_tiltAxis->SetProfile(m_tiltProfile);
179 
180 #else // old API
181 
182  PMDAxisControl::CountsProfile desired_profile;
183 
184  // Set a position to move to by modifying the respective profiles.
185  // NOTE: profile values are in revolutions, so here we convert
186  // from degrees (divide by 360) for readability.
187  m_panProfile.pos = PMDUtils::RadsToRevs(q[0]);
188  m_panProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit * percentVelocity / 100.);
189 
190  vpDEBUG_TRACE(12, "Speed percent: %lf", vpBiclops::speedLimit * percentVelocity / 100.);
191 
192  m_panAxis->ProfileToCounts(m_panProfile, desired_profile);
193  vpCDEBUG(12) << "desired_profile.pos: " << desired_profile.pos << std::endl;
194  vpCDEBUG(12) << "desired_profile.vel: " << desired_profile.vel << std::endl;
195 
196  m_panAxis->SetProfile(desired_profile);
197 
198  // Set a position to move to by modifying the respective profiles.
199  // NOTE: profile values are in revolutions, so here we convert
200  // from degrees (divide by 360) for readability.
201  m_tiltProfile.pos = PMDUtils::RadsToRevs(q[1]);
202  m_tiltProfile.vel = PMDUtils::RadsToRevs(vpBiclops::speedLimit * percentVelocity / 100.);
203 
204  m_tiltAxis->ProfileToCounts(m_tiltProfile, desired_profile);
205  vpCDEBUG(12) << "desired_profile.pos: " << desired_profile.pos << std::endl;
206  vpCDEBUG(12) << "desired_profile.vel: " << desired_profile.vel << std::endl;
207 
208  m_tiltAxis->SetProfile(desired_profile);
209 #endif
210 
211  // Coordinate motion
212  PMDUtils::Coordinate(axisList);
213  m_biclops.Move(Biclops::PanMask + Biclops::TiltMask /*, 0*/); //
214 }
215 
216 void vpRobotBiclopsController::setVelocity(const vpColVector &q_dot)
217 {
218  if (q_dot.getRows() != vpBiclops::ndof) {
219  vpERROR_TRACE("Bad dimension for velocity vector.");
220  throw vpRobotException(vpRobotException::lowLevelError, "Bad dimension for velocity vector.");
221  }
222 
223 #ifdef VISP_HAVE_BICLOPS_AND_GET_HOMED_STATE_FUNCTION // new API
224  // Get the currently defined (default) motion profiles.
225  // PMDAxisControl::Profile m_panProfile, m_tiltProfile;
226  m_panAxis->GetProfile(m_panProfile);
227  m_tiltAxis->GetProfile(m_tiltProfile);
228 
229  // Set a position to move to by modifying the respective profiles.
230  // NOTE: profile values are in revolutions, so here we convert
231  // from degrees (divide by 360) for readability.
232  m_panProfile.vel = PMDUtils::RadsToRevs(q_dot[0]);
233  m_tiltProfile.vel = PMDUtils::RadsToRevs(q_dot[1]);
234 
235  // Inform the controller of the new desired position.
236  m_panAxis->SetProfile(m_panProfile);
237  m_tiltAxis->SetProfile(m_tiltProfile);
238 
239  m_panAxis->SetProfileMode(PMDVelocityContouringProfile);
240  m_tiltAxis->SetProfileMode(PMDVelocityContouringProfile);
241 #else // old API
242  m_panAxis->SetProfileMode(PMDVelocityContouringProfile);
243  m_tiltAxis->SetProfileMode(PMDVelocityContouringProfile);
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  m_panProfile.vel = PMDUtils::RadsToRevs(q_dot[0]);
251 
252  m_panAxis->ProfileToCounts(m_panProfile, desired_profile);
253  m_panAxis->SetProfile(desired_profile);
254 
255  // Set a position to move to by modifying the respective profiles.
256  // NOTE: profile values are in revolutions, so here we convert
257  // from degrees (divide by 360) for readability.
258  m_tiltProfile.vel = PMDUtils::RadsToRevs(q_dot[1]);
259 
260  m_tiltAxis->ProfileToCounts(m_tiltProfile, desired_profile);
261  m_tiltAxis->SetProfile(desired_profile);
262 #endif
263  // Coordinate motion
264  m_biclops.Move(Biclops::PanMask + Biclops::TiltMask, 0); //
265 }
266 
267 vpColVector vpRobotBiclopsController::getPosition()
268 {
269  vpDEBUG_TRACE(12, "Start vpRobotBiclopsController::getPosition() ");
271  PMDint32 panpos, tiltpos;
272 
273  m_panAxis->GetPosition(panpos);
274  m_tiltAxis->GetPosition(tiltpos);
275 
276  q[0] = PMDUtils::RevsToRads(m_panAxis->CountsToUnits(panpos));
277  q[1] = PMDUtils::RevsToRads(m_tiltAxis->CountsToUnits(tiltpos));
278 
279  vpCDEBUG(11) << "++++++++ Mesure : " << q.t();
280  vpDEBUG_TRACE(12, "End vpRobotBiclopsController::getPosition()");
281 
282  return q;
283 }
284 
285 vpColVector vpRobotBiclopsController::getActualPosition()
286 {
288  PMDint32 panpos, tiltpos;
289 
290  m_panAxis->GetActualPosition(panpos);
291  m_tiltAxis->GetActualPosition(tiltpos);
292 
293  q[0] = PMDUtils::RevsToRads(m_panAxis->CountsToUnits(panpos));
294  q[1] = PMDUtils::RevsToRads(m_tiltAxis->CountsToUnits(tiltpos));
295 
296  return q;
297 }
298 
299 vpColVector vpRobotBiclopsController::getVelocity()
300 {
302  PMDint32 pan_vel, tilt_vel;
303 
304  m_panAxis->GetVelocity(pan_vel);
305  m_tiltAxis->GetVelocity(tilt_vel);
306 
307  q_dot[0] = PMDUtils::RevsToRads(m_panAxis->CountsToUnits(pan_vel));
308  q_dot[1] = PMDUtils::RevsToRads(m_tiltAxis->CountsToUnits(tilt_vel));
309 
310  return q_dot;
311 }
312 
313 vpColVector vpRobotBiclopsController::getActualVelocity()
314 {
316  PMDint32 pan_vel, tilt_vel;
317 
318  m_panAxis->GetActualVelocity(pan_vel);
319  m_tiltAxis->GetActualVelocity(tilt_vel);
320 
321  q_dot[0] = PMDUtils::RevsToRads(m_panAxis->CountsToUnits(pan_vel));
322  q_dot[1] = PMDUtils::RevsToRads(m_tiltAxis->CountsToUnits(tilt_vel));
323 
324  return q_dot;
325 }
326 
327 void vpRobotBiclopsController::writeShm(shmType &shm)
328 {
329  for (unsigned int i = 0; i < vpBiclops::ndof; i++) {
330  vpDEBUG_TRACE(13, "q_dot[%d]=%f", i, m_shm.q_dot[i]);
331  }
332  memcpy(&this->m_shm, &shm, sizeof(shmType));
333  for (unsigned int i = 0; i < vpBiclops::ndof; i++) {
334  vpDEBUG_TRACE(13, "shm.q_dot[%d]=%f", i, m_shm.q_dot[i]);
335  }
336 }
337 
338 vpRobotBiclopsController::shmType vpRobotBiclopsController::readShm()
339 {
340  shmType tmp_shm;
341 
342  for (unsigned int i = 0; i < vpBiclops::ndof; i++) {
343  vpDEBUG_TRACE(13, "shm.q_dot[%d]=%f", i, m_shm.q_dot[i]);
344  }
345  memcpy(&tmp_shm, &this->m_shm, sizeof(shmType));
346  for (unsigned int i = 0; i < vpBiclops::ndof; i++) {
347  vpDEBUG_TRACE(13, "tmp_shm.q_dot[%d]=%f", i, tmp_shm.q_dot[i]);
348  }
349 
350  return tmp_shm;
351 }
352 
353 #elif !defined(VISP_BUILD_SHARED_LIBS)
354 // Work around to avoid warning:
355 // libvisp_robot.a(vpRobotBiclopsController.cpp.o) has no symbols
356 void dummy_vpRobotBiclopsController() { };
357 #endif
358 
359 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
unsigned int getRows() const
Definition: vpArray2D.h:290
static const float speedLimit
Pan and tilt axis max velocity in rad/s to perform a displacement.
Definition: vpBiclops.h:105
static const unsigned int ndof
Number of dof.
Definition: vpBiclops.h:99
Implementation of column vector and the associated operations.
Definition: vpColVector.h:167
vpRowVector t() const
Error that can be emitted by the vpRobot class and its derivatives.
@ constructionError
Error from constructor.
@ notInitializedError
Cannot initialize the robot.
@ lowLevelError
Error thrown by the low level sdk.
#define vpCDEBUG(level)
Definition: vpDebug.h:506
#define vpDEBUG_TRACE
Definition: vpDebug.h:482
#define vpERROR_TRACE
Definition: vpDebug.h:388