PX4 Firmware
PX4 Autopilot Software http://px4.io
sensor_bridge.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2014 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 /**
35  * @author Pavel Kirienko <pavel.kirienko@gmail.com>
36  */
37 
38 #include "sensor_bridge.hpp"
39 #include <cassert>
40 
41 #include "gnss.hpp"
42 #include "mag.hpp"
43 #include "baro.hpp"
44 #include "flow.hpp"
45 #include "battery.hpp"
46 
47 /*
48  * IUavcanSensorBridge
49  */
51 {
52  list.add(new UavcanBarometerBridge(node));
53  list.add(new UavcanMagnetometerBridge(node));
54  list.add(new UavcanGnssBridge(node));
55  list.add(new UavcanFlowBridge(node));
56  list.add(new UavcanBatteryBridge(node));
57 }
58 
59 /*
60  * UavcanCDevSensorBridgeBase
61  */
63 {
64  for (unsigned i = 0; i < _max_channels; i++) {
65  if (_channels[i].node_id >= 0) {
66  (void)unregister_class_devname(_class_devname, _channels[i].class_instance);
67  }
68  }
69 
70  delete [] _channels;
71 }
72 
73 void
74 UavcanCDevSensorBridgeBase::publish(const int node_id, const void *report)
75 {
76  Channel *channel = nullptr;
77 
78  // Checking if such channel already exists
79  for (unsigned i = 0; i < _max_channels; i++) {
80  if (_channels[i].node_id == node_id) {
81  channel = _channels + i;
82  break;
83  }
84  }
85 
86  // No such channel - try to create one
87  if (channel == nullptr) {
88  if (_out_of_channels) {
89  return; // Give up immediately - saves some CPU time
90  }
91 
92  DEVICE_LOG("adding channel %d...", node_id);
93 
94  // Search for the first free channel
95  for (unsigned i = 0; i < _max_channels; i++) {
96  if (_channels[i].node_id < 0) {
97  channel = _channels + i;
98  break;
99  }
100  }
101 
102  // No free channels left
103  if (channel == nullptr) {
104  _out_of_channels = true;
105  DEVICE_LOG("out of channels");
106  return;
107  }
108 
109  // update device id as we now know our device node_id
110  _device_id.devid_s.address = static_cast<uint8_t>(node_id);
111 
112  // Ask the CDev helper which class instance we can take
113  const int class_instance = register_class_devname(_class_devname);
114 
115  if (class_instance < 0 || class_instance >= int(_max_channels)) {
116  _out_of_channels = true;
117  DEVICE_LOG("out of class instances");
118  (void)unregister_class_devname(_class_devname, class_instance);
119  return;
120  }
121 
122  // Publish to the appropriate topic, abort on failure
123  channel->node_id = node_id;
124  channel->class_instance = class_instance;
125 
126  channel->orb_advert = orb_advertise_multi(_orb_topic, report, &channel->orb_instance, ORB_PRIO_VERY_HIGH);
127 
128  if (channel->orb_advert == nullptr) {
129  DEVICE_LOG("ADVERTISE FAILED");
130  (void)unregister_class_devname(_class_devname, class_instance);
131  *channel = Channel();
132  return;
133  }
134 
135  DEVICE_LOG("channel %d class instance %d ok", channel->node_id, channel->class_instance);
136  }
137 
138  assert(channel != nullptr);
139 
140  (void)orb_publish(_orb_topic, channel->orb_advert, report);
141 }
142 
143 unsigned
145 {
146  unsigned out = 0;
147 
148  for (unsigned i = 0; i < _max_channels; i++) {
149  if (_channels[i].node_id >= 0) {
150  out += 1;
151  }
152  }
153 
154  return out;
155 }
156 
157 void
159 {
160  printf("devname: %s\n", _class_devname);
161 
162  for (unsigned i = 0; i < _max_channels; i++) {
163  if (_channels[i].node_id >= 0) {
164  printf("channel %d: node id %d --> class instance %d\n",
165  i, _channels[i].node_id, _channels[i].class_instance);
166 
167  } else {
168  printf("channel %d: empty\n", i);
169  }
170  }
171 }
static void make_all(uavcan::INode &node, List< IUavcanSensorBridge *> &list)
Sensor bridge factory.
device identifier information
Definition: Device.hpp:240
Definition: List.hpp:59
#define DEVICE_LOG(FMT,...)
Definition: Device.hpp:51
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
UAVCAN <–> ORB bridge for GNSS messages: uavcan.equipment.gnss.Fix (deprecated, but still supported ...
void print_status() const override
Prints current status in a human readable format to stdout.
unsigned get_num_redundant_channels() const override
Returns number of active redundancy channels.
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
Definition: uORB.cpp:53
void publish(const int node_id, const void *report)
Sends one measurement into appropriate ORB topic.