HAPTIX API

haptix_sim_utils.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Open Source Robotics Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17 
20 
21 #ifndef __HAPTIX_SIM_UTILS_API_HAPTIX_H__
22 #define __HAPTIX_SIM_UTILS_API_HAPTIX_H__
23 
24 #include <iostream>
25 #include <string>
26 #include <mutex>
27 #include <ignition/transport.hh>
28 #include "haptix/comm/haptix.h"
29 #include "msg/hxCollideMode.pb.h"
30 #include "msg/hxColor.pb.h"
31 #include "msg/hxContactPoint_V.pb.h"
32 #include "msg/hxEmpty.pb.h"
33 #include "msg/hxJoint.pb.h"
34 #include "msg/hxLink.pb.h"
35 #include "msg/hxModel.pb.h"
36 #include "msg/hxQuaternion.pb.h"
37 #include "msg/hxSimInfo.pb.h"
38 #include "msg/hxTime.pb.h"
39 #include "msg/hxTransform.pb.h"
40 #include "msg/hxVector3.pb.h"
41 
43 unsigned int kTimeout = 1000;
44 
46 static std::string lastResult;
47 static std::mutex lastResultLock;
48 
50 static ignition::transport::Node *haptixSimUtilsNode = NULL;
51 
56 static ignition::transport::Node *getHxNode()
57 {
58  if (!haptixSimUtilsNode)
59  haptixSimUtilsNode = new ignition::transport::Node();
60 
61  return haptixSimUtilsNode;
62 }
63 
69 template <typename T, typename T2> bool hxs_convertScalar(T _in, T2 *_out)
70 {
71  if (!_in.has_data())
72  {
73  std::cerr << "hxs_convertScalar() error: No [data] in msg" << std::endl;
74  return false;
75  }
76 
77  if (!_out)
78  {
79  std::cerr << "hxs_convertScalar() error: NULL output" << std::endl;
80  return false;
81  }
82 
83  *_out = _in.data();
84  return true;
85 }
86 
93 static bool hxs_convertVector3(const haptix::comm::msgs::hxVector3 _in,
94  hxsVector3 *_out)
95 {
96  if (!_out)
97  {
98  std::cerr << "hxs_convertVector3() error: NULL output" << std::endl;
99  return false;
100  }
101 
102  // Initialize the C struct.
103  memset(_out, 0, sizeof(hxsVector3));
104 
105  _out->x = _in.x();
106  _out->y = _in.y();
107  _out->z = _in.z();
108 
109  return true;
110 }
111 
118 static bool hxs_convertVector3(const hxsVector3 *_in,
119  haptix::comm::msgs::hxVector3 *_out)
120 {
121  if (!_in)
122  {
123  std::cerr << "hxs_convertVector3() error: NULL input" << std::endl;
124  return false;
125  }
126 
127  if (!_out)
128  {
129  std::cerr << "hxs_convertVector3() error: NULL output" << std::endl;
130  return false;
131  }
132 
133  // Initialize the protobuf message.
134  _out->Clear();
135 
136  _out->set_x(_in->x);
137  _out->set_y(_in->y);
138  _out->set_z(_in->z);
139 
140  return true;
141 }
142 
149 static bool hxs_convertQuaternion(const haptix::comm::msgs::hxQuaternion _in,
150  hxsQuaternion *_out)
151 {
152  if (!_out)
153  {
154  std::cerr << "hxs_convertQuaternion() error: NULL output" << std::endl;
155  return false;
156  }
157 
158  // Initialize the C struct.
159  memset(_out, 0, sizeof(hxsQuaternion));
160 
161  _out->w = _in.w();
162  _out->x = _in.x();
163  _out->y = _in.y();
164  _out->z = _in.z();
165 
166  return true;
167 }
168 
175 static bool hxs_convertQuaternion(const hxsQuaternion *_in,
176  haptix::comm::msgs::hxQuaternion *_out)
177 {
178  if (!_in)
179  {
180  std::cerr << "hxs_convertQuaternion() error: NULL input" << std::endl;
181  return false;
182  }
183 
184  if (!_out)
185  {
186  std::cerr << "hxs_convertQuaternion() error: NULL output" << std::endl;
187  return false;
188  }
189 
190  // Initialize the protobuf message.
191  _out->Clear();
192 
193  _out->set_w(_in->w);
194  _out->set_x(_in->x);
195  _out->set_y(_in->y);
196  _out->set_z(_in->z);
197 
198  return true;
199 }
200 
207 static bool hxs_convertColor(const haptix::comm::msgs::hxColor _in,
208  hxsColor *_out)
209 {
210  if (!_out)
211  {
212  std::cerr << "hxs_convertColor() error: NULL output" << std::endl;
213  return false;
214  }
215 
216  // Initialize the C struct.
217  memset(_out, 0, sizeof(hxsColor));
218 
219  _out->r = _in.r();
220  _out->g = _in.g();
221  _out->b = _in.b();
222  _out->alpha = _in.alpha();
223 
224  return true;
225 }
226 
233 static bool hxs_convertCollisionMode(
234  const haptix::comm::msgs::hxCollideMode _in, hxsCollideMode *_out)
235 {
236  if (!_out)
237  {
238  std::cerr << "hxs_convertCollisionMode() error: NULL output" << std::endl;
239  return false;
240  }
241 
242  // Initialize the C struct.
243  memset(_out, 0, sizeof(hxsCollideMode));
244 
245  switch (_in.mode())
246  {
247  case haptix::comm::msgs::hxCollideMode::hxsNOCOLLIDE:
248  *_out = hxsNOCOLLIDE;
249  break;
250  case haptix::comm::msgs::hxCollideMode::hxsDETECTIONONLY:
251  *_out = hxsDETECTIONONLY;
252  break;
253  case haptix::comm::msgs::hxCollideMode::hxsCOLLIDE:
254  *_out = hxsCOLLIDE;
255  break;
256  default:
257  std::cerr << "hxs_convertCollisionMode() error: Unkown collision mode ["
258  << _in.mode() << "]" << std::endl;
259  return false;
260  }
261 
262  return true;
263 }
264 
271 static bool hxs_convertTransform(const haptix::comm::msgs::hxTransform _in,
272  hxsTransform *_out)
273 {
274  if (!_out)
275  {
276  std::cerr << "hxs_convertTransform() error: NULL output" << std::endl;
277  return false;
278  }
279 
280  // Initialize the C struct.
281  memset(_out, 0, sizeof(hxsTransform));
282 
283  bool result = true;
284  result &= hxs_convertVector3(_in.pos(), &_out->pos);
285  result &= hxs_convertQuaternion(_in.orient(), &_out->orient);
286 
287  return result;
288 }
289 
296 static bool hxs_convertTransform(const hxsTransform *_in,
297  haptix::comm::msgs::hxTransform *_out)
298 {
299  if (!_in)
300  {
301  std::cerr << "hxs_convertTransform() error: NULL input" << std::endl;
302  return false;
303  }
304 
305  if (!_out)
306  {
307  std::cerr << "hxs_convertTransform() error: NULL output" << std::endl;
308  return false;
309  }
310 
311  // Initialize the message.
312  _out->Clear();
313 
314  bool result = true;
315  result &= hxs_convertVector3(&(_in->pos), _out->mutable_pos());
316  result &= hxs_convertQuaternion(&(_in->orient), _out->mutable_orient());
317 
318  return result;
319 }
320 
327 static bool hxs_convertJoint(const haptix::comm::msgs::hxJoint _in,
328  hxsJoint *_out)
329 {
330  if (!_out)
331  {
332  std::cerr << "hxs_convertJoint() error: NULL output" << std::endl;
333  return false;
334  }
335 
336  // Initialize the C struct.
337  memset(_out, 0, sizeof(hxsJoint));
338 
339  if (_in.name().size() > hxsMAXNAMESIZE - 1)
340  {
341  std::cerr << "hxs_convertJoint() error: The name of the joint ["
342  << _in.name() << "] exceeds the maximum size allowed ("
343  << hxsMAXNAMESIZE << " chars)." << std::endl;
344  return false;
345  }
346 
347  strncpy(_out->name, _in.name().c_str(), strlen(_in.name().c_str()));
348  _out->name[strlen(_in.name().c_str())] = '\0';
349  _out->pos = _in.pos();
350  _out->vel = _in.vel();
351  _out->torque_motor = _in.torque_motor();
352 
353  bool result = true;
354  result &= hxs_convertVector3(_in.wrench_reactive().force(),
355  &_out->wrench_reactive.force);
356 
357  result &= hxs_convertVector3(_in.wrench_reactive().torque(),
358  &_out->wrench_reactive.torque);
359 
360  return result;
361 }
362 
369 static bool hxs_convertWrench(const hxsWrench *_in,
370  haptix::comm::msgs::hxWrench *_out)
371 {
372  if (!_in)
373  {
374  std::cerr << "hxs_convertWrench() error: NULL input" << std::endl;
375  return false;
376  }
377 
378  if (!_out)
379  {
380  std::cerr << "hxs_convertWrench() error: NULL output" << std::endl;
381  return false;
382  }
383 
384  bool result = true;
385  result &= hxs_convertVector3(&_in->force, _out->mutable_force());
386  result &= hxs_convertVector3(&_in->torque, _out->mutable_torque());
387  return result;
388 }
389 
396 static bool hxs_convertLink(const haptix::comm::msgs::hxLink _in, hxsLink *_out)
397 {
398  if (!_out)
399  {
400  std::cerr << "hxs_convertLink() error: NULL output" << std::endl;
401  return false;
402  }
403 
404  // Initialize the C struct.
405  memset(_out, 0, sizeof(hxsLink));
406 
407  if (_in.name().size() > hxsMAXNAMESIZE - 1)
408  {
409  std::cerr << "hxs_convertLink() error: The name of the link ["
410  << _in.name() << "] exceeds the maximum size allowed ("
411  << hxsMAXNAMESIZE << " chars)." << std::endl;
412  return false;
413  }
414 
415  strncpy(_out->name, _in.name().c_str(), strlen(_in.name().c_str()));
416  _out->name[strlen(_in.name().c_str())] = '\0';
417 
418  bool result = true;
419  result &= hxs_convertTransform(_in.transform(), &_out->transform);
420  result &= hxs_convertVector3(_in.lin_vel(), &_out->lin_vel);
421  result &= hxs_convertVector3(_in.ang_vel(), &_out->ang_vel);
422  result &= hxs_convertVector3(_in.lin_acc(), &_out->lin_acc);
423  result &= hxs_convertVector3(_in.ang_acc(), &_out->ang_acc);
424 
425  return result;
426 }
427 
434 static bool hxs_convertModel(const haptix::comm::msgs::hxModel _in,
435  hxsModel *_out)
436 {
437  if (_in.name().size() > hxsMAXNAMESIZE - 1)
438  {
439  std::cerr << "hxs_convertModel() error: The name of the model ["
440  << _in.name() << "] exceeds the maximum size allowed ("
441  << hxsMAXNAMESIZE << " chars)." << std::endl;
442  return false;
443  }
444 
445  if (!_out)
446  {
447  std::cerr << "hxs_convertModel() error: NULL output" << std::endl;
448  return false;
449  }
450 
451  // Initialize the C struct.
452  memset(_out, 0, sizeof(hxsModel));
453 
454  strncpy(_out->name, _in.name().c_str(), strlen(_in.name().c_str()));
455  _out->name[strlen(_in.name().c_str())] = '\0';
456 
457  bool result = true;
458  result &= hxs_convertTransform(_in.transform(), &(_out->transform));
459  _out->link_count = _in.links_size();
460  _out->joint_count = _in.joints_size();
461 
462  // Fill the links.
463  for (int i = 0; i < _out->link_count; ++i)
464  result &= hxs_convertLink(_in.links(i), &_out->links[i]);
465 
466  // Fill the joints.
467  for (int i = 0; i < _out->joint_count; ++i)
468  result &= hxs_convertJoint(_in.joints(i), &_out->joints[i]);
469 
470  _out->gravity_mode = _in.gravity_mode();
471 
472  return result;
473 }
474 
481 static bool hxs_convertContactPoints(
482  const haptix::comm::msgs::hxContactPoint_V _in, hxsContactPoints *_out)
483 {
484  if (!_out)
485  {
486  std::cerr << "hxs_convertContactPoints() error: NULL output" << std::endl;
487  return false;
488  }
489 
490  // Initialize the C struct.
491  memset(_out, 0, sizeof(hxsContactPoints));
492 
493  _out->contact_count = _in.contacts_size();
494 
495  bool result = true;
496 
497  for (int i = 0; i < _out->contact_count; ++i)
498  {
499  if (_in.contacts(i).link1().size() > hxsMAXNAMESIZE - 1)
500  {
501  std::cerr << "hxs_convertContactPoints() error: The name of the link1 ["
502  << _in.contacts(i).link1() << "] exceeds the maximum size "
503  << "allowed (" << hxsMAXNAMESIZE << " chars)." << std::endl;
504  return false;
505  }
506 
507  if (_in.contacts(i).link2().size() > hxsMAXNAMESIZE - 1)
508  {
509  std::cerr << "hxs_convertContactPoints() error: The name of the link2 ["
510  << _in.contacts(i).link2() << "] exceeds the maximum size "
511  << "allowed (" << hxsMAXNAMESIZE << " chars)." << std::endl;
512  return false;
513  }
514 
515  strncpy(_out->contacts[i].link1, _in.contacts(i).link1().c_str(),
516  strlen(_in.contacts(i).link1().c_str()));
517  _out->contacts[i].link1[strlen(_in.contacts(i).link1().c_str())] = '\0';
518 
519  strncpy(_out->contacts[i].link2, _in.contacts(i).link2().c_str(),
520  strlen(_in.contacts(i).link2().c_str()));
521  _out->contacts[i].link2[strlen(_in.contacts(i).link2().c_str())] = '\0';
522 
523  result &= hxs_convertVector3(_in.contacts(i).point(),
524  &_out->contacts[i].point);
525  result &= hxs_convertVector3(_in.contacts(i).normal(),
526  &_out->contacts[i].normal);
527  _out->contacts[i].distance = _in.contacts(i).distance();
528  result &= hxs_convertVector3(_in.contacts(i).wrench().force(),
529  &_out->contacts[i].wrench.force);
530  result &= hxs_convertVector3(_in.contacts(i).wrench().torque(),
531  &_out->contacts[i].wrench.torque);
532  }
533 
534  return result;
535 }
536 
543 static bool hxs_convertSimInfo(const haptix::comm::msgs::hxSimInfo _in,
544  hxsSimInfo *_out)
545 {
546  if (!_out)
547  {
548  std::cerr << "hxs_convertSimInfo() error: NULL output" << std::endl;
549  return false;
550  }
551 
552  // Initialize the C struct.
553  memset(_out, 0, sizeof(hxsSimInfo));
554 
555  _out->model_count = _in.models_size();
556 
557  bool result = true;
558 
559  // Fill the models.
560  for (int i = 0; i < _out->model_count; ++i)
561  result &= hxs_convertModel(_in.models(i), &_out->models[i]);
562 
563  // Fill the camera.
564  result &= hxs_convertTransform(_in.camera_transform(),
565  &_out->camera_transform);
566 
567  return result;
568 }
569 
581 template<typename REQ, typename REP, typename T>
582 hxResult hxs_call(const std::string &_service,
583  const std::string &_funcName,
584  const REQ _req,
585  REP _rep,
586  T _dst,
587  bool (*_f)(const REP _rep, T _dst))
588 {
589  bool result;
590  ignition::transport::Node *hxNode = getHxNode();
591 
592  // Request the service.
593  bool executed = hxNode->Request(_service, _req, kTimeout, _rep, result);
594 
595  if (executed)
596  {
597  if (result)
598  {
599  // Fill the struct with the response.
600  if (_f(_rep, _dst))
601  return hxOK;
602  else
603  return hxERROR;
604  }
605  else
606  {
607  std::lock_guard<std::mutex> lock(lastResultLock);
608  lastResult = _funcName + "() Service call failed.";
609  std::cerr << lastResult << std::endl;
610  }
611  }
612  else
613  {
614  std::lock_guard<std::mutex> lock(lastResultLock);
615  lastResult = _funcName + "() Service call timed out.";
616  std::cerr << lastResult << std::endl;
617  }
618 
619  return hxERROR;
620 }
621 
628 template<typename REQ, typename REP>
629 hxResult hxs_call(const std::string &_service,
630  const std::string &_funcName,
631  const REQ _req,
632  REP _rep)
633 {
634  bool result;
635  ignition::transport::Node *hxNode = getHxNode();
636 
637  // Request the service.
638  bool executed = hxNode->Request(_service, _req, kTimeout, _rep, result);
639 
640  if (executed)
641  {
642  if (result)
643  return hxOK;
644  else
645  {
646  std::lock_guard<std::mutex> lock(lastResultLock);
647  lastResult = _funcName + "() Service call failed.";
648  std::cerr << lastResult << std::endl;
649  }
650  }
651  else
652  {
653  std::lock_guard<std::mutex> lock(lastResultLock);
654  lastResult = _funcName + "() Service call timed out.";
655  std::cerr << lastResult << std::endl;
656  }
657 
658  return hxERROR;
659 }
660 
661 #endif
unsigned int kTimeout
Timeout used for the service requests (ms.).
Definition: haptix_sim_utils.h:43
hxResult hxs_call(const std::string &_service, const std::string &_funcName, const REQ _req, REP _rep, T _dst, bool(*_f)(const REP _rep, T _dst))
Function that requests a given service and converts the protobuf response to a C-struct.
Definition: haptix_sim_utils.h:582
success
Definition: haptix.h:63
#define hxsMAXNAMESIZE
Maximum number of characters allowed per name.
Definition: haptix_sim.h:46
failure
Definition: haptix.h:65
static ignition::transport::Node * haptixSimUtilsNode
ignition transport node.
Definition: haptix_sim_utils.h:50
hxResult
API return codes.
Definition: haptix.h:60
Structures and functions for the primary HAPTIX API.
static std::string lastResult
Error string, to be retrieved by hx_last_result()
Definition: haptix_sim_utils.h:46