YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
YarpViconBridge.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 iCub Facility
3 * Authors: Nicolo' Genesio
4 * CopyPolicy: Released under the terms of the LGPLv2.1 or later, see LGPL.TXT
5 */
6
7#include<YarpViconBridge.h>
8#include<yarp/os/Time.h>
9#include<cmath>
10
11using namespace ViconDataStreamSDK::CPP;
12using namespace yarp::os;
13using namespace yarp::sig;
14using namespace yarp::dev;
15
16#define output_stream if(!logFile.empty()) ; else yInfo()
17
18constexpr uint32_t default_rate = 120;
19
20YarpViconBridge::YarpViconBridge(std::string _hostname) : PeriodicThread(1.0/default_rate),
21 hostname(_hostname),
22 logFile(""),
23 multicastAddress("244.0.0.0:44801"),
29 interrupted(false),
33 silent(false),
35 axisMapping("ZUp"),
36 subject_string("Subj_"),
37 segment_string("::Seg_"),
38 viconroot_string("Vicon_ROOT"),
39 labeled_marker_string("::Marker_"),
40 unlabeled_marker_string("UnlMarker#"),
41 poly(nullptr),
42 itf(nullptr)
43{
44}
45
46bool YarpViconBridge::open(Searchable &config) {
47
48 if (config.check("log_file"))
49 {
50 logFile = config.find("log_file").asString();
51 yInfo()<< "Using log file <"<< logFile << "> ...";
52 }
53
54 if(config.check("hostname"))
55 {
56 hostname = config.find("hostname").asString();
57 hostname = hostname + ":801";
58 }
59
60 if(config.check("silent"))
61 {
62 silent = true;
63 }
64
65 if(config.check("inversion"))
66 {
67 inversion = true;
68 }
69
70 if (config.check("enable_multicast"))
71 {
72 enableMultiCast = true;
73 multicastAddress = config.find("multicastAddress").asString();
74 yInfo() << "Enabling multicast address <"<< multicastAddress << "> ...";
75 }
76
77 if (config.check("connect_to_multicast"))
78 {
79 connectToMultiCast = true;
80 multicastAddress = config.find("connect_to_multicast").asString();
81 yInfo() << "connecting to multicast address <"<< multicastAddress << "> ...";
82 }
83
84 if(config.check("publish_segments"))
85 {
86 publish_segments = config.find("publish_segments").asBool();
87 }
88
89 if(config.check("publish_labeled_markers"))
90 {
91 publish_labeled_markers = config.find("publish_labeled_markers").asBool();
92 }
93
94 if(config.check("publish_unlabeled_markers"))
95 {
96 publish_unlabeled_markers = config.find("publish_unlabeled_markers").asBool();
97 }
98
99 if(config.check("subject_string"))
100 {
101 subject_string=config.find("subject_string").asString();
102 }
103
104 if(config.check("segment_string"))
105 {
106 segment_string=config.find("segment_string").asString();
107 }
108
109 if(config.check("test_frame"))
110 {
111 test_frame = config.find("test_frame").asString();
112 }
113
114 if(config.check("viconroot_string"))
115 {
116 viconroot_string = config.find("viconroot_string").asString();
117 }
118
119 if(config.check("labeled_marker_string"))
120 {
121 labeled_marker_string = config.find("labeled_marker_string").asString();
122 }
123
124 if(config.check("unlabeled_marker_string"))
125 {
126 unlabeled_marker_string = config.find("unlabeled_marker_string").asString();
127 }
128
129 if(config.check("centroids"))
130 {
131 bReadCentroids = true;
132 }
133
134 if(config.check("rays"))
135 {
136 bReadRayData = true;
137 }
138
139 if(config.check("client-buffer-size"))
140 {
141 clientBufferSize = static_cast<unsigned int>(config.find("client-buffer-size").asInt32());
142 }
143
144 if(config.check("set-axis-mapping"))
145 {
146 axisMapping = config.find("set-axis-mapping").asString();
147 if( axisMapping == "XUp" || axisMapping == "YUp" || axisMapping == "ZUp" )
148 {
149 yInfo() << "Setting Axis to "<< axisMapping;
150 }
151 else
152 {
153 yInfo() << "Unknown axis setting: "<< axisMapping <<" . Should be XUp, YUp, or ZUp";
154 return false;
155 }
156 }
157
158 if(!logFile.empty())
159 {
160 ofs.open(logFile.c_str());
161 if(!ofs.is_open())
162 {
163 yError() << "YarpViconBridge: Could not open log file <" << logFile << ">...exiting";
164 return false;
165 }
166 }
167
168 // Connect to a server
169 yInfo() << "Connecting to " << hostname << " ...";
170 while( !viconClient.IsConnected().Connected )
171 {
172 // Direct connection
173 if(interrupted)
174 return false;
175
176 bool ok = false;
178 {
179 // Multicast connection
180 ok = ( viconClient.ConnectToMulticast( hostname, multicastAddress ).Result == Result::Success );
181
182 }
183 else
184 {
185 ok =( viconClient.Connect( hostname ).Result == Result::Success );
186 }
187 if(!ok)
188 {
189 yWarning() << "Connect failed...";
190 }
191
192 #ifdef WIN32
193 Sleep( 1000 );
194 #else
195 sleep(1);
196 #endif
197 }
198
199 // Enable some different data types
200 viconClient.EnableSegmentData();
201 viconClient.EnableMarkerData();
202 viconClient.EnableUnlabeledMarkerData();
203 viconClient.EnableMarkerRayData();
204 viconClient.EnableDeviceData();
205 viconClient.EnableDebugData();
206 if( bReadCentroids )
207 {
208 viconClient.EnableCentroidData();
209 }
210 if( bReadRayData )
211 {
212 viconClient.EnableMarkerRayData();
213 }
214
215 // Set the streaming mode
216 //viconClient.SetStreamMode( ViconDataStreamSDK::CPP::StreamMode::ClientPull );
217 //viconClient.SetStreamMode( ViconDataStreamSDK::CPP::StreamMode::ClientPullPreFetch );
218 viconClient.SetStreamMode( ViconDataStreamSDK::CPP::StreamMode::ServerPush );
219
220 // Set the global up axis
221 viconClient.SetAxisMapping( Direction::Forward,
222 Direction::Left,
223 Direction::Up ); // Z-up
224
225 if( axisMapping == "YUp")
226 {
227 viconClient.SetAxisMapping( Direction::Forward,
228 Direction::Up,
229 Direction::Right ); // Y-up
230 }
231 else if( axisMapping == "XUp")
232 {
233 viconClient.SetAxisMapping( Direction::Up,
234 Direction::Forward,
235 Direction::Left ); // X-up
236 }
237
238 if( clientBufferSize > 0 )
239 {
240 viconClient.SetBufferSize( clientBufferSize );
241 yInfo() << "Setting client buffer size to " << clientBufferSize ;
242 }
243
244 if( enableMultiCast )
245 {
246 assert( viconClient.IsConnected().Connected );
247 viconClient.StartTransmittingMulticast( hostname, multicastAddress );
248 }
249
250 // configuring transformClient
251 poly = new PolyDriver;
252 Property prop;
253 prop.put("device", "transformClient");
254 prop.put("local", "/transformClientVicon");
255 prop.put("remote", "/transformServer");
256 if(!poly->open(prop))
257 {
258 yError()<<"YarpViconBridge: unable to open `transformClient` device";
259 return false;
260 }
261
262 poly->view(itf);
263 if(!itf)
264 {
265 yError()<<"YarpViconBridge: unable to open `transformClient` device";
266 return false;
267 }
268
269 frameRateWindow = 1000; // frames
270 counter = 0;
271 lastTime = clock();
272 return PeriodicThread::start();
273
274}
275
276void YarpViconBridge::run()
277{
278 // Get a frame
279 if (!silent)
280 {
281 output_stream << "Waiting for new frame...";
282 }
283 if(interrupted)
284 this->close();
285 while( viconClient.GetFrame().Result != Result::Success)
286 {
287 // Sleep a little so that we don't lumber the CPU with a busy poll
288 #ifdef WIN32
289 Sleep( 200 );
290 #else
291 sleep(1);
292 #endif
293
294 output_stream << ".";
295 }
296 if(++counter == frameRateWindow)
297 {
298 clock_t Now = clock();
299 double FrameRate = static_cast<double>(frameRateWindow * CLOCKS_PER_SEC) / static_cast<double>(Now - lastTime);
300 if(!logFile.empty())
301 {
303 struct tm * timeinfo;
304 time ( &rawtime );
306
307 ofs << "Frame rate = " << FrameRate << " at " << asctime (timeinfo)<< std::endl;
308 }
309
310 lastTime = Now;
311 counter = 0;
312 }
313
314 // Get the frame number
316 Output_GetFrameRate Rate = viconClient.GetFrameRate();
317
318 if (!silent)
319 {
320 yInfo() << "Frame rate: " << Rate.FrameRateHz;
321 output_stream << "Frame Number: " << _Output_GetFrameNumber.FrameNumber ;
322 // Get the latency
323 output_stream << "Latency: " << viconClient.GetLatencyTotal().Total << "s" ;
324 }
325
326 for( unsigned int LatencySampleIndex = 0 ; LatencySampleIndex < viconClient.GetLatencySampleCount().Count ; ++LatencySampleIndex )
327 {
328 std::string SampleName = viconClient.GetLatencySampleName( LatencySampleIndex ).Name;
329 double SampleValue = viconClient.GetLatencySampleValue( SampleName ).Value;
330
331 if (!silent)
332 {
333 output_stream << " " << SampleName << " " << SampleValue << "s" ;
334 }
335 }
336
338 if (!silent)
339 {
341 output_stream << "Hardware Frame Number: " << _Output_GetHardwareFrameNumber.HardwareFrameNumber;
342 }
343
344
345
346 if (test_frame!="")
347 {
349 test_matrix.eye();
350 static double start_test_time = yarp::os::Time::now();
354 }
355
356 // Count the number of subjects
357 unsigned int SubjectCount = viconClient.GetSubjectCount().SubjectCount;
358 if (!silent)
359 {
360 output_stream << "Subjects (" << SubjectCount << "):" ;
361 }
362
363 for( unsigned int SubjectIndex = 0 ; SubjectIndex < SubjectCount ; ++SubjectIndex )
364 {
365 // Get the subject name
366 std::string SubjectName = viconClient.GetSubjectName( SubjectIndex ).SubjectName;
367 // Get the root segment
368 std::string RootSegment = viconClient.GetSubjectRootSegmentName( SubjectName ).SegmentName;
369 // Count the number of segments
370 unsigned int SegmentCount = viconClient.GetSegmentCount( SubjectName ).SegmentCount;
371
372 if (!silent)
373 {
374 output_stream << " Subject #" << SubjectIndex ;
375 output_stream << " Name: " << SubjectName ;
376 output_stream << " Root Segment: " << RootSegment ;
377 output_stream << " Segments (" << SegmentCount << "):" ;
378 }
379
380 for( unsigned int SegmentIndex = 0 ; SegmentIndex < SegmentCount ; ++SegmentIndex )
381 {
382 // Get the segment name
383 std::string SegmentName = viconClient.GetSegmentName( SubjectName, SegmentIndex ).SegmentName;
384
385 // Get the segment parent
386 std::string SegmentParentName = viconClient.GetSegmentParentName( SubjectName, SegmentName ).SegmentName;
387
388 // Get the segment's children
389 unsigned int ChildCount = viconClient.GetSegmentChildCount( SubjectName, SegmentName ).SegmentCount;
390
391 if (!silent)
392 {
393 output_stream << " Segment #" << SegmentIndex ;
394 output_stream << " Name: " << SegmentName;
395 output_stream << " Parent: " << SegmentParentName;
396 output_stream << " Children (" << ChildCount << "):";
397 for( unsigned int ChildIndex = 0 ; ChildIndex < ChildCount ; ++ChildIndex )
398 {
399 std::string ChildName = viconClient.GetSegmentChildName( SubjectName, SegmentName, ChildIndex ).SegmentName;
400 output_stream << " " << ChildName ;
401 }
402 }
403
404 // Get the global segment rotation as a matrix
406 viconClient.GetSegmentGlobalRotationMatrix( SubjectName, SegmentName );
408 viconClient.GetSegmentGlobalTranslation( SubjectName, SegmentName );
409 yarp::sig::Matrix m1(4, 4);
410 m1[0][0] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 0 ]; m1[0][1] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 1 ]; m1[0][2] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 2 ]; m1[0][3] = _Output_GetSegmentGlobalTranslation.Translation[ 0 ]/1000.0;
411 m1[1][0] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 3 ]; m1[1][1] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 4 ]; m1[1][2] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 5 ]; m1[1][3] = _Output_GetSegmentGlobalTranslation.Translation[ 1 ]/1000.0;
412 m1[2][0] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 6 ]; m1[2][1] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 7 ]; m1[2][2] = _Output_GetSegmentGlobalRotationMatrix.Rotation[ 8 ]; m1[2][3] = _Output_GetSegmentGlobalTranslation.Translation[ 2 ]/1000.0;
413 m1[3][0] = 0; m1[3][1] = 0; m1[3][2] = 0; m1[3][3] = 1;
414
416 {
417 std::string tf_name;
418 if (subject_string!="")
419 {
421 }
422 else
423 {
424 if (segment_string !="")
425 {
427 }
428 else
429 {
431 }
432 }
433 if(inversion)
434 {
436 itf->setTransform(viconroot_string, tf_name, m1);
437
438 }
439 else
440 {
441 itf->setTransform(tf_name, viconroot_string, m1);
442 }
443 }
444 }
445
446
448 {
449 // Count the number of markers
450 unsigned int MarkerCount = viconClient.GetMarkerCount( SubjectName ).MarkerCount;
451 if (!silent)
452 {
453 output_stream << " Markers (" << MarkerCount << "):";
454 }
455
456 for( unsigned int MarkerIndex = 0 ; MarkerIndex < MarkerCount ; ++MarkerIndex )
457 {
458 // Get the marker name
459 std::string MarkerName = viconClient.GetMarkerName( SubjectName, MarkerIndex ).MarkerName;
460
461 // Get the marker parent
462 std::string MarkerParentName = viconClient.GetMarkerParentName( SubjectName, MarkerName ).SegmentName;
463
464 // Get the global marker translation
466 viconClient.GetMarkerGlobalTranslation( SubjectName, MarkerName );
467
468 yarp::sig::Matrix m1(4, 4);
469 m1[0][0] = 1; m1[0][1] = 0; m1[0][2] = 0; m1[0][3] = _Output_GetMarkerGlobalTranslation.Translation[ 0 ]/1000.0;
470 m1[1][0] = 0; m1[1][1] = 1; m1[1][2] = 0; m1[1][3] = _Output_GetMarkerGlobalTranslation.Translation[ 1 ]/1000.0;
471 m1[2][0] = 0; m1[2][1] = 0; m1[2][2] = 1; m1[2][3] = _Output_GetMarkerGlobalTranslation.Translation[ 2 ]/1000.0;
472 m1[3][0] = 0; m1[3][1] = 0; m1[3][2] = 0; m1[3][3] = 1;
473
474 std::string tf_name;
475 if (subject_string!="")
476 {
478 }
479 else
480 {
481 if (labeled_marker_string !="")
482 {
484 }
485 else
486 {
488 }
489 }
490
491 if(inversion)
492 {
494 itf->setTransform(viconroot_string, tf_name, m1);
495 }
496 else
497 {
498 itf->setTransform(tf_name, viconroot_string, m1);
499 }
500
501 if (!silent)
502 {
503 if (!bReadRayData)
504 {
505 continue;
506 }
508 viconClient.GetMarkerRayContributionCount(SubjectName, MarkerName);
509
510 if( _Output_GetMarkerRayContributionCount.Result != Result::Success )
511 {
512 continue;
513 }
514 output_stream << " Contributed to by: ";
515 for( unsigned int ContributionIndex = 0; ContributionIndex < _Output_GetMarkerRayContributionCount.RayContributionsCount; ++ContributionIndex )
516 {
518 viconClient.GetMarkerRayContribution( SubjectName, MarkerName, ContributionIndex );
519 output_stream << "ID:" << _Output_GetMarkerRayContribution.CameraID << " Index:" << _Output_GetMarkerRayContribution.CentroidIndex << " ";
520 }
521 }
522 }
523 }
524 }
525
526 // Get the unlabeled markers
527 unsigned int UnlabeledMarkerCount = viconClient.GetUnlabeledMarkerCount().MarkerCount;
529 {
530 // Get the global marker translation
532 viconClient.GetUnlabeledMarkerGlobalTranslation( UnlabeledMarkerIndex );
533
534 yarp::sig::Matrix m1(4, 4);
535 m1[0][0] = 1; m1[0][1] = 0; m1[0][2] = 0; m1[0][3] = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[ 0 ]/1000.0;
536 m1[1][0] = 0; m1[1][1] = 1; m1[1][2] = 0; m1[1][3] = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[ 1 ]/1000.0;
537 m1[2][0] = 0; m1[2][1] = 0; m1[2][2] = 1; m1[2][3] = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[ 2 ]/1000.0;
538 m1[3][0] = 0; m1[3][1] = 0; m1[3][2] = 0; m1[3][3] = 1;
539
541 {
542 std::string tf_name = unlabeled_marker_string + std::to_string(UnlabeledMarkerIndex);
543 if(inversion)
544 {
546 itf->setTransform(viconroot_string, tf_name, m1);
547 }
548 else
549 {
550 itf->setTransform(tf_name, viconroot_string, m1);
551 }
552
553 }
554 }
555}
556
557bool YarpViconBridge::close()
558{
561 interrupted = true;
562 if(poly)
563 {
564 poly->close();
565 delete poly;
566 poly = nullptr;
567 }
568 if( enableMultiCast )
569 {
570 viconClient.StopTransmittingMulticast();
571 }
572 viconClient.DisableSegmentData();
573 viconClient.DisableMarkerData();
574 viconClient.DisableUnlabeledMarkerData();
575 viconClient.DisableDeviceData();
576 if( bReadCentroids )
577 {
578 viconClient.DisableCentroidData();
579 }
580 if( bReadRayData )
581 {
582 bReadRayData = false;
583 }
584
585 // Disconnect and dispose
586 auto t = clock();
587 yInfo() << " Disconnecting..." ;
588 viconClient.Disconnect();
589 auto dt = clock() - t;
590 double secs = static_cast<double>(dt)/static_cast<double>(CLOCKS_PER_SEC);
591 yInfo() << " Disconnect time = " << secs << " secs" ;
592
593 return true;
594}
#define yInfo(...)
Definition Log.h:319
#define yError(...)
Definition Log.h:361
#define yWarning(...)
Definition Log.h:340
#define output_stream
constexpr uint32_t default_rate
A container for a device driver.
Definition PolyDriver.h:23
A mini-server for performing network communication in the background.
void close() override
Stop port activity.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
An abstraction for a periodic thread.
bool isRunning() const
Returns true when the thread is started, false otherwise.
bool start()
Call this to start the thread.
void stop()
Call this to stop the thread, this call blocks until the thread is terminated (and releaseThread() ca...
A class for storing options and configuration information.
Definition Property.h:33
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition Property.cpp:987
A base class for nested structures that can be searched.
Definition Searchable.h:31
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
virtual Value & find(const std::string &key) const =0
Gets a value corresponding to a given keyword.
A class for a Matrix.
Definition Matrix.h:39
For streams capable of holding different kinds of content, check what they actually have.
yarp::sig::Matrix SE3inv(const yarp::sig::Matrix &H)
Returns the inverse of a 4 by 4 rototranslational matrix (defined in Math.h).
Definition math.cpp:912
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
An interface to the operating system, including Port based communication.