kitt_platform
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Macros
node_handle.h
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage, Inc. nor the names of its
18  * contributors may be used to endorse or promote prducts derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #ifndef ROS_NODE_HANDLE_H_
36 #define ROS_NODE_HANDLE_H_
37 
38 #include <stdint.h>
39 
40 #include "std_msgs/Time.h"
42 #include "rosserial_msgs/Log.h"
44 
45 #define SYNC_SECONDS 5
46 
47 #define MODE_FIRST_FF 0
48 /*
49  * The second sync byte is a protocol version. It's value is 0xff for the first
50  * version of the rosserial protocol (used up to hydro), 0xfe for the second version
51  * (introduced in hydro), 0xfd for the next, and so on. Its purpose is to enable
52  * detection of mismatched protocol versions (e.g. hydro rosserial_python with groovy
53  * rosserial_arduino. It must be changed in both this file and in
54  * rosserial_python/src/rosserial_python/SerialClient.py
55  */
56 #define MODE_PROTOCOL_VER 1
57 #define PROTOCOL_VER1 0xff // through groovy
58 #define PROTOCOL_VER2 0xfe // in hydro
59 #define PROTOCOL_VER PROTOCOL_VER2
60 #define MODE_SIZE_L 2
61 #define MODE_SIZE_H 3
62 #define MODE_SIZE_CHECKSUM 4 // checksum for msg size received from size L and H
63 #define MODE_TOPIC_L 5 // waiting for topic id
64 #define MODE_TOPIC_H 6
65 #define MODE_MESSAGE 7
66 #define MODE_MSG_CHECKSUM 8 // checksum for msg and topic id
67 
68 
69 #define MSG_TIMEOUT 20 //20 milliseconds to recieve all of message data
70 
71 #include "msg.h"
72 
73 namespace ros {
74 
76  public:
77  virtual int publish(int id, const Msg* msg)=0;
78  virtual int spinOnce()=0;
79  virtual bool connected()=0;
80  };
81 }
82 
83 #include "publisher.h"
84 #include "subscriber.h"
85 #include "service_server.h"
86 #include "service_client.h"
87 
88 namespace ros {
89 
91 
92  /* Node Handle */
93  template<class Hardware,
94  int MAX_SUBSCRIBERS=25,
95  int MAX_PUBLISHERS=25,
96  int INPUT_SIZE=512,
97  int OUTPUT_SIZE=512>
99  {
100  protected:
101  Hardware hardware_;
102 
103  /* time used for syncing */
104  uint32_t rt_time;
105 
106  /* used for computing current time */
108 
109  uint8_t message_in[INPUT_SIZE];
110  uint8_t message_out[OUTPUT_SIZE];
111 
112  Publisher * publishers[MAX_PUBLISHERS];
113  Subscriber_ * subscribers[MAX_SUBSCRIBERS];
114 
115  /*
116  * Setup Functions
117  */
118  public:
120 
121  for(unsigned int i=0; i< MAX_PUBLISHERS; i++)
122  publishers[i] = 0;
123 
124  for(unsigned int i=0; i< MAX_SUBSCRIBERS; i++)
125  subscribers[i] = 0;
126 
127  for(unsigned int i=0; i< INPUT_SIZE; i++)
128  message_in[i] = 0;
129 
130  for(unsigned int i=0; i< OUTPUT_SIZE; i++)
131  message_out[i] = 0;
132 
134  req_param_resp.ints = NULL;
136  req_param_resp.floats = NULL;
138  req_param_resp.ints = NULL;
139  }
140 
141  Hardware* getHardware(){
142  return &hardware_;
143  }
144 
145  /* Start serial, initialize buffers */
146  void initNode(){
147  hardware_.init();
148  mode_ = 0;
149  bytes_ = 0;
150  index_ = 0;
151  topic_ = 0;
152  };
153 
154  /* Start a named port, which may be network server IP, initialize buffers */
155  void initNode(char *portName){
156  hardware_.init(portName);
157  mode_ = 0;
158  bytes_ = 0;
159  index_ = 0;
160  topic_ = 0;
161  };
162 
163  protected:
164  //State machine variables for spinOnce
165  int mode_;
166  int bytes_;
167  int topic_;
168  int index_;
170 
172 
173  /* used for syncing the time */
174  uint32_t last_sync_time;
177 
178  public:
179  /* This function goes in your loop() function, it handles
180  * serial input and callbacks for subscribers.
181  */
182 
183 
184  virtual int spinOnce(){
185 
186  /* restart if timed out */
187  uint32_t c_time = hardware_.time();
188  if( (c_time - last_sync_receive_time) > (SYNC_SECONDS*2200) ){
189  configured_ = false;
190  }
191 
192  /* reset if message has timed out */
193  if ( mode_ != MODE_FIRST_FF){
194  if (c_time > last_msg_timeout_time){
196  }
197  }
198 
199  /* while available buffer, read data */
200  while( true )
201  {
202  int data = hardware_.read();
203  if( data < 0 )
204  break;
205  checksum_ += data;
206  if( mode_ == MODE_MESSAGE ){ /* message data being recieved */
207  message_in[index_++] = data;
208  bytes_--;
209  if(bytes_ == 0) /* is message complete? if so, checksum */
211  }else if( mode_ == MODE_FIRST_FF ){
212  if(data == 0xff){
213  mode_++;
215  }
216  else if( hardware_.time() - c_time > (SYNC_SECONDS)){
217  /* We have been stuck in spinOnce too long, return error */
218  configured_=false;
219  return -2;
220  }
221  }else if( mode_ == MODE_PROTOCOL_VER ){
222  if(data == PROTOCOL_VER){
223  mode_++;
224  }else{
226  if (configured_ == false)
227  requestSyncTime(); /* send a msg back showing our protocol version */
228  }
229  }else if( mode_ == MODE_SIZE_L ){ /* bottom half of message size */
230  bytes_ = data;
231  index_ = 0;
232  mode_++;
233  checksum_ = data; /* first byte for calculating size checksum */
234  }else if( mode_ == MODE_SIZE_H ){ /* top half of message size */
235  bytes_ += data<<8;
236  mode_++;
237  }else if( mode_ == MODE_SIZE_CHECKSUM ){
238  if( (checksum_%256) == 255)
239  mode_++;
240  else
241  mode_ = MODE_FIRST_FF; /* Abandon the frame if the msg len is wrong */
242  }else if( mode_ == MODE_TOPIC_L ){ /* bottom half of topic id */
243  topic_ = data;
244  mode_++;
245  checksum_ = data; /* first byte included in checksum */
246  }else if( mode_ == MODE_TOPIC_H ){ /* top half of topic id */
247  topic_ += data<<8;
249  if(bytes_ == 0)
251  }else if( mode_ == MODE_MSG_CHECKSUM ){ /* do checksum */
253  if( (checksum_%256) == 255){
255  requestSyncTime();
256  negotiateTopics();
257  last_sync_time = c_time;
258  last_sync_receive_time = c_time;
259  return -1;
260  }else if(topic_ == TopicInfo::ID_TIME){
264  param_recieved= true;
265  }else if(topic_ == TopicInfo::ID_TX_STOP){
266  configured_ = false;
267  }else{
268  if(subscribers[topic_-100])
270  }
271  }
272  }
273  }
274 
275  /* occasionally sync time */
276  if( configured_ && ((c_time-last_sync_time) > (SYNC_SECONDS*500) )){
277  requestSyncTime();
278  last_sync_time = c_time;
279  }
280 
281  return 0;
282  }
283 
284 
285  /* Are we connected to the PC? */
286  virtual bool connected() {
287  return configured_;
288  };
289 
290  /********************************************************************
291  * Time functions
292  */
293 
295  {
296  std_msgs::Time t;
298  rt_time = hardware_.time();
299  }
300 
301  void syncTime(uint8_t * data)
302  {
303  std_msgs::Time t;
304  uint32_t offset = hardware_.time() - rt_time;
305 
306  t.deserialize(data);
307  t.data.sec += offset/1000;
308  t.data.nsec += (offset%1000)*1000000UL;
309 
310  this->setNow(t.data);
312  }
313 
315  {
316  uint32_t ms = hardware_.time();
317  Time current_time;
318  current_time.sec = ms/1000 + sec_offset;
319  current_time.nsec = (ms%1000)*1000000UL + nsec_offset;
320  normalizeSecNSec(current_time.sec, current_time.nsec);
321  return current_time;
322  }
323 
324  void setNow( Time & new_now )
325  {
326  uint32_t ms = hardware_.time();
327  sec_offset = new_now.sec - ms/1000 - 1;
328  nsec_offset = new_now.nsec - (ms%1000)*1000000UL + 1000000000UL;
330  }
331 
332  /********************************************************************
333  * Topic Management
334  */
335 
336  /* Register a new publisher */
338  {
339  for(int i = 0; i < MAX_PUBLISHERS; i++){
340  if(publishers[i] == 0){ // empty slot
341  publishers[i] = &p;
342  p.id_ = i+100+MAX_SUBSCRIBERS;
343  p.nh_ = this;
344  return true;
345  }
346  }
347  return false;
348  }
349 
350  /* Register a new subscriber */
351  template<typename MsgT>
353  for(int i = 0; i < MAX_SUBSCRIBERS; i++){
354  if(subscribers[i] == 0){ // empty slot
355  subscribers[i] = (Subscriber_*) &s;
356  s.id_ = i+100;
357  return true;
358  }
359  }
360  return false;
361  }
362 
363  /* Register a new Service Server */
364  template<typename MReq, typename MRes>
366  bool v = advertise(srv.pub);
367  for(int i = 0; i < MAX_SUBSCRIBERS; i++){
368  if(subscribers[i] == 0){ // empty slot
369  subscribers[i] = (Subscriber_*) &srv;
370  srv.id_ = i+100;
371  return v;
372  }
373  }
374  return false;
375  }
376 
377  /* Register a new Service Client */
378  template<typename MReq, typename MRes>
380  bool v = advertise(srv.pub);
381  for(int i = 0; i < MAX_SUBSCRIBERS; i++){
382  if(subscribers[i] == 0){ // empty slot
383  subscribers[i] = (Subscriber_*) &srv;
384  srv.id_ = i+100;
385  return v;
386  }
387  }
388  return false;
389  }
390 
392  {
394  int i;
395  for(i = 0; i < MAX_PUBLISHERS; i++)
396  {
397  if(publishers[i] != 0) // non-empty slot
398  {
399  ti.topic_id = publishers[i]->id_;
400  ti.topic_name = (char *) publishers[i]->topic_;
401  ti.message_type = (char *) publishers[i]->msg_->getType();
402  ti.md5sum = (char *) publishers[i]->msg_->getMD5();
403  ti.buffer_size = OUTPUT_SIZE;
404  publish( publishers[i]->getEndpointType(), &ti );
405  }
406  }
407  for(i = 0; i < MAX_SUBSCRIBERS; i++)
408  {
409  if(subscribers[i] != 0) // non-empty slot
410  {
411  ti.topic_id = subscribers[i]->id_;
412  ti.topic_name = (char *) subscribers[i]->topic_;
413  ti.message_type = (char *) subscribers[i]->getMsgType();
414  ti.md5sum = (char *) subscribers[i]->getMsgMD5();
415  ti.buffer_size = INPUT_SIZE;
416  publish( subscribers[i]->getEndpointType(), &ti );
417  }
418  }
419  configured_ = true;
420  }
421 
422  virtual int publish(int id, const Msg * msg)
423  {
424  if(id >= 100 && !configured_)
425  return 0;
426 
427  /* serialize message */
428  uint16_t l = msg->serialize(message_out+7);
429 
430  /* setup the header */
431  message_out[0] = 0xff;
433  message_out[2] = (uint8_t) ((uint16_t)l&255);
434  message_out[3] = (uint8_t) ((uint16_t)l>>8);
435  message_out[4] = 255 - ((message_out[2] + message_out[3])%256);
436  message_out[5] = (uint8_t) ((int16_t)id&255);
437  message_out[6] = (uint8_t) ((int16_t)id>>8);
438 
439  /* calculate checksum */
440  int chk = 0;
441  for(int i =5; i<l+7; i++)
442  chk += message_out[i];
443  l += 7;
444  message_out[l++] = 255 - (chk%256);
445 
446  if( l <= OUTPUT_SIZE ){
447  hardware_.write(message_out, l);
448  return l;
449  }else{
450  logerror("Message from device dropped: message larger than buffer.");
451  return -1;
452  }
453  }
454 
455  /********************************************************************
456  * Logging
457  */
458 
459  private:
460  void log(char byte, const char * msg){
462  l.level= byte;
463  l.msg = (char*)msg;
465  }
466 
467  public:
468  void logdebug(const char* msg){
470  }
471  void loginfo(const char * msg){
473  }
474  void logwarn(const char *msg){
476  }
477  void logerror(const char*msg){
479  }
480  void logfatal(const char*msg){
482  }
483 
484  /********************************************************************
485  * Parameters
486  */
487 
488  private:
491 
492  bool requestParam(const char * name, int time_out = 1000){
493  param_recieved = false;
495  req.name = (char*)name;
497  uint16_t end_time = hardware_.time() + time_out;
498  while(!param_recieved ){
499  spinOnce();
500  if (hardware_.time() > end_time) return false;
501  }
502  return true;
503  }
504 
505  public:
506  bool getParam(const char* name, int* param, int length =1){
507  if (requestParam(name) ){
508  if (length == req_param_resp.ints_length){
509  //copy it over
510  for(int i=0; i<length; i++)
511  param[i] = req_param_resp.ints[i];
512  return true;
513  }
514  }
515  return false;
516  }
517  bool getParam(const char* name, float* param, int length=1){
518  if (requestParam(name) ){
519  if (length == req_param_resp.floats_length){
520  //copy it over
521  for(int i=0; i<length; i++)
522  param[i] = req_param_resp.floats[i];
523  return true;
524  }
525  }
526  return false;
527  }
528  bool getParam(const char* name, char** param, int length=1){
529  if (requestParam(name) ){
530  if (length == req_param_resp.strings_length){
531  //copy it over
532  for(int i=0; i<length; i++)
533  strcpy(param[i],req_param_resp.strings[i]);
534  return true;
535  }
536  }
537  return false;
538  }
539  };
540 
541 }
542 
543 #endif
int id_
Definition: publisher.h:58
uint8_t message_out[OUTPUT_SIZE]
Definition: node_handle.h:110
Definition: subscriber.h:60
void logdebug(const char *msg)
Definition: node_handle.h:468
void logwarn(const char *msg)
Definition: node_handle.h:474
bool configured_
Definition: node_handle.h:171
void initNode()
Definition: node_handle.h:146
uint32_t nsec
Definition: time.h:50
#define MODE_PROTOCOL_VER
Definition: node_handle.h:56
uint32_t sec
Definition: time.h:50
Definition: time.h:47
Definition: TopicInfo.h:12
Definition: subscriber.h:43
const char * topic_name
Definition: TopicInfo.h:16
int mode_
Definition: node_handle.h:161
Definition: TopicInfo.h:25
ros::Time data
Definition: Time.h:16
void syncTime(uint8_t *data)
Definition: node_handle.h:301
void log(char byte, const char *msg)
Definition: node_handle.h:460
bool param_recieved
Definition: node_handle.h:489
const char * md5sum
Definition: TopicInfo.h:18
Time now()
Definition: node_handle.h:314
Definition: node_handle.h:98
Definition: node_handle.h:75
virtual bool connected()=0
bool subscribe(Subscriber< MsgT > &s)
Definition: node_handle.h:352
void logerror(const char *msg)
Definition: node_handle.h:477
Definition: Log.h:20
Publisher pub
Definition: service_server.h:69
uint32_t last_msg_timeout_time
Definition: node_handle.h:176
Definition: Log.h:21
uint32_t last_sync_time
Definition: node_handle.h:174
uint32_t rt_time
Definition: node_handle.h:104
void logfatal(const char *msg)
Definition: node_handle.h:480
void negotiateTopics()
Definition: node_handle.h:391
virtual void callback(unsigned char *data)=0
virtual int publish(int id, const Msg *msg)
Definition: node_handle.h:422
virtual int deserialize(unsigned char *inbuffer)
Definition: Time.h:39
Definition: Log.h:12
Definition: TopicInfo.h:20
uint32_t nsec_offset
Definition: node_handle.h:107
Definition: Log.h:18
NodeHandleBase_ * nh_
Definition: publisher.h:59
#define MODE_SIZE_CHECKSUM
Definition: node_handle.h:62
uint8_t level
Definition: Log.h:15
void loginfo(const char *msg)
Definition: node_handle.h:471
#define SYNC_SECONDS
Definition: node_handle.h:45
int32_t buffer_size
Definition: TopicInfo.h:19
Definition: Log.h:17
uint8_t strings_length
Definition: RequestParam.h:63
Publisher * publishers[MAX_PUBLISHERS]
Definition: node_handle.h:112
NodeHandle_()
Definition: node_handle.h:119
char ** strings
Definition: RequestParam.h:65
#define MODE_TOPIC_H
Definition: node_handle.h:64
Definition: Time.h:13
virtual int spinOnce()=0
virtual int deserialize(unsigned char *inbuffer)
Definition: RequestParam.h:123
bool requestParam(const char *name, int time_out=1000)
Definition: node_handle.h:492
uint32_t last_sync_receive_time
Definition: node_handle.h:175
uint8_t message_in[INPUT_SIZE]
Definition: node_handle.h:109
Definition: TopicInfo.h:27
#define MODE_MESSAGE
Definition: node_handle.h:65
void setNow(Time &new_now)
Definition: node_handle.h:324
int32_t * ints
Definition: RequestParam.h:59
int id_
Definition: subscriber.h:50
virtual int publish(int id, const Msg *msg)=0
void normalizeSecNSec(uint32_t &sec, uint32_t &nsec)
Definition: time.cpp:39
Hardware hardware_
Definition: node_handle.h:101
Publisher pub
Definition: service_client.h:78
#define MODE_SIZE_H
Definition: node_handle.h:61
int topic_
Definition: node_handle.h:167
virtual bool connected()
Definition: node_handle.h:286
bool getParam(const char *name, int *param, int length=1)
Definition: node_handle.h:506
#define MODE_MSG_CHECKSUM
Definition: node_handle.h:66
Definition: publisher.h:44
int bytes_
Definition: node_handle.h:166
const char * message_type
Definition: TopicInfo.h:17
bool getParam(const char *name, float *param, int length=1)
Definition: node_handle.h:517
bool getParam(const char *name, char **param, int length=1)
Definition: node_handle.h:528
float * floats
Definition: RequestParam.h:62
#define MSG_TIMEOUT
Definition: node_handle.h:69
int index_
Definition: node_handle.h:168
bool advertise(Publisher &p)
Definition: node_handle.h:337
void initNode(char *portName)
Definition: node_handle.h:155
int checksum_
Definition: node_handle.h:169
Definition: RequestParam.h:13
Definition: service_server.h:46
#define MODE_FIRST_FF
Definition: node_handle.h:47
Hardware * getHardware()
Definition: node_handle.h:141
const char * name
Definition: RequestParam.h:16
virtual int serialize(unsigned char *outbuffer) const =0
Subscriber_ * subscribers[MAX_SUBSCRIBERS]
Definition: node_handle.h:113
uint8_t floats_length
Definition: RequestParam.h:60
void requestSyncTime()
Definition: node_handle.h:294
Definition: service_client.h:46
#define PROTOCOL_VER
Definition: node_handle.h:59
rosserial_msgs::RequestParamResponse req_param_resp
Definition: node_handle.h:490
#define MODE_TOPIC_L
Definition: node_handle.h:63
Definition: Log.h:19
bool advertiseService(ServiceServer< MReq, MRes > &srv)
Definition: node_handle.h:365
Definition: RequestParam.h:54
uint8_t ints_length
Definition: RequestParam.h:57
uint32_t sec_offset
Definition: node_handle.h:107
Definition: msg.h:43
bool serviceClient(ServiceClient< MReq, MRes > &srv)
Definition: node_handle.h:379
Definition: TopicInfo.h:26
#define MODE_SIZE_L
Definition: node_handle.h:60
uint16_t topic_id
Definition: TopicInfo.h:15
virtual int spinOnce()
Definition: node_handle.h:184
const char * msg
Definition: Log.h:16