PX4 Firmware
PX4 Autopilot Software http://px4.io
uORBManager.hpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2015 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * 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
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 #ifndef _uORBManager_hpp_
35 #define _uORBManager_hpp_
36 
37 #include "uORBCommon.hpp"
38 #include "uORBDeviceMaster.hpp"
39 
40 #include <stdint.h>
41 
42 #ifdef __PX4_NUTTX
43 #include "ORBSet.hpp"
44 #else
45 #include <string>
46 #include <set>
47 #define ORBSet std::set<std::string>
48 #endif
49 
50 #ifdef ORB_COMMUNICATOR
51 #include "uORBCommunicator.hpp"
52 #endif /* ORB_COMMUNICATOR */
53 
54 namespace uORB
55 {
56 class Manager;
57 }
58 
59 /**
60  * This is implemented as a singleton. This class manages creating the
61  * uORB nodes for each uORB topics and also implements the behavor of the
62  * uORB Api's.
63  */
65 #ifdef ORB_COMMUNICATOR
67 #endif /* ORB_COMMUNICATOR */
68 {
69 public:
70  // public interfaces for this class.
71 
72  /**
73  * Initialize the singleton. Call this before everything else.
74  * @return true on success
75  */
76  static bool initialize();
77 
78  /**
79  * Terminate the singleton. Call this after everything else.
80  * @return true on success
81  */
82  static bool terminate();
83 
84  /**
85  * Method to get the singleton instance for the uORB::Manager.
86  * Make sure initialize() is called first.
87  * @return uORB::Manager*
88  */
89  static uORB::Manager *get_instance() { return _Instance; }
90 
91  /**
92  * Get the DeviceMaster. If it does not exist,
93  * it will be created and initialized.
94  * Note: the first call to this is not thread-safe.
95  * @return nullptr if initialization failed (and errno will be set)
96  */
98 
99  // ==== uORB interface methods ====
100  /**
101  * Advertise as the publisher of a topic.
102  *
103  * This performs the initial advertisement of a topic; it creates the topic
104  * node in /obj if required and publishes the initial data.
105  *
106  * Any number of advertisers may publish to a topic; publications are atomic
107  * but co-ordination between publishers is not provided by the ORB.
108  *
109  * Internally this will call orb_advertise_multi with an instance of 0 and
110  * default priority.
111  *
112  * @param meta The uORB metadata (usually from the ORB_ID() macro)
113  * for the topic.
114  * @param data A pointer to the initial data to be published.
115  * For topics updated by interrupt handlers, the advertisement
116  * must be performed from non-interrupt context.
117  * @param queue_size Maximum number of buffered elements. If this is 1, no queuing is
118  * used.
119  * @return nullptr on error, otherwise returns an object pointer
120  * that can be used to publish to the topic.
121  * If the topic in question is not known (due to an
122  * ORB_DEFINE with no corresponding ORB_DECLARE)
123  * this function will return nullptr and set errno to ENOENT.
124  */
125  orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data, unsigned int queue_size = 1)
126  {
127  return orb_advertise_multi(meta, data, nullptr, ORB_PRIO_DEFAULT, queue_size);
128  }
129 
130  /**
131  * Advertise as the publisher of a topic.
132  *
133  * This performs the initial advertisement of a topic; it creates the topic
134  * node in /obj if required and publishes the initial data.
135  *
136  * Any number of advertisers may publish to a topic; publications are atomic
137  * but co-ordination between publishers is not provided by the ORB.
138  *
139  * The multi can be used to create multiple independent instances of the same topic
140  * (each instance has its own buffer).
141  * This is useful for multiple publishers who publish the same topic. The subscriber
142  * then subscribes to all instances and chooses which source he wants to use.
143  *
144  * @param meta The uORB metadata (usually from the ORB_ID() macro)
145  * for the topic.
146  * @param data A pointer to the initial data to be published.
147  * For topics updated by interrupt handlers, the advertisement
148  * must be performed from non-interrupt context.
149  * @param instance Pointer to an integer which will yield the instance ID (0-based)
150  * of the publication. This is an output parameter and will be set to the newly
151  * created instance, ie. 0 for the first advertiser, 1 for the next and so on.
152  * @param priority The priority of the instance. If a subscriber subscribes multiple
153  * instances, the priority allows the subscriber to prioritize the best
154  * data source as long as its available. The subscriber is responsible to check
155  * and handle different priorities (@see orb_priority()).
156  * @param queue_size Maximum number of buffered elements. If this is 1, no queuing is
157  * used.
158  * @return PX4_ERROR on error, otherwise returns a handle
159  * that can be used to publish to the topic.
160  * If the topic in question is not known (due to an
161  * ORB_DEFINE with no corresponding ORB_DECLARE)
162  * this function will return -1 and set errno to ENOENT.
163  */
164  orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance,
165  int priority, unsigned int queue_size = 1);
166 
167  /**
168  * Unadvertise a topic.
169  *
170  * @param handle handle returned by orb_advertise or orb_advertise_multi.
171  * @return 0 on success
172  */
173  int orb_unadvertise(orb_advert_t handle);
174 
175  /**
176  * Publish new data to a topic.
177  *
178  * The data is atomically published to the topic and any waiting subscribers
179  * will be notified. Subscribers that are not waiting can check the topic
180  * for updates using orb_check and/or orb_stat.
181  *
182  * @param meta The uORB metadata (usually from the ORB_ID() macro)
183  * for the topic.
184  * @handle The handle returned from orb_advertise.
185  * @param data A pointer to the data to be published.
186  * @return OK on success, PX4_ERROR otherwise with errno set accordingly.
187  */
188  int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data);
189 
190  /**
191  * Subscribe to a topic.
192  *
193  * The returned value is a file descriptor that can be passed to poll()
194  * in order to wait for updates to a topic, as well as topic_read,
195  * orb_check and orb_stat.
196  *
197  * If there were any publications of the topic prior to the subscription,
198  * an orb_check right after orb_subscribe will return true.
199  *
200  * Subscription will succeed even if the topic has not been advertised;
201  * in this case the topic will have a timestamp of zero, it will never
202  * signal a poll() event, checking will always return false and it cannot
203  * be copied. When the topic is subsequently advertised, poll, check,
204  * stat and copy calls will react to the initial publication that is
205  * performed as part of the advertisement.
206  *
207  * Subscription will fail if the topic is not known to the system, i.e.
208  * there is nothing in the system that has declared the topic and thus it
209  * can never be published.
210  *
211  * Internally this will call orb_subscribe_multi with instance 0.
212  *
213  * @param meta The uORB metadata (usually from the ORB_ID() macro)
214  * for the topic.
215  * @return PX4_ERROR on error, otherwise returns a handle
216  * that can be used to read and update the topic.
217  */
218  int orb_subscribe(const struct orb_metadata *meta);
219 
220  /**
221  * Subscribe to a multi-instance of a topic.
222  *
223  * The returned value is a file descriptor that can be passed to poll()
224  * in order to wait for updates to a topic, as well as topic_read,
225  * orb_check and orb_stat.
226  *
227  * If there were any publications of the topic prior to the subscription,
228  * an orb_check right after orb_subscribe_multi will return true.
229  *
230  * Subscription will succeed even if the topic has not been advertised;
231  * in this case the topic will have a timestamp of zero, it will never
232  * signal a poll() event, checking will always return false and it cannot
233  * be copied. When the topic is subsequently advertised, poll, check,
234  * stat and copy calls will react to the initial publication that is
235  * performed as part of the advertisement.
236  *
237  * Subscription will fail if the topic is not known to the system, i.e.
238  * there is nothing in the system that has declared the topic and thus it
239  * can never be published.
240  *
241  * If a publisher publishes multiple instances the subscriber should
242  * subscribe to each instance with orb_subscribe_multi
243  * (@see orb_advertise_multi()).
244  *
245  * @param meta The uORB metadata (usually from the ORB_ID() macro)
246  * for the topic.
247  * @param instance The instance of the topic. Instance 0 matches the
248  * topic of the orb_subscribe() call, higher indices
249  * are for topics created with orb_advertise_multi().
250  * @return PX4_ERROR on error, otherwise returns a handle
251  * that can be used to read and update the topic.
252  * If the topic in question is not known (due to an
253  * ORB_DEFINE_OPTIONAL with no corresponding ORB_DECLARE)
254  * this function will return -1 and set errno to ENOENT.
255  */
256  int orb_subscribe_multi(const struct orb_metadata *meta, unsigned instance);
257 
258  /**
259  * Unsubscribe from a topic.
260  *
261  * @param handle A handle returned from orb_subscribe.
262  * @return OK on success, PX4_ERROR otherwise with errno set accordingly.
263  */
264  int orb_unsubscribe(int handle);
265 
266  /**
267  * Fetch data from a topic.
268  *
269  * This is the only operation that will reset the internal marker that
270  * indicates that a topic has been updated for a subscriber. Once poll
271  * or check return indicating that an updaet is available, this call
272  * must be used to update the subscription.
273  *
274  * @param meta The uORB metadata (usually from the ORB_ID() macro)
275  * for the topic.
276  * @param handle A handle returned from orb_subscribe.
277  * @param buffer Pointer to the buffer receiving the data, or NULL
278  * if the caller wants to clear the updated flag without
279  * using the data.
280  * @return OK on success, PX4_ERROR otherwise with errno set accordingly.
281  */
282  int orb_copy(const struct orb_metadata *meta, int handle, void *buffer);
283 
284  /**
285  * Check whether a topic has been published to since the last orb_copy.
286  *
287  * This check can be used to determine whether to copy the topic when
288  * not using poll(), or to avoid the overhead of calling poll() when the
289  * topic is likely to have updated.
290  *
291  * Updates are tracked on a per-handle basis; this call will continue to
292  * return true until orb_copy is called using the same handle. This interface
293  * should be preferred over calling orb_stat due to the race window between
294  * stat and copy that can lead to missed updates.
295  *
296  * @param handle A handle returned from orb_subscribe.
297  * @param updated Set to true if the topic has been updated since the
298  * last time it was copied using this handle.
299  * @return OK if the check was successful, PX4_ERROR otherwise with
300  * errno set accordingly.
301  */
302  int orb_check(int handle, bool *updated);
303 
304  /**
305  * Return the last time that the topic was updated. If a queue is used, it returns
306  * the timestamp of the latest element in the queue.
307  *
308  * @param handle A handle returned from orb_subscribe.
309  * @param time Returns the absolute time that the topic was updated, or zero if it has
310  * never been updated. Time is measured in microseconds.
311  * @return OK on success, PX4_ERROR otherwise with errno set accordingly.
312  */
313  int orb_stat(int handle, uint64_t *time);
314 
315  /**
316  * Check if a topic has already been created and published (advertised)
317  *
318  * @param meta ORB topic metadata.
319  * @param instance ORB instance
320  * @return OK if the topic exists, PX4_ERROR otherwise.
321  */
322  int orb_exists(const struct orb_metadata *meta, int instance);
323 
324  /**
325  * Return the priority of the topic
326  *
327  * @param handle A handle returned from orb_subscribe.
328  * @param priority Returns the priority of this topic. This is only relevant for
329  * topics which are published by multiple publishers (e.g. mag0, mag1, etc.)
330  * and allows a subscriber to pick the topic with the highest priority,
331  * independent of the startup order of the associated publishers.
332  * @return OK on success, PX4_ERROR otherwise with errno set accordingly.
333  */
334  int orb_priority(int handle, int32_t *priority);
335 
336  /**
337  * Set the minimum interval between which updates are seen for a subscription.
338  *
339  * If this interval is set, the subscriber will not see more than one update
340  * within the period.
341  *
342  * Specifically, the first time an update is reported to the subscriber a timer
343  * is started. The update will continue to be reported via poll and orb_check, but
344  * once fetched via orb_copy another update will not be reported until the timer
345  * expires.
346  *
347  * This feature can be used to pace a subscriber that is watching a topic that
348  * would otherwise update too quickly.
349  *
350  * @param handle A handle returned from orb_subscribe.
351  * @param interval An interval period in milliseconds.
352  * @return OK on success, PX4_ERROR otherwise with ERRNO set accordingly.
353  */
354  int orb_set_interval(int handle, unsigned interval);
355 
356 
357  /**
358  * Get the minimum interval between which updates are seen for a subscription.
359  *
360  * @see orb_set_interval()
361  *
362  * @param handle A handle returned from orb_subscribe.
363  * @param interval The returned interval period in milliseconds.
364  * @return OK on success, PX4_ERROR otherwise with ERRNO set accordingly.
365  */
366  int orb_get_interval(int handle, unsigned *interval);
367 
368 #ifdef ORB_COMMUNICATOR
369  /**
370  * Method to set the uORBCommunicator::IChannel instance.
371  * @param comm_channel
372  * The IChannel instance to talk to remote proxies.
373  * @note:
374  * Currently this call only supports the use of one IChannel
375  * Future extensions may include more than one IChannel's.
376  */
377  void set_uorb_communicator(uORBCommunicator::IChannel *comm_channel);
378 
379  /**
380  * Gets the uORB Communicator instance.
381  */
382  uORBCommunicator::IChannel *get_uorb_communicator();
383 
384  /**
385  * Utility method to check if there is a remote subscriber present
386  * for a given topic
387  */
388  bool is_remote_subscriber_present(const char *messageName);
389 #endif /* ORB_COMMUNICATOR */
390 
391 private: // class methods
392  /**
393  * Advertise a node; don't consider it an error if the node has
394  * already been advertised.
395  */
396  int node_advertise(const struct orb_metadata *meta, bool is_advertiser, int *instance = nullptr,
397  int priority = ORB_PRIO_DEFAULT);
398 
399  /**
400  * Common implementation for orb_advertise and orb_subscribe.
401  *
402  * Handles creation of the object and the initial publication for
403  * advertisers.
404  */
405  int node_open(const struct orb_metadata *meta, bool advertiser, int *instance = nullptr,
406  int priority = ORB_PRIO_DEFAULT);
407 
408 private: // data members
410 
411 #ifdef ORB_COMMUNICATOR
412  // the communicator channel instance.
413  uORBCommunicator::IChannel *_comm_channel{nullptr};
414 
415  ORBSet _remote_subscriber_topics;
416  ORBSet _remote_topics;
417 #endif /* ORB_COMMUNICATOR */
418 
420 
421 private: //class methods
422  Manager();
423  virtual ~Manager();
424 
425 #ifdef ORB_COMMUNICATOR
426  /**
427  * Interface to process a received topic from remote.
428  * @param topic_name
429  * This represents the uORB message Name (topic); This message Name should be
430  * globally unique.
431  * @param isAdvertisement
432  * Represents if the topic has been advertised or is no longer avialable.
433  * @return
434  * 0 = success; This means the messages is successfully handled in the
435  * handler.
436  * otherwise = failure.
437  */
438  virtual int16_t process_remote_topic(const char *topic_name, bool isAdvertisement);
439 
440  /**
441  * Interface to process a received AddSubscription from remote.
442  * @param messageName
443  * This represents the uORB message Name; This message Name should be
444  * globally unique.
445  * @param msgRate
446  * The max rate at which the subscriber can accept the messages.
447  * @return
448  * 0 = success; This means the messages is successfully handled in the
449  * handler.
450  * otherwise = failure.
451  */
452  virtual int16_t process_add_subscription(const char *messageName, int32_t msgRateInHz);
453 
454  /**
455  * Interface to process a received control msg to remove subscription
456  * @param messageName
457  * This represents the uORB message Name; This message Name should be
458  * globally unique.
459  * @return
460  * 0 = success; This means the messages is successfully handled in the
461  * handler.
462  * otherwise = failure.
463  */
464  virtual int16_t process_remove_subscription(const char *messageName);
465 
466  /**
467  * Interface to process the received data message.
468  * @param messageName
469  * This represents the uORB message Name; This message Name should be
470  * globally unique.
471  * @param length
472  * The length of the data buffer to be sent.
473  * @param data
474  * The actual data to be sent.
475  * @return
476  * 0 = success; This means the messages is successfully handled in the
477  * handler.
478  * otherwise = failure.
479  */
480  virtual int16_t process_received_message(const char *messageName, int32_t length, uint8_t *data);
481 #endif /* ORB_COMMUNICATOR */
482 
483 #ifdef ORB_USE_PUBLISHER_RULES
484 
485  struct PublisherRule {
486  const char **topics; //null-terminated list of topic names
487  const char *module_name; //only this module is allowed to publish one of the topics
488  bool ignore_other_topics;
489  };
490 
491  /**
492  * test if str starts with pre
493  */
494  bool startsWith(const char *pre, const char *str);
495 
496  /**
497  * find a topic in a rule
498  */
499  bool findTopic(const PublisherRule &rule, const char *topic_name);
500 
501  /**
502  * trim whitespace from the beginning of a string
503  */
504  void strTrim(const char **str);
505 
506  /**
507  * Read publisher rules from a file. It has the format:
508  *
509  * restrict_topics: <topic1>, <topic2>, <topic3>
510  * module: <module_name>
511  * [ignore_others:true]
512  *
513  * @return 0 on success, <0 otherwise
514  */
515  int readPublisherRulesFromFile(const char *file_name, PublisherRule &rule);
516 
517  PublisherRule _publisher_rule;
518  bool _has_publisher_rules = false;
519 
520 #endif /* ORB_USE_PUBLISHER_RULES */
521 
522 };
523 
524 #endif /* _uORBManager_hpp_ */
int node_advertise(const struct orb_metadata *meta, bool is_advertiser, int *instance=nullptr, int priority=ORB_PRIO_DEFAULT)
Advertise a node; don&#39;t consider it an error if the node has already been advertised.
DeviceMaster * _device_master
static uORB::Manager * get_instance()
Method to get the singleton instance for the uORB::Manager.
Definition: uORBManager.hpp:89
virtual ~Manager()
Definition: uORBManager.cpp:87
int orb_set_interval(int handle, unsigned interval)
Set the minimum interval between which updates are seen for a subscription.
uORB::DeviceMaster * get_device_master()
Get the DeviceMaster.
Definition: uORBManager.cpp:92
static bool initialize()
Initialize the singleton.
Definition: uORBManager.cpp:49
int orb_unsubscribe(int handle)
Unsubscribe from a topic.
LidarLite * instance
Definition: ll40ls.cpp:65
static bool terminate()
Terminate the singleton.
Definition: uORBManager.cpp:58
int orb_subscribe(const struct orb_metadata *meta)
Subscribe to a topic.
int node_open(const struct orb_metadata *meta, bool advertiser, int *instance=nullptr, int priority=ORB_PRIO_DEFAULT)
Common implementation for orb_advertise and orb_subscribe.
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority, unsigned int queue_size=1)
Advertise as the publisher of a topic.
int orb_unadvertise(orb_advert_t handle)
Unadvertise a topic.
uint8_t * data
Definition: dataman.cpp:149
int orb_priority(int handle, int32_t *priority)
Return the priority of the topic.
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Publish new data to a topic.
Class passed to the communication link implement to provide callback for received messages over a cha...
int orb_subscribe_multi(const struct orb_metadata *meta, unsigned instance)
Subscribe to a multi-instance of a topic.
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
Fetch data from a topic.
static Manager * _Instance
int orb_exists(const struct orb_metadata *meta, int instance)
Check if a topic has already been created and published (advertised)
Object metadata.
Definition: uORB.h:50
Interface to enable remote subscriptions.
orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data, unsigned int queue_size=1)
Advertise as the publisher of a topic.
int orb_get_interval(int handle, unsigned *interval)
Get the minimum interval between which updates are seen for a subscription.
Master control device for ObjDev.
int orb_check(int handle, bool *updated)
Check whether a topic has been published to since the last orb_copy.
int orb_stat(int handle, uint64_t *time)
Return the last time that the topic was updated.
This is implemented as a singleton.
Definition: uORBManager.hpp:64