34 #include <visp3/core/vpConfig.h>
36 #if defined(VISP_HAVE_BICLOPS) && defined(VISP_HAVE_THREADS)
45 #include <visp3/core/vpExponentialMap.h>
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/core/vpTime.h>
48 #include <visp3/robot/vpBiclops.h>
49 #include <visp3/robot/vpRobotBiclops.h>
50 #include <visp3/robot/vpRobotException.h>
52 #include "private/vpRobotBiclopsController_impl.h"
56 #include <visp3/core/vpDebug.h>
65 static std::mutex m_mutex_end_thread;
66 static std::mutex m_mutex_shm;
67 static std::mutex m_mutex_measure;
74 :
vpBiclops(),
vpRobot(), m_control_thread(), m_positioningVelocity(defaultPositioningVelocity),
77 vpDEBUG_TRACE(12,
"Begin default constructor.");
79 m_controller =
new vpRobotBiclopsController;
84 :
vpBiclops(),
vpRobot(), m_control_thread(), m_positioningVelocity(defaultPositioningVelocity),
87 vpDEBUG_TRACE(12,
"Begin default constructor.");
89 m_controller =
new vpRobotBiclopsController;
97 vpDEBUG_TRACE(12,
"Start vpRobotBiclops::~vpRobotBiclops()");
100 vpDEBUG_TRACE(12,
"Unlock mutex vpEndThread_mutex");
101 m_mutex_end_thread.unlock();
104 vpDEBUG_TRACE(12,
"Wait end of control thread");
106 if (m_control_thread.joinable()) {
107 m_control_thread.join();
111 vpDEBUG_TRACE(12,
"Stop vpRobotBiclops::~vpRobotBiclops()");
119 FILE *fd = fopen(m_configfile.c_str(),
"r");
121 vpCERROR <<
"Cannot open Biclops config file: " << m_configfile << std::endl;
127 m_controller->init(m_configfile);
133 vpERROR_TRACE(
"Error caught");
146 vpRobotBiclopsController *controller =
static_cast<vpRobotBiclopsController *
>(arg);
150 vpRobotBiclopsController::shmType shm;
152 vpDEBUG_TRACE(10,
"Start control loop");
170 vpDEBUG_TRACE(11,
"Lock mutex vpShm_mutex");
173 shm = controller->readShm();
175 vpDEBUG_TRACE(11,
"unlock mutex vpShm_mutex");
176 m_mutex_shm.unlock();
179 prev_q_dot[i] = shm.q_dot[i];
180 new_q_dot[i] =
false;
181 change_dir[i] =
false;
182 force_halt[i] =
false;
183 enable_limit[i] =
true;
187 mes_q = controller->getActualPosition();
188 mes_q_dot = controller->getActualVelocity();
190 vpDEBUG_TRACE(11,
"Lock mutex vpShm_mutex");
193 shm = controller->readShm();
196 shm.actual_q[i] = mes_q[i];
197 shm.actual_q_dot[i] = mes_q_dot[i];
200 controller->writeShm(shm);
202 vpDEBUG_TRACE(11,
"unlock mutex vpShm_mutex");
203 m_mutex_shm.unlock();
205 vpDEBUG_TRACE(11,
"unlock mutex vpMeasure_mutex");
206 m_mutex_measure.unlock();
208 while (!controller->isStopRequested()) {
211 mes_q = controller->getActualPosition();
212 mes_q_dot = controller->getActualVelocity();
214 vpDEBUG_TRACE(11,
"Lock mutex vpShm_mutex");
217 shm = controller->readShm();
221 shm.actual_q[i] = mes_q[i];
222 shm.actual_q_dot[i] = mes_q_dot[i];
232 if (mes_q[i] < -softLimit[i]) {
233 vpDEBUG_TRACE(12,
"Axe %d in low joint limit", i);
234 shm.status[i] = vpRobotBiclopsController::STOP;
235 shm.jointLimit[i] =
true;
237 else if (mes_q[i] > softLimit[i]) {
238 vpDEBUG_TRACE(12,
"Axe %d in hight joint limit", i);
239 shm.status[i] = vpRobotBiclopsController::STOP;
240 shm.jointLimit[i] =
true;
243 shm.status[i] = vpRobotBiclopsController::SPEED;
244 shm.jointLimit[i] =
false;
249 if (std::fabs(shm.q_dot[i] - prev_q_dot[i]) >
250 std::fabs(
vpMath::maximum(shm.q_dot[i], prev_q_dot[i])) * std::numeric_limits<double>::epsilon())
253 new_q_dot[i] =
false;
256 if ((shm.q_dot[i] * prev_q_dot[i]) < 0.)
257 change_dir[i] =
true;
259 change_dir[i] =
false;
261 vpDEBUG_TRACE(13,
"status : %d %d", shm.status[0], shm.status[1]);
262 vpDEBUG_TRACE(13,
"joint : %d %d", shm.jointLimit[0], shm.jointLimit[1]);
263 vpDEBUG_TRACE(13,
"new q_dot : %d %d", new_q_dot[0], new_q_dot[1]);
264 vpDEBUG_TRACE(13,
"new dir : %d %d", change_dir[0], change_dir[1]);
265 vpDEBUG_TRACE(13,
"force halt : %d %d", force_halt[0], force_halt[1]);
266 vpDEBUG_TRACE(13,
"enable limit: %d %d", enable_limit[0], enable_limit[1]);
268 bool updateVelocity =
false;
273 if (shm.status[i] == vpRobotBiclopsController::STOP) {
275 if (change_dir[i] ==
false) {
278 if (enable_limit[i] ==
true) {
281 if (force_halt[i] ==
false) {
283 force_halt[i] =
true;
284 updateVelocity =
true;
290 q_dot[i] = shm.q_dot[i];
291 shm.status[i] = vpRobotBiclopsController::SPEED;
292 force_halt[i] =
false;
293 updateVelocity =
true;
298 if (enable_limit[i] ==
true) {
300 q_dot[i] = shm.q_dot[i];
301 shm.status[i] = vpRobotBiclopsController::SPEED;
302 force_halt[i] =
false;
303 enable_limit[i] =
false;
304 updateVelocity =
true;
309 if (force_halt[i] ==
false) {
311 force_halt[i] =
true;
312 enable_limit[i] =
true;
313 updateVelocity =
true;
322 q_dot[i] = shm.q_dot[i];
323 shm.status[i] = vpRobotBiclopsController::SPEED;
324 enable_limit[i] =
true;
325 updateVelocity =
true;
331 if (shm.status[i] == vpRobotBiclopsController::STOP) {
332 if (enable_limit[i] ==
true) {
335 if (force_halt[i] ==
false) {
338 force_halt[i] =
true;
339 updateVelocity =
true;
345 enable_limit[i] =
true;
350 controller->writeShm(shm);
352 vpDEBUG_TRACE(11,
"unlock mutex vpShm_mutex");
353 m_mutex_shm.unlock();
355 if (updateVelocity) {
359 controller->setVelocity(q_dot);
364 prev_q_dot[i] = shm.q_dot[i];
369 controller->stopRequest(
false);
371 vpDEBUG_TRACE(10,
"End of the control thread: stop the robot");
373 controller->setVelocity(q_dot);
378 delete[] enable_limit;
379 vpDEBUG_TRACE(11,
"unlock vpEndThread_mutex");
380 m_mutex_end_thread.unlock();
394 vpDEBUG_TRACE(12,
"Speed to position control.");
403 vpDEBUG_TRACE(12,
"Lock mutex vpEndThread_mutex");
404 m_mutex_end_thread.lock();
406 vpDEBUG_TRACE(12,
"Create speed control thread");
410 vpDEBUG_TRACE(12,
"Speed control thread created");
425 m_controller->setVelocity(q_dot);
427 m_controller->stopRequest(
true);
458 if (velocity < 0 || velocity > 100) {
459 vpERROR_TRACE(
"Bad positioning velocity");
463 m_positioningVelocity = velocity;
472 vpERROR_TRACE(
"Robot was not in position-based control\n"
473 "Modification of the robot state");
498 vpDEBUG_TRACE(12,
"Lock mutex vpEndThread_mutex");
499 m_mutex_end_thread.lock();
500 m_controller->setPosition(q, m_positioningVelocity);
501 vpDEBUG_TRACE(12,
"Unlock mutex vpEndThread_mutex");
502 m_mutex_end_thread.unlock();
516 vpERROR_TRACE(
"Error caught");
525 vpERROR_TRACE(
"Cannot get Biclops position from file");
560 q = m_controller->getPosition();
568 vpDEBUG_TRACE(12,
"Lock mutex vpMeasure_mutex");
569 m_mutex_measure.lock();
571 vpRobotBiclopsController::shmType shm;
573 vpDEBUG_TRACE(12,
"Lock mutex vpShm_mutex");
576 shm = m_controller->readShm();
578 vpDEBUG_TRACE(12,
"unlock mutex vpShm_mutex");
579 m_mutex_shm.unlock();
582 q[i] = shm.actual_q[i];
585 vpCDEBUG(11) <<
"++++++++ Measure actuals: " << q.
t();
587 vpDEBUG_TRACE(12,
"unlock mutex vpMeasure_mutex");
588 m_mutex_measure.unlock();
597 vpERROR_TRACE(
"Cannot send a velocity to the robot "
598 "use setRobotState(vpRobot::STATE_VELOCITY_CONTROL) first) ");
600 "Cannot send a velocity to the robot "
601 "use setRobotState(vpRobot::STATE_VELOCITY_CONTROL) first) ");
607 "in the camera frame:"
608 "functionality not implemented");
619 "in the reference frame:"
620 "functionality not implemented");
625 "functionality not implemented");
629 "in the end-effector frame:"
630 "functionality not implemented");
637 vpDEBUG_TRACE(12,
"Velocity limitation.");
649 if (fabs(q_dot[i]) > max) {
651 max = fabs(q_dot[i]);
652 vpERROR_TRACE(
"Excess velocity: ROTATION "
660 q_dot_sat = q_dot * max;
663 vpCDEBUG(12) <<
"send velocity: " << q_dot_sat.
t() << std::endl;
665 vpRobotBiclopsController::shmType shm;
667 vpDEBUG_TRACE(12,
"Lock mutex vpShm_mutex");
670 shm = m_controller->readShm();
673 shm.q_dot[i] = q_dot[i];
675 m_controller->writeShm(shm);
677 vpDEBUG_TRACE(12,
"unlock mutex vpShm_mutex");
678 m_mutex_shm.unlock();
712 q_dot = m_controller->getVelocity();
720 vpDEBUG_TRACE(12,
"Lock mutex vpMeasure_mutex");
721 m_mutex_measure.lock();
723 vpRobotBiclopsController::shmType shm;
725 vpDEBUG_TRACE(12,
"Lock mutex vpShm_mutex");
728 shm = m_controller->readShm();
730 vpDEBUG_TRACE(12,
"unlock mutex vpShm_mutex");
731 m_mutex_shm.unlock();
734 q_dot[i] = shm.actual_q_dot[i];
737 vpCDEBUG(11) <<
"++++++++ Velocity actuals: " << q_dot.
t();
739 vpDEBUG_TRACE(12,
"unlock mutex vpMeasure_mutex");
740 m_mutex_measure.unlock();
756 std::ifstream fd(filename.c_str(), std::ios::in);
763 std::string key(
"R:");
764 std::string id(
"#PTU-EVI - Position");
765 bool pos_found =
false;
770 while (std::getline(fd, line)) {
773 if (!(line.compare(0,
id.size(),
id) == 0)) {
774 std::cout <<
"Error: this position file " << filename <<
" is not for Biclops robot" << std::endl;
778 if ((line.compare(0, 1,
"#") == 0)) {
781 if ((line.compare(0, key.size(), key) == 0)) {
789 std::istringstream ss(line);
805 std::cout <<
"Error: unable to find a position for Biclops robot in " << filename << std::endl;
821 d = q_current - m_q_previous;
833 c_previousMc_current = fMc_previous.
inverse() * fMc_current;
842 "functionality not implemented");
846 "functionality not implemented");
850 "functionality not implemented");
854 m_q_previous = q_current;
857 #elif !defined(VISP_BUILD_SHARED_LIBS)
859 void dummy_vpRobotBiclops() { };
unsigned int getRows() const
Jacobian, geometric model functionalities... for Biclops, pan, tilt head.
static const float speedLimit
Pan and tilt axis max velocity in rad/s to perform a displacement.
static const float tiltJointLimit
Tilt axis +/- joint limit in rad.
void get_fJe(const vpColVector &q, vpMatrix &fJe) const
void get_fMc(const vpColVector &q, vpHomogeneousMatrix &fMc) const
vpHomogeneousMatrix get_cMe() const
static const float panJointLimit
Pan axis +/- joint limit in rad.
static const unsigned int ndof
Number of dof.
void get_eJe(const vpColVector &q, vpMatrix &eJe) const
Implementation of column vector and the associated operations.
void resize(unsigned int i, bool flagNullify=true)
static vpColVector inverse(const vpHomogeneousMatrix &M)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
static double rad(double deg)
static Type maximum(const Type &a, const Type &b)
static double deg(double rad)
Implementation of a matrix and operations on matrices.
void setPositioningVelocity(double velocity)
virtual ~vpRobotBiclops()
double getPositioningVelocity(void)
void getDisplacement(const vpRobot::vpControlFrameType frame, vpColVector &d) VP_OVERRIDE
void getVelocity(const vpRobot::vpControlFrameType frame, vpColVector &q_dot)
void get_eJe(vpMatrix &eJe) VP_OVERRIDE
bool readPositionFile(const std::string &filename, vpColVector &q)
void get_cVe(vpVelocityTwistMatrix &cVe) const
vpRobot::vpRobotStateType setRobotState(const vpRobot::vpRobotStateType newState) VP_OVERRIDE
void get_fJe(vpMatrix &fJe) VP_OVERRIDE
void getPosition(const vpRobot::vpControlFrameType frame, vpColVector &q) VP_OVERRIDE
static const double defaultPositioningVelocity
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &q_dot) VP_OVERRIDE
void setConfigFile(const std::string &filename="/usr/share/BiclopsDefault.cfg")
static void vpRobotBiclopsSpeedControlLoop(void *arg)
void setPosition(const vpRobot::vpControlFrameType frame, const vpColVector &q) VP_OVERRIDE
Error that can be emitted by the vpRobot class and its derivatives.
@ wrongStateError
Wrong robot state.
@ constructionError
Error from constructor.
@ readingParametersError
Cannot parse parameters.
Class that defines a generic virtual robot.
vpMatrix eJe
robot Jacobian expressed in the end-effector frame
virtual vpRobotStateType getRobotState(void) const
@ STATE_POSITION_CONTROL
Initialize the position controller.
@ STATE_VELOCITY_CONTROL
Initialize the velocity controller.
@ STATE_ACCELERATION_CONTROL
Initialize the acceleration controller.
@ STATE_STOP
Stops robot motion especially in velocity and acceleration control.
vpMatrix fJe
robot Jacobian expressed in the robot reference frame available
virtual vpRobotStateType setRobotState(const vpRobot::vpRobotStateType newState)
vpVelocityTwistMatrix & buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
VISP_EXPORT int wait(double t0, double t)