Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
vpForceTorqueAtiNetFTSensor.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  * ATI Force torque interface.
33  *
34 *****************************************************************************/
35 
36 #include <stdint.h>
37 
38 #include <visp3/core/vpConfig.h>
39 #include <visp3/core/vpException.h>
40 #include <visp3/core/vpTime.h>
41 #include <visp3/sensor/vpForceTorqueAtiNetFTSensor.h>
42 
43 // Make vpForceTorqueAtiNetFTSensor available only if inet_ntop() used to
44 // communicate by UDP with the sensor through vpUDPClient is available; inet_ntop()
45 // is not supported on win XP
46 #ifdef VISP_HAVE_FUNC_INET_NTOP
47 
48 #ifndef DOXYGEN_SHOULD_SKIP_THIS
49 typedef struct response_struct
50 {
51  uint32_t rdt_sequence;
52  uint32_t ft_sequence;
53  uint32_t status;
54  int32_t FTData[6];
55 } RESPONSE;
56 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
57 
58 BEGIN_VISP_NAMESPACE
66  : vpUDPClient(), m_counts_per_force(1000000), m_counts_per_torque(1000000000), m_scaling_factor(1), m_ft_bias(6, 0),
67  m_data_count(0), m_data_count_prev(0), m_ft(6, 0), m_is_streaming_started(false)
68 { }
69 
75 vpForceTorqueAtiNetFTSensor::vpForceTorqueAtiNetFTSensor(const std::string &hostname, int port)
76  : vpUDPClient(hostname, port), m_counts_per_force(1000000), m_counts_per_torque(1000000000), m_scaling_factor(1),
77  m_ft_bias(6, 0), m_data_count(0), m_data_count_prev(0), m_ft(6, 0), m_is_streaming_started(false)
78 { }
79 
85 {
86  if (!m_is_init) {
87  throw(vpException(vpException::notInitialized, "Cannot start streaming: UDP client is not initialized"));
88  }
89 
91  throw(vpException(vpException::notInitialized, "Streaming is already started"));
92  }
93 
94  // Since UDP packet could be lost, retry startup 10 times before giving up
95  for (unsigned int i = 0; i < 10; ++i) {
96  int len = 8;
97  unsigned char request[8]; // The request data sent to the Net F/T
98  uint16_t val1 = htons(0x1234); // Standard header
99  uint16_t val2 = htons(0x0002); // Start high-speed streaming (see table 10.1 in Net F/T user manual)
100  uint32_t val3 = htons(0); // Infinite sample (see section 10.1 in Net F/T user manual
101  memcpy(&request[0], &val1, sizeof(val1));
102  memcpy(&request[2], &val2, sizeof(val2));
103  memcpy(&request[4], &val3, sizeof(val3));
104 
105  // Send start stream
106  if (send(request, len) != len) {
107  throw(vpException(vpException::notInitialized, "UDP client is not initialized"));
108  }
109  std::cout << "wait: " << i << std::endl;
110 
111  m_is_streaming_started = true;
112  if (waitForNewData()) {
113  return true;
114  }
115  }
116  m_is_streaming_started = false;
117  return false;
118 }
119 
124 {
125  if (!m_is_init) {
126  throw(vpException(vpException::notInitialized, "Cannot stop streaming: UDP client is not initialized"));
127  }
128 
129  if (!m_is_streaming_started) {
130  throw(vpException(vpException::notInitialized, "Cannot stop streaming: streaming was not started"));
131  }
132 
133  int len = 8;
134  unsigned char request[8]; // The request data sent to the Net F/T
135  uint16_t val1 = htons(0x1234); // Standard header
136  uint16_t val2 = htons(0x0002); // Start high-speed streaming (see table 10.1 in Net F/T user manual)
137  uint32_t val3 = htons(0); // Infinite sample (see section 10.1 in Net F/T user manual
138  memcpy(&request[0], &val1, sizeof(val1));
139  memcpy(&request[2], &val2, sizeof(val2));
140  memcpy(&request[4], &val3, sizeof(val3));
141 
142  // Send start stream
143  if (send(request, len) != len) {
144  throw(vpException(vpException::notInitialized, "Cannot stop streaming"));
145  }
146 
147  m_is_streaming_started = false;
148 }
149 
156 {
158  stopStreaming();
159  }
160 }
161 
169 void vpForceTorqueAtiNetFTSensor::bias(unsigned int n_counts)
170 {
171  if (!m_is_init) {
172  throw(vpException(vpException::notInitialized, "Cannot bias: UDP client is not initialized"));
173  }
174 
175  if (!m_is_streaming_started) {
176  throw(vpException(vpException::notInitialized, "Cannot bias: streaming was not started"));
177  }
178 
179  vpColVector ft_bias_tmp(6, 0);
180  m_ft_bias = 0;
181 
182  if (n_counts == 0) {
184  }
185  else {
186  for (unsigned int i = 0; i < n_counts; i++) {
187  ft_bias_tmp += getForceTorque();
188  waitForNewData();
189  }
190  m_ft_bias = ft_bias_tmp / n_counts;
191  }
192 }
193 
200 
212 {
213  if (!m_is_init) {
214  throw(vpException(vpException::notInitialized, "Cannot get F/T: UDP client is not initialized"));
215  }
216 
217  if (!m_is_streaming_started) {
218  throw(vpException(vpException::notInitialized, "Cannot get F/T: streaming was not started"));
219  }
220 
222  throw(vpException(vpException::notInitialized, "Cannot get F/T: no new data available"));
223  }
224 
225  return m_ft;
226 }
227 
234 {
235  if (!m_is_init) {
236  throw(vpException(vpException::notInitialized, "Cannot wait for new data: UDP client is not initialized"));
237  }
238 
239  if (!m_is_streaming_started) {
240  throw(vpException(vpException::notInitialized, "Cannot wait for new data: streaming was not started"));
241  }
242 
243  double t = vpTime::measureTimeMs();
245  while (vpTime::measureTimeMs() - t < static_cast<double>(timeout)) {
246  unsigned char response[36];
247  RESPONSE resp;
248  if (receive((void *)response, 36)) {
249  uint32_t resp1, resp2, resp3;
250  memcpy(&resp1, &response[0], sizeof(uint32_t));
251  memcpy(&resp2, &response[4], sizeof(uint32_t));
252  memcpy(&resp3, &response[8], sizeof(uint32_t));
253  resp.rdt_sequence = ntohl(resp1);
254  resp.ft_sequence = ntohl(resp2);
255  resp.status = ntohl(resp3);
256 
257  for (int i = 0; i < 6; i++) {
258  int32_t resp4;
259  memcpy(&resp4, &response[12 + i * 4], sizeof(int32_t));
260  resp.FTData[i] = ntohl(resp4);
261  }
262  // Output the response data.
263  if (resp.status) {
264  throw(vpException(vpException::notInitialized, "Cannot wait for new data: status 0x%08x is not 0x00000000",
265  resp.status));
266  }
267  double force_factor = static_cast<double>(m_scaling_factor) / static_cast<double>(m_counts_per_force);
268  double torque_factor = static_cast<double>(m_scaling_factor) / static_cast<double>(m_counts_per_torque);
269  for (int i = 0; i < 3; i++) {
270  m_ft[i] = resp.FTData[i] * force_factor;
271  }
272  for (int i = 3; i < 6; i++) {
273  m_ft[i] = resp.FTData[i] * torque_factor;
274  }
275  // Consider bias
276  m_ft -= m_ft_bias;
277 
278  m_data_count++;
279  }
280 
282  return true;
283  }
284  vpTime::sleepMs(1);
285  }
286 
287  return false;
288 }
289 END_VISP_NAMESPACE
290 #endif
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition: vpException.h:74
void bias(unsigned int n_counts=50)
virtual ~vpForceTorqueAtiNetFTSensor() VP_OVERRIDE
bool waitForNewData(unsigned int timeout=50)
This class implements a basic (IPv4) User Datagram Protocol (UDP) client.
Definition: vpUDPClient.h:174
int receive(std::string &msg, int timeoutMs=0)
bool m_is_init
Definition: vpUDPClient.h:191
int send(const std::string &msg)
VISP_EXPORT void sleepMs(double t)
VISP_EXPORT double measureTimeMs()