1 /**************************************************************************** 2 * 3 * ViSP, open source Visual Servoing Platform software. 4 * Copyright (C) 2005 - 2019 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 http://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 * Basic class used to make robot simulators. 33 * 34 * Authors: 35 * Nicolas Melchior 36 * 37 *****************************************************************************/ 38 39 #ifndef vpRobotWireFrameSimulator_HH 40 #define vpRobotWireFrameSimulator_HH 41 42 /*! 43 \file vpRobotWireFrameSimulator.h 44 \brief Basic class used to make robot simulators. 45 */ 46 47 #include <visp3/core/vpConfig.h> 48 49 #if defined(VISP_HAVE_MODULE_GUI) && ((defined(_WIN32) && !defined(WINRT_8_0)) || defined(VISP_HAVE_PTHREAD)) 50 51 #include <cmath> // std::fabs 52 #include <limits> // numeric_limits 53 #if defined(_WIN32) 54 // Include WinSock2.h before windows.h to ensure that winsock.h is not 55 // included by windows.h since winsock.h and winsock2.h are incompatible 56 #include <WinSock2.h> 57 #include <windows.h> 58 #elif defined(VISP_HAVE_PTHREAD) 59 #include <pthread.h> 60 #endif 61 62 #include <visp3/gui/vpDisplayD3D.h> 63 #include <visp3/gui/vpDisplayGDI.h> 64 #include <visp3/gui/vpDisplayGTK.h> 65 #include <visp3/gui/vpDisplayOpenCV.h> 66 #include <visp3/gui/vpDisplayX.h> 67 #include <visp3/robot/vpRobot.h> 68 #include <visp3/robot/vpRobotSimulator.h> 69 #include <visp3/robot/vpWireFrameSimulator.h> 70 71 /*! 72 \class vpRobotWireFrameSimulator 73 74 \ingroup group_robot_simu_gantry group_robot_simu_arm 75 76 \brief This class aims to be a basis used to create all the 77 simulators of robots. 78 79 Thus in this class you will find all the parameters and methods 80 which are necessary to create a simulator. Several methods are pure 81 virtual. In this case it means that they are specific to the each 82 robot, for example the computation of the geometrical model. 83 84 \warning This class uses threading capabilities. Thus on Unix-like 85 platforms, the libpthread third-party library need to be 86 installed. On Windows, we use the native threading capabilities. 87 */ 88 class VISP_EXPORT vpRobotWireFrameSimulator : protected vpWireFrameSimulator, public vpRobotSimulator 89 { 90 public: 91 vpImage<vpRGBa> I; 92 93 typedef enum { MODEL_3D, MODEL_DH } vpDisplayRobotType; 94 95 protected: 96 /*! cpu time at the begining of the robot's movement*/ 97 double tcur; 98 /*! cpu time at the end of the last robot's movement*/ 99 double tprev; 100 101 /*! Contains the 3D model of the robot's arms*/ 102 Bound_scene *robotArms; 103 104 /*! Size of the fMi table*/ 105 unsigned int size_fMi; 106 /*! Table containing all the homogeneous matrices between the reference 107 frame of the robot and the frames you used to compute the Denavit-Hartenberg 108 representation 109 110 If you use a camera at the end of the effector, the last homogeneous matrix 111 has to be the one between the reference frame and the camera frame (fMc)*/ 112 vpHomogeneousMatrix *fMi; 113 114 /*! The articular coordinates*/ 115 vpColVector artCoord; 116 /*! The articular velocity*/ 117 vpColVector artVel; 118 /*! The velocity in the current frame (articular, camera or reference)*/ 119 vpColVector velocity; 120 121 #if defined(_WIN32) 122 HANDLE hThread; 123 HANDLE mutex_fMi; 124 HANDLE mutex_artVel; 125 HANDLE mutex_artCoord; 126 HANDLE mutex_velocity; 127 HANDLE mutex_display; 128 #elif defined(VISP_HAVE_PTHREAD) 129 pthread_t thread; 130 pthread_attr_t attr; 131 pthread_mutex_t mutex_fMi; 132 pthread_mutex_t mutex_artVel; 133 pthread_mutex_t mutex_artCoord; 134 pthread_mutex_t mutex_velocity; 135 pthread_mutex_t mutex_display; 136 #endif 137 138 bool displayBusy; 139 140 /*! True if the robot has to be stopped*/ 141 bool robotStop; 142 /*! True if one of the joint reach the limit*/ 143 bool jointLimit; 144 /*! Index of the joint which is in limit*/ 145 unsigned int jointLimitArt; 146 /*! True if the singularity are automatically managed */ 147 bool singularityManagement; 148 149 /*! External camera parameters*/ 150 vpCameraParameters cameraParam; 151 152 #if defined VISP_HAVE_X11 153 vpDisplayX display; 154 #elif defined VISP_HAVE_GDI 155 vpDisplayGDI display; 156 #elif defined VISP_HAVE_OPENCV 157 vpDisplayOpenCV display; 158 #elif defined VISP_HAVE_D3D9 159 vpDisplayD3D display; 160 #elif defined VISP_HAVE_GTK 161 vpDisplayGTK display; 162 #endif 163 164 vpDisplayRobotType displayType; 165 166 bool displayAllowed; 167 //! Flag used to force the sampling time in the thread computing the robot's 168 //! displacement to a constant value (\e samplingTime). It may be useful if 169 //! the main thread (computing the features) is very time consumming. False 170 //! by default. 171 bool constantSamplingTimeMode; 172 173 //! Flag used to specify to the thread managing the robot displacements that 174 //! the setVelocity() method has been called. 175 bool setVelocityCalled; 176 177 bool verbose_; 178 179 // private: 180 //#ifndef DOXYGEN_SHOULD_SKIP_THIS 181 // vpRobotWireFrameSimulator(const vpRobotWireFrameSimulator &) 182 // : vpWireFrameSimulator(), vpRobotSimulator(), 183 // I(), tcur(0), tprev(0), robotArms(NULL), size_fMi(8), fMi(NULL), 184 // artCoord(), artVel(), velocity(), 185 // #if defined(_WIN32) 186 // #elif defined(VISP_HAVE_PTHREAD) 187 // thread(), attr(), 188 // #endif 189 // mutex_fMi(), mutex_artVel(), mutex_artCoord(), mutex_velocity(), 190 // mutex_display(), displayBusy(false), robotStop(false), 191 // jointLimit(false), jointLimitArt(false), 192 // singularityManagement(true), cameraParam(), 193 // #if defined(VISP_HAVE_DISPLAY) 194 // display(), 195 // #endif 196 // displayType(MODEL_3D), displayAllowed(true), 197 // constantSamplingTimeMode(false), setVelocityCalled(false), 198 // verbose_(false) 199 // { 200 // throw vpException(vpException::functionNotImplementedError, "Not 201 // implemented!"); 202 // } 203 // vpRobotWireFrameSimulator &operator=(const vpRobotWireFrameSimulator 204 // &){ 205 // throw vpException(vpException::functionNotImplementedError, "Not 206 // implemented!"); return *this; 207 // } 208 //#endif 209 210 public: 211 vpRobotWireFrameSimulator(); 212 explicit vpRobotWireFrameSimulator(bool display); 213 virtual ~vpRobotWireFrameSimulator(); 214 215 /** @name Inherited functionalities from vpRobotWireFrameSimulator */ 216 //@{ 217 /*! 218 Get the parameters of the virtual external camera. 219 220 \return It returns the camera parameters. 221 */ getExternalCameraParameters()222 vpCameraParameters getExternalCameraParameters() const 223 { 224 // if(px_ext != 1 && py_ext != 1) 225 // we assume px_ext and py_ext > 0 226 if ((std::fabs(px_ext - 1.) > vpMath::maximum(px_ext, 1.) * std::numeric_limits<double>::epsilon()) && 227 (std::fabs(py_ext - 1) > vpMath::maximum(py_ext, 1.) * std::numeric_limits<double>::epsilon())) 228 return vpCameraParameters(px_ext, py_ext, I.getWidth() / 2, I.getHeight() / 2); 229 else { 230 unsigned int size = vpMath::minimum(I.getWidth(), I.getHeight()) / 2; 231 return vpCameraParameters(size, size, I.getWidth() / 2, I.getHeight() / 2); 232 } 233 } 234 /*! 235 Get the external camera's position relative to the the world reference 236 frame. 237 238 \return the main external camera position relative to the the world 239 reference frame. 240 */ getExternalCameraPosition()241 vpHomogeneousMatrix getExternalCameraPosition() const 242 { 243 return this->vpWireFrameSimulator::getExternalCameraPosition(); 244 } 245 246 void getInternalView(vpImage<vpRGBa> &I); 247 void getInternalView(vpImage<unsigned char> &I); 248 249 vpHomogeneousMatrix get_cMo(); 250 /*! 251 Get the pose between the object and the fixed world frame. 252 253 \return The pose between the object and the fixed world frame. 254 */ get_fMo()255 vpHomogeneousMatrix get_fMo() const { return fMo; } 256 257 /* Display functions */ 258 void initScene(const vpSceneObject &obj, const vpSceneDesiredObject &desiredObject); 259 void initScene(const char *obj, const char *desiredObject); 260 void initScene(const vpSceneObject &obj); 261 void initScene(const char *obj); 262 263 /*! 264 Set the color used to display the camera in the external view. 265 266 \param col : The desired color. 267 */ setCameraColor(const vpColor & col)268 void setCameraColor(const vpColor &col) { camColor = col; } 269 270 /*! 271 Set the flag used to force the sampling time in the thread computing the 272 robot's displacement to a constant value; see setSamplingTime(). It may be 273 useful if the main thread (computing the features) is very time consuming. 274 False by default. 275 276 \param _constantSamplingTimeMode : The new value of the 277 constantSamplingTimeMode flag. 278 */ setConstantSamplingTimeMode(const bool _constantSamplingTimeMode)279 inline void setConstantSamplingTimeMode(const bool _constantSamplingTimeMode) 280 { 281 constantSamplingTimeMode = _constantSamplingTimeMode; 282 } 283 284 /*! 285 Set the color used to display the object at the current position in the 286 robot's camera view. 287 288 \param col : The desired color. 289 */ setCurrentViewColor(const vpColor & col)290 void setCurrentViewColor(const vpColor &col) { curColor = col; } 291 292 /*! 293 Set the color used to display the object at the desired position in the 294 robot's camera view. 295 296 \param col : The desired color. 297 */ setDesiredViewColor(const vpColor & col)298 void setDesiredViewColor(const vpColor &col) { desColor = col; } 299 300 /*! 301 Set the desired position of the robot's camera relative to the object. 302 303 \param cdMo_ : The desired pose of the camera. 304 */ setDesiredCameraPosition(const vpHomogeneousMatrix & cdMo_)305 void setDesiredCameraPosition(const vpHomogeneousMatrix &cdMo_) 306 { 307 this->vpWireFrameSimulator::setDesiredCameraPosition(cdMo_); 308 } 309 310 /*! 311 Set the way to draw the robot. Depending on what you choose you can 312 display a 3D wireframe model or a set of lines linking the frames used to 313 compute the geometrical model. 314 315 \param dispType : Type of display. Can be MODEL_3D or MODEL_DH. 316 */ setDisplayRobotType(const vpDisplayRobotType dispType)317 inline void setDisplayRobotType(const vpDisplayRobotType dispType) { displayType = dispType; } 318 /*! 319 Set the external camera point of view. 320 321 \param camMf_ : The pose of the external camera relative to the world 322 reference frame. 323 */ setExternalCameraPosition(const vpHomogeneousMatrix & camMf_)324 void setExternalCameraPosition(const vpHomogeneousMatrix &camMf_) 325 { 326 this->vpWireFrameSimulator::setExternalCameraPosition(camMf_); 327 } 328 /*! 329 Specify the thickness of the graphics drawings. 330 */ setGraphicsThickness(unsigned int thickness)331 void setGraphicsThickness(unsigned int thickness) { this->thickness_ = thickness; } 332 333 /*! 334 Set the sampling time. 335 336 \param delta_t : Sampling time in second used to compute the robot 337 displacement from the velocity applied to the robot during this time. 338 339 Since the wireframe simulator is threaded, the sampling time is set to 340 vpTime::getMinTimeForUsleepCall() / 1000 seconds. 341 342 */ setSamplingTime(const double & delta_t)343 inline void setSamplingTime(const double &delta_t) 344 { 345 if (delta_t < static_cast<float>(vpTime::getMinTimeForUsleepCall() * 1e-3)) { 346 this->delta_t_ = static_cast<float>(vpTime::getMinTimeForUsleepCall() * 1e-3); 347 } else { 348 this->delta_t_ = delta_t; 349 } 350 } 351 /*! Set the parameter which enable or disable the singularity mangement */ setSingularityManagement(bool sm)352 void setSingularityManagement(bool sm) { singularityManagement = sm; } 353 354 /*! 355 Activates extra printings when the robot reaches joint limits... 356 */ setVerbose(bool verbose)357 void setVerbose(bool verbose) { this->verbose_ = verbose; } 358 359 /*! 360 Set the pose between the object and the fixed world frame. 361 362 \param fMo_ : The pose between the object and the fixed world frame. 363 */ set_fMo(const vpHomogeneousMatrix & fMo_)364 void set_fMo(const vpHomogeneousMatrix &fMo_) { this->fMo = fMo_; } 365 //@} 366 367 protected: 368 /** @name Protected Member Functions Inherited from vpRobotWireFrameSimulator 369 */ 370 //@{ 371 /*! 372 Function used to launch the thread which moves the robot. 373 */ 374 #if defined(_WIN32) launcher(LPVOID lpParam)375 static DWORD WINAPI launcher(LPVOID lpParam) 376 { 377 (static_cast<vpRobotWireFrameSimulator *>(lpParam))->updateArticularPosition(); 378 return 0; 379 } 380 #elif defined(VISP_HAVE_PTHREAD) 381 static void *launcher(void *arg) 382 { 383 (reinterpret_cast<vpRobotWireFrameSimulator *>(arg))->updateArticularPosition(); 384 // pthread_exit((void*) 0); 385 return NULL; 386 } 387 #endif 388 389 /* Robot functions */ init()390 void init() { ; } 391 /*! Method lauched by the thread to compute the position of the robot in the 392 * articular frame. */ 393 virtual void updateArticularPosition() = 0; 394 /*! Method used to check if the robot reached a joint limit. */ 395 virtual int isInJointLimit() = 0; 396 /*! Compute the articular velocity relative to the velocity in another 397 * frame. */ 398 virtual void computeArticularVelocity() = 0; 399 400 /* Display functions */ initDisplay()401 void initDisplay() { ; } 402 virtual void initArms() = 0; 403 404 #if defined(_WIN32) get_artCoord()405 vpColVector get_artCoord() const 406 { 407 #if defined(WINRT_8_1) 408 WaitForSingleObjectEx(mutex_artCoord, INFINITE, FALSE); 409 #else // pure win32 410 WaitForSingleObject(mutex_artCoord, INFINITE); 411 #endif 412 vpColVector artCoordTmp(6); 413 artCoordTmp = artCoord; 414 ReleaseMutex(mutex_artCoord); 415 return artCoordTmp; 416 } set_artCoord(const vpColVector & coord)417 void set_artCoord(const vpColVector &coord) 418 { 419 #if defined(WINRT_8_1) 420 WaitForSingleObjectEx(mutex_artCoord, INFINITE, FALSE); 421 #else // pure win32 422 WaitForSingleObject(mutex_artCoord, INFINITE); 423 #endif 424 artCoord = coord; 425 ReleaseMutex(mutex_artCoord); 426 } 427 get_artVel()428 vpColVector get_artVel() const 429 { 430 #if defined(WINRT_8_1) 431 WaitForSingleObjectEx(mutex_artVel, INFINITE, FALSE); 432 #else // pure win32 433 WaitForSingleObject(mutex_artVel, INFINITE); 434 #endif 435 vpColVector artVelTmp(artVel); 436 ReleaseMutex(mutex_artVel); 437 return artVelTmp; 438 } set_artVel(const vpColVector & vel)439 void set_artVel(const vpColVector &vel) 440 { 441 #if defined(WINRT_8_1) 442 WaitForSingleObjectEx(mutex_artVel, INFINITE, FALSE); 443 #else // pure win32 444 WaitForSingleObject(mutex_artVel, INFINITE); 445 #endif 446 artVel = vel; 447 ReleaseMutex(mutex_artVel); 448 } 449 get_velocity()450 vpColVector get_velocity() 451 { 452 #if defined(WINRT_8_1) 453 WaitForSingleObjectEx(mutex_velocity, INFINITE, FALSE); 454 #else // pure win32 455 WaitForSingleObject(mutex_velocity, INFINITE); 456 #endif 457 vpColVector velocityTmp = velocity; 458 ReleaseMutex(mutex_velocity); 459 return velocityTmp; 460 } set_velocity(const vpColVector & vel)461 void set_velocity(const vpColVector &vel) 462 { 463 #if defined(WINRT_8_1) 464 WaitForSingleObjectEx(mutex_velocity, INFINITE, FALSE); 465 #else // pure win32 466 WaitForSingleObject(mutex_velocity, INFINITE); 467 #endif 468 velocity = vel; 469 ReleaseMutex(mutex_velocity); 470 } 471 set_displayBusy(const bool & status)472 void set_displayBusy(const bool &status) 473 { 474 #if defined(WINRT_8_1) 475 WaitForSingleObjectEx(mutex_display, INFINITE, FALSE); 476 #else // pure win32 477 WaitForSingleObject(mutex_display, INFINITE); 478 #endif 479 displayBusy = status; 480 ReleaseMutex(mutex_display); 481 } get_displayBusy()482 bool get_displayBusy() 483 { 484 #if defined(WINRT_8_1) 485 WaitForSingleObjectEx(mutex_display, INFINITE, FALSE); 486 #else // pure win32 487 WaitForSingleObject(mutex_display, INFINITE); 488 #endif 489 bool status = displayBusy; 490 if (!displayBusy) 491 displayBusy = true; 492 ReleaseMutex(mutex_display); 493 return status; 494 } 495 496 #elif defined(VISP_HAVE_PTHREAD) get_artCoord()497 vpColVector get_artCoord() 498 { 499 pthread_mutex_lock(&mutex_artCoord); 500 vpColVector artCoordTmp(6); 501 artCoordTmp = artCoord; 502 pthread_mutex_unlock(&mutex_artCoord); 503 return artCoordTmp; 504 } set_artCoord(const vpColVector & coord)505 void set_artCoord(const vpColVector &coord) 506 { 507 pthread_mutex_lock(&mutex_artCoord); 508 artCoord = coord; 509 pthread_mutex_unlock(&mutex_artCoord); 510 } 511 get_artVel()512 vpColVector get_artVel() 513 { 514 pthread_mutex_lock(&mutex_artVel); 515 vpColVector artVelTmp(artVel); 516 pthread_mutex_unlock(&mutex_artVel); 517 return artVelTmp; 518 } set_artVel(const vpColVector & vel)519 void set_artVel(const vpColVector &vel) 520 { 521 pthread_mutex_lock(&mutex_artVel); 522 artVel = vel; 523 pthread_mutex_unlock(&mutex_artVel); 524 } 525 get_velocity()526 vpColVector get_velocity() 527 { 528 pthread_mutex_lock(&mutex_velocity); 529 vpColVector velocityTmp = velocity; 530 pthread_mutex_unlock(&mutex_velocity); 531 return velocityTmp; 532 } set_velocity(const vpColVector & vel)533 void set_velocity(const vpColVector &vel) 534 { 535 pthread_mutex_lock(&mutex_velocity); 536 velocity = vel; 537 pthread_mutex_unlock(&mutex_velocity); 538 } 539 set_displayBusy(const bool & status)540 void set_displayBusy(const bool &status) 541 { 542 pthread_mutex_lock(&mutex_display); 543 displayBusy = status; 544 pthread_mutex_unlock(&mutex_display); 545 } get_displayBusy()546 bool get_displayBusy() 547 { 548 pthread_mutex_lock(&mutex_display); 549 bool status = displayBusy; 550 if (!displayBusy) 551 displayBusy = true; 552 pthread_mutex_unlock(&mutex_display); 553 return status; 554 } 555 #endif 556 557 /*! Get a table of poses between the reference frame and the frames you used 558 * to compute the Denavit-Hartenberg representation */ 559 virtual void get_fMi(vpHomogeneousMatrix *fMit) = 0; 560 //@} 561 }; 562 563 #endif 564 #endif 565