Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpMocapQualisys.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  * Motion capture using Qualisys device.
33  *
34 *****************************************************************************/
35 
36 #include <visp3/core/vpConfig.h>
37 
38 #ifdef VISP_HAVE_QUALISYS
39 
40 #include <cmath>
41 #include <iostream>
42 
43 #include <visp3/core/vpTime.h>
44 #include <visp3/sensor/vpMocapQualisys.h>
45 
46 #include <qualisys_cpp_sdk/RTPacket.h>
47 #include <qualisys_cpp_sdk/RTProtocol.h>
48 
50 #ifndef DOXYGEN_SHOULD_SKIP_THIS
51 class vpMocapQualisys::vpMocapQualisysImpl
52 {
53 public:
54  vpMocapQualisysImpl()
55  : m_rtProtocol(), m_basePort(22222), m_udpPort(6734), m_majorVersion(1), m_minorVersion(19), m_bigEndian(false),
56  m_dataAvailable(false), m_streamFrames(false), m_verbose(false), m_serverAddr()
57  { }
58 
59  virtual ~vpMocapQualisysImpl() { close(); }
60 
61  void close()
62  {
63  m_rtProtocol.StopCapture();
64  m_rtProtocol.Disconnect();
65  }
66 
67  bool connect()
68  {
69  int n_attempt = 2;
70  for (auto i = 0; i < n_attempt; i++) {
71  if (!m_rtProtocol.Connected()) {
72  if (!m_rtProtocol.Connect(m_serverAddr.c_str(), m_basePort, &m_udpPort, m_majorVersion, m_minorVersion,
73  m_bigEndian)) {
74  std::cout << "Qualisys connection error: " << m_rtProtocol.GetErrorString() << std::endl;
75 
76  vpTime::sleepMs(1000);
77  }
78  }
79  else {
80  if (m_verbose) {
81  std::cout << "Qualisys connected" << std::endl;
82  }
83  return verifyDataStreamed();
84  }
85  }
86 
87  std::cout << "Qualisys connection timeout" << std::endl;
88 
89  return false;
90  }
91 
92  bool verifyDataStreamed()
93  {
94  bool readSettingsOK = false;
95 
96  for (auto i = 0; i < 6; i++) {
97  if (!m_dataAvailable) {
98  if (!m_rtProtocol.Read6DOFSettings(m_dataAvailable)) {
99  if (m_verbose) {
100  std::cout << "Reading 6DOF settings error: " << m_rtProtocol.GetErrorString() << std::endl;
101  }
102 
103  vpTime::sleepMs(1000);
104  }
105  }
106  else {
107  if (m_verbose && !readSettingsOK) {
108  std::cout << "Reading 6DOF settings succeded." << std::endl;
109  }
110  readSettingsOK = true;
111  }
112  }
113 
114  if (!readSettingsOK) {
115  if (m_verbose) {
116  std::cout << "Reading 6DOF settings timeout: " << std::endl;
117  }
118  return false;
119  }
120  else {
121  for (auto i = 0; i < 6; i++) {
122  if (!m_streamFrames) {
123  if (!m_rtProtocol.StreamFrames(CRTProtocol::RateAllFrames, 0, m_udpPort, nullptr, CRTProtocol::cComponent6d)) {
124  if (m_verbose) {
125  std::cout << "Streaming frames error: " << m_rtProtocol.GetErrorString() << std::endl;
126  }
127 
128  vpTime::sleepMs(1000);
129  }
130  m_streamFrames = true;
131  }
132  else {
133  if (m_verbose) {
134  std::cout << "Starting to stream 6DOF data" << std::endl;
135  }
136  return true;
137  }
138  }
139 
140  std::cout << "Streaming frames timeout: " << std::endl;
141 
142  return false;
143  }
144  }
145 
146  bool getBodyPose(int iBody, std::string &name, vpHomogeneousMatrix &M, CRTPacket *rtPacket)
147  {
148  float fX, fY, fZ;
149  float rotationMatrix[9];
150 
151  if (rtPacket->Get6DOFBody(iBody, fX, fY, fZ, rotationMatrix)) {
152  const char *pTmpStr = m_rtProtocol.Get6DOFBodyName(iBody);
153  if (pTmpStr) {
154  name = std::string(pTmpStr);
155  }
156  else {
157  if (m_verbose) {
158  std::cout << "Unknown body" << std::endl;
159  }
160  return false;
161  }
162 
163  M[0][3] = fX / 1000.;
164  M[1][3] = fY / 1000.;
165  M[2][3] = fZ / 1000.;
166  M[3][3] = 1.;
167  unsigned int k = 0;
168  for (unsigned int j = 0; j < 3; j++) {
169  for (unsigned int i = 0; i < 3; i++) {
170  M[i][j] = rotationMatrix[k++];
171  }
172  }
173 
174  return true;
175  }
176  else {
177  return false;
178  }
179  }
180 
181  bool getBodiesPose(std::map<std::string, vpHomogeneousMatrix> &bodies_pose, bool all_bodies)
182  {
183  CRTPacket::EPacketType packetType;
184 
185  if (m_rtProtocol.Receive(packetType, true) == CNetwork::ResponseType::success) {
186  if (packetType == CRTPacket::PacketData) {
187  CRTPacket *rtPacket = m_rtProtocol.GetRTPacket();
188  for (unsigned int iBody = 0; iBody < rtPacket->Get6DOFBodyCount(); iBody++) {
189  std::string bodyName;
190 
191  vpHomogeneousMatrix bodyPose;
192  if (!getBodyPose(iBody, bodyName, bodyPose, rtPacket)) {
193  std::cout << "Error : Could not get pose from body n°" << iBody << std::endl;
194 
195  return false;
196  }
197  if (all_bodies) {
198  bodies_pose[bodyName] = bodyPose;
199  }
200  else if (bodyPose.isValid()) {
201  bodies_pose[bodyName] = bodyPose;
202  }
203  }
204  return true;
205  }
206  }
207  return false;
208  }
209 
210  bool getSpecificBodyPose(const std::string &body_name, vpHomogeneousMatrix &body_pose)
211  {
212  std::map<std::string, vpHomogeneousMatrix> bodies_pose;
213  if (getBodiesPose(bodies_pose, true)) {
214  if (bodies_pose.find(body_name) != bodies_pose.end()) {
215  body_pose = bodies_pose[body_name];
216  if (m_verbose) {
217  std::cout << "I found bodyName" << body_name << std::endl;
218  }
219  return true;
220  }
221  else {
222  std::cout << "The body " << body_name << " was not found in Qualisys. Please check the name you typed."
223  << std::endl;
224 
225  return false;
226  }
227  }
228  else {
229  std::cout << "Error : could not process data from Qualisys" << std::endl;
230 
231  return false;
232  }
233  }
234 
235  void setServerAddress(const std::string &serverAddr) { m_serverAddr = serverAddr; }
236 
237  void setVerbose(bool verbose) { m_verbose = verbose; }
238 
239 private:
240  CRTProtocol m_rtProtocol;
241  unsigned short m_basePort;
242  unsigned short m_udpPort;
243  int m_majorVersion;
244  int m_minorVersion;
245  bool m_bigEndian;
246  bool m_dataAvailable;
247  bool m_streamFrames;
248  bool m_verbose;
249  std::string m_serverAddr;
250 };
251 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
252 
253 /*
254  **********************************************************************************************
255  */
256 
260 vpMocapQualisys::vpMocapQualisys() : m_impl(new vpMocapQualisysImpl()) { }
261 
266 
270 void vpMocapQualisys::close() { m_impl->close(); }
271 
277 bool vpMocapQualisys::connect() { return m_impl->connect(); }
278 
286 bool vpMocapQualisys::getBodiesPose(std::map<std::string, vpHomogeneousMatrix> &bodies_pose, bool all_bodies)
287 {
288  return m_impl->getBodiesPose(bodies_pose, all_bodies);
289 }
290 
297 bool vpMocapQualisys::getSpecificBodyPose(const std::string &body_name, vpHomogeneousMatrix &body_pose)
298 {
299  return m_impl->getSpecificBodyPose(body_name, body_pose);
300 }
307 void vpMocapQualisys::setServerAddress(const std::string &serverAddr) { m_impl->setServerAddress(serverAddr); }
308 
313 void vpMocapQualisys::setVerbose(bool verbose) { m_impl->setVerbose(verbose); }
314 END_VISP_NAMESPACE
315 #else
316 // Work around to avoid warning:
317 // libvisp_sensor.a(vpMocapQualisys.cpp.o) has no symbols
318 void dummy_vpMocapQualisys() { };
319 #endif
Implementation of an homogeneous matrix and operations on such kind of matrices.
void setServerAddress(const std::string &serverAddr)
bool getSpecificBodyPose(const std::string &body_name, vpHomogeneousMatrix &body_pose)
void setVerbose(bool verbose)
virtual ~vpMocapQualisys()
bool getBodiesPose(std::map< std::string, vpHomogeneousMatrix > &bodies_pose, bool all_bodies=false)
bool m_verbose
Definition: vpMocap.h:105
std::string m_serverAddr
Definition: vpMocap.h:106
VISP_EXPORT void sleepMs(double t)