DTrackSDK  v2.9.0
example_flystick_feedback.cpp
1 /* DTrackSDK in C++: example_flystick_feedback.cpp
2  *
3  * C++ example to control a Flystick with feedback.
4  *
5  * Copyright (c) 2021-2022 Advanced Realtime Tracking GmbH & Co. KG
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * Purpose:
31  * - example with or without DTrack2/DTRACK3 remote commands
32  * - in communicating mode: starts measurement, collects some frames and stops measurement again
33  * - in listening mode: please start measurement manually e.g. in DTrack frontend application
34  * - for DTrackSDK v2.8.0 (or newer)
35  */
36 
37 #include "DTrackSDK.hpp"
38 
39 #include <iostream>
40 #include <sstream>
41 
42 // global DTrackSDK
43 static DTrackSDK* dt = NULL;
44 
45 static bool sentFeedback = false;
46 
47 // prototypes
48 static bool doFeedback( int flystickId );
49 static bool data_error_to_console();
50 static void messages_to_console();
51 
52 
61 int main( int argc, char** argv )
62 {
63  if ( argc != 2 )
64  {
65  std::cout << "Usage: example_flystick_feedback [<server host/ip>:]<data port>" << std::endl;
66  return -1;
67  }
68 
69  // initialization:
70 
71  dt = new DTrackSDK( (const char *)argv[ 1 ] );
72 
73  if ( ! dt->isDataInterfaceValid() )
74  {
75  std::cout << "DTrackSDK init error" << std::endl;
76  delete dt;
77  return -3;
78  }
79  std::cout << "connected to ATC '" << argv[ 1 ] << "', listening at local data port " << dt->getDataPort() << std::endl;
80 
81 // dt->setCommandTimeoutUS( 30000000 ); // NOTE: change here timeout for exchanging commands, if necessary
82 // dt->setDataTimeoutUS( 3000000 ); // NOTE: change here timeout for receiving tracking data, if necessary
83 // dt->setDataBufferSize( 100000 ); // NOTE: change here buffer size for receiving tracking data, if necessary
84 
85  if ( dt->isCommandInterfaceValid() ) // ensure full access for DTrack2/DTRACK3 commands, if in communicating mode
86  {
87  if ( ! dt->isCommandInterfaceFullAccess() )
88  {
89  std::cout << "Full access to ATC required!" << std::endl; // maybe DTrack2/3 frontend is still connected to ATC
90  data_error_to_console();
91  messages_to_console();
92  delete dt;
93  return -10;
94  }
95  }
96 
97  // measurement:
98 
99  if ( dt->isCommandInterfaceValid() )
100  {
101  if ( ! dt->startMeasurement() ) // start measurement
102  {
103  std::cout << "Measurement start failed!" << std::endl;
104  data_error_to_console();
105  messages_to_console();
106  delete dt;
107  return -4;
108  }
109  }
110 
111  int count = 0;
112  bool isRunning = true;
113  while ( isRunning ) // collect frames
114  {
115  count++;
116 
117  if ( dt->receive() )
118  {
119  int nfly = 0;
120  for ( int id = 0; id < dt->getNumFlyStick(); id++ )
121  {
122  if ( ( dt->getFlyStick( id )->num_button >= 8 ) && ( dt->getFlyStick( id )->num_joystick >= 2 ) )
123  { // demo routine needs at least 8 buttons and 2 joystick values (e.g. Flystick2+)
124  nfly++;
125 
126  if ( ! doFeedback( id ) )
127  isRunning = false;
128  }
129  }
130 
131  if ( nfly == 0 )
132  {
133  std::cout << "No suitable Flystick identified!" << std::endl;
134  isRunning = false;
135  }
136  }
137  else
138  {
139  data_error_to_console();
140  if ( dt->isCommandInterfaceValid() ) messages_to_console();
141  }
142 
143  if ( ( count % 100 == 1 ) && dt->isCommandInterfaceValid() )
144  messages_to_console();
145  }
146 
147  if ( dt->isCommandInterfaceValid() )
148  {
149  dt->stopMeasurement(); // stop measurement
150  messages_to_console();
151  }
152 
153  delete dt; // clean up
154  return 0;
155 }
156 
157 
164 static bool doFeedback( int flystickId )
165 {
166  const DTrackFlyStick* fly = dt->getFlyStick( flystickId );
167  if ( fly == NULL )
168  {
169  std::cout << "DTrackSDK fatal error: invalid Flystick id " << flystickId << std::endl;
170  return false;
171  }
172 
173  if ( fly->button[ 0 ] != 0 ) // stop program if trigger button is pressed
174  return false;
175 
176  // get beep feedback:
177 
178  if ( fly->button[ 5 ] != 0 ) // joystick button of Flystick2+
179  {
180  double beepDuration = 500.0 + fly->joystick[ 0 ] * 450.0; // range 50 .. 950 ms
181  double beepFrequency = 5000.0 + fly->joystick[ 1 ] * 3000.0; // range 2000 .. 8000 Hz
182 
183  if ( ! sentFeedback ) // prevents permanent sending of feedback commands as long as button is pressed
184  dt->flystickBeep( flystickId, beepDuration, beepFrequency );
185 
186  sentFeedback = true;
187  return true;
188  }
189 
190  // get vibration feedback:
191 
192  int vibrationPattern = 0; // Flystick2+ supports up to 6 vibration pattern
193  if ( fly->button[ 1 ] != 0 ) vibrationPattern = 1;
194  if ( fly->button[ 2 ] != 0 ) vibrationPattern = 2;
195  if ( fly->button[ 3 ] != 0 ) vibrationPattern = 3;
196  if ( fly->button[ 4 ] != 0 ) vibrationPattern = 4;
197  if ( fly->button[ 6 ] != 0 ) vibrationPattern = 5; // button '5' (joystick button) is already used
198  if ( fly->button[ 7 ] != 0 ) vibrationPattern = 6;
199 
200  if ( vibrationPattern > 0 )
201  {
202  if ( ! sentFeedback ) // prevents permanent sending of feedback commands as long as button is pressed
203  dt->flystickVibration( flystickId, vibrationPattern );
204 
205  sentFeedback = true;
206  return true;
207  }
208 
209  sentFeedback = false;
210  return true;
211 }
212 
213 
219 static bool data_error_to_console()
220 {
221  bool ret = true;
222 
223  if ( dt->getLastDataError() != DTrackSDK::ERR_NONE )
224  {
226  {
227  std::cout << "--- timeout while waiting for tracking data" << std::endl;
228  }
229  else if ( dt->getLastDataError() == DTrackSDK::ERR_NET )
230  {
231  std::cout << "--- error while receiving tracking data" << std::endl;
232  }
233  else if ( dt->getLastDataError() == DTrackSDK::ERR_PARSE )
234  {
235  std::cout << "--- error while parsing tracking data" << std::endl;
236  }
237 
238  ret = false;
239  }
240 
242  {
244  {
245  std::cout << "--- timeout while waiting for Controller command" << std::endl;
246  }
247  else if ( dt->getLastServerError() == DTrackSDK::ERR_NET )
248  {
249  std::cout << "--- error while receiving Controller command" << std::endl;
250  }
251  else if ( dt->getLastServerError() == DTrackSDK::ERR_PARSE )
252  {
253  std::cout << "--- error while parsing Controller command" << std::endl;
254  }
255 
256  ret = false;
257  }
258 
259  return ret;
260 }
261 
262 
266 static void messages_to_console()
267 {
268  while ( dt->getMessage() )
269  {
270  std::cout << "ATC message: \"" << dt->getMessageStatus() << "\" \"" << dt->getMessageMsg() << "\"" << std::endl;
271  }
272 }
273 
int getNumFlyStick() const
Get number of calibrated Flysticks.
const DTrackFlyStick * getFlyStick(int id) const
Get Flystick data.
bool receive()
Receive and process one tracking data packet.
Definition: DTrackSDK.cpp:441
unsigned short getDataPort() const
Get UDP data port where tracking data is received.
Definition: DTrackSDK.cpp:321
bool isCommandInterfaceFullAccess()
Returns if TCP connection has full access for DTrack2/DTRACK3 commands.
Definition: DTrackSDK.cpp:341
A.R.T. Flystick data (6DOF + buttons).
DTrack SDK main class derived from DTrackParser.
Definition: DTrackSDK.hpp:77
std::string getMessageStatus() const
Get status of last DTrack2/DTRACK3 event message.
Definition: DTrackSDK.cpp:949
Errors getLastServerError() const
Get last error at exchanging commands with Controller (command transmission).
Definition: DTrackSDK.cpp:558
bool isCommandInterfaceValid() const
Returns if TCP connection for DTrack2/DTRACK3 commands is active.
Definition: DTrackSDK.cpp:330
bool flystickVibration(int flystickId, int vibrationPattern)
Send Flystick feedback command to start a vibration pattern on a specific Flystick.
Definition: DTrackSDK.cpp:1040
std::string getMessageMsg() const
Get message text of last DTrack2/DTRACK3 event message.
Definition: DTrackSDK.cpp:958
int num_joystick
Number of joystick values.
bool flystickBeep(int flystickId, double durationMs, double frequencyHz)
Send Flystick feedback command to start a beep on a specific Flystick.
Definition: DTrackSDK.cpp:1025
Timeout occured.
Definition: DTrackSDK.hpp:93
Error while parsing command.
Definition: DTrackSDK.hpp:95
bool isDataInterfaceValid() const
Returns if UDP socket is open to receive tracking data on local machine.
Definition: DTrackSDK.cpp:310
bool getMessage()
Get DTrack2/DTRACK3 event message from the Controller.
Definition: DTrackSDK.cpp:864
Errors getLastDataError() const
Get last error at receiving tracking data (data transmission).
Definition: DTrackSDK.cpp:549
int button[DTRACKSDK_FLYSTICK_MAX_BUTTON]
Button state (1 pressed, 0 not pressed): 0 front, 1..n-1 right to left.
bool stopMeasurement()
Stop measurement.
Definition: DTrackSDK.cpp:615
bool startMeasurement()
Start measurement.
Definition: DTrackSDK.cpp:595
Network error.
Definition: DTrackSDK.hpp:94
double joystick[DTRACKSDK_FLYSTICK_MAX_JOYSTICK]
Joystick value (-1.0 <= joystick <= 1.0); 0 horizontal, 1 vertical.