|
|
|
@ -36,12 +36,15 @@
@@ -36,12 +36,15 @@
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include "sensor_bridge.hpp" |
|
|
|
|
#include <systemlib/err.h> |
|
|
|
|
#include <cassert> |
|
|
|
|
|
|
|
|
|
#include "gnss.hpp" |
|
|
|
|
#include "mag.hpp" |
|
|
|
|
#include "baro.hpp" |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* IUavcanSensorBridge |
|
|
|
|
*/ |
|
|
|
|
IUavcanSensorBridge* IUavcanSensorBridge::make(uavcan::INode &node, const char *bridge_name) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
@ -64,3 +67,91 @@ void IUavcanSensorBridge::print_known_names(const char *prefix)
@@ -64,3 +67,91 @@ void IUavcanSensorBridge::print_known_names(const char *prefix)
|
|
|
|
|
printf("%s%s\n", prefix, UavcanMagnetometerBridge::NAME); |
|
|
|
|
printf("%s%s\n", prefix, UavcanBarometerBridge::NAME); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* UavcanCDevSensorBridgeBase |
|
|
|
|
*/ |
|
|
|
|
UavcanCDevSensorBridgeBase::~UavcanCDevSensorBridgeBase() |
|
|
|
|
{ |
|
|
|
|
for (unsigned i = 0; i < _max_channels; i++) { |
|
|
|
|
if (_channels[i].redunancy_channel_id >= 0) { |
|
|
|
|
(void)unregister_class_devname(_class_devname, _channels[i].class_instance); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
delete [] _orb_topics; |
|
|
|
|
delete [] _channels; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void UavcanCDevSensorBridgeBase::publish(const int redundancy_channel_id, const void *report) |
|
|
|
|
{ |
|
|
|
|
Channel *channel = nullptr; |
|
|
|
|
|
|
|
|
|
// Checking if such channel already exists
|
|
|
|
|
for (unsigned i = 0; i < _max_channels; i++) { |
|
|
|
|
if (_channels[i].redunancy_channel_id == redundancy_channel_id) { |
|
|
|
|
channel = _channels + i; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// No such channel - try to create one
|
|
|
|
|
if (channel == nullptr) { |
|
|
|
|
if (_out_of_channels) { |
|
|
|
|
return; // Give up immediately - saves some CPU time
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
log("adding channel %d...", redundancy_channel_id); |
|
|
|
|
|
|
|
|
|
// Search for the first free channel
|
|
|
|
|
for (unsigned i = 0; i < _max_channels; i++) { |
|
|
|
|
if (_channels[i].redunancy_channel_id < 0) { |
|
|
|
|
channel = _channels + i; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// No free channels left
|
|
|
|
|
if (channel == nullptr) { |
|
|
|
|
_out_of_channels = true; |
|
|
|
|
log("out of channels"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Ask the CDev helper which class instance we can take
|
|
|
|
|
const int class_instance = register_class_devname(_class_devname); |
|
|
|
|
if (class_instance < 0 || class_instance >= int(_max_channels)) { |
|
|
|
|
_out_of_channels = true; |
|
|
|
|
log("out of class instances"); |
|
|
|
|
(void)unregister_class_devname(_class_devname, class_instance); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Publish to the appropriate topic, abort on failure
|
|
|
|
|
channel->orb_id = _orb_topics[class_instance]; |
|
|
|
|
channel->redunancy_channel_id = redundancy_channel_id; |
|
|
|
|
channel->class_instance = class_instance; |
|
|
|
|
|
|
|
|
|
channel->orb_advert = orb_advertise(channel->orb_id, report); |
|
|
|
|
if (channel->orb_advert < 0) { |
|
|
|
|
log("ADVERTISE FAILED"); |
|
|
|
|
*channel = Channel(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
log("channel %d class instance %d ok", channel->redunancy_channel_id, channel->class_instance); |
|
|
|
|
} |
|
|
|
|
assert(channel != nullptr); |
|
|
|
|
|
|
|
|
|
(void)orb_publish(channel->orb_id, channel->orb_advert, report); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
unsigned UavcanCDevSensorBridgeBase::get_num_redundant_channels() const |
|
|
|
|
{ |
|
|
|
|
unsigned out = 0; |
|
|
|
|
for (unsigned i = 0; i < _max_channels; i++) { |
|
|
|
|
if (_channels[i].redunancy_channel_id >= 0) { |
|
|
|
|
out += 1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return out; |
|
|
|
|
} |
|
|
|
|