libuavcan documentation

This commit is contained in:
Pavel Kirienko
2014-07-14 22:22:18 +04:00
parent ee4c191684
commit e5ca1f7379
47 changed files with 1102 additions and 132 deletions
@@ -12,7 +12,11 @@
namespace uavcan
{
/**
* This class implements the standard services for data type introspection.
* Once started it does not require any attention from the application.
* The user does not need to deal with it directly - it's started by the node class.
*/
class UAVCAN_EXPORT DataTypeInfoProvider : Noncopyable
{
typedef MethodBinder<DataTypeInfoProvider*,
@@ -13,7 +13,15 @@
namespace uavcan
{
/**
* Please read the specs to learn how the time synchronization works.
*
* No more than one object of this class is allowed per node; otherwise a disaster is bound to happen.
*
* NOTE: In order for this class to work, the platform driver must implement
* CAN bus TX loopback with both UTC and monotonic timestamping.
*
* Ref. M. Gergeleit, H. Streich - "Implementing a Distributed High-Resolution Real-Time Clock using the CAN-Bus"
*
* TODO: Enforce max one master per node
*/
class UAVCAN_EXPORT GlobalTimeSyncMaster : protected LoopbackFrameListenerBase
@@ -57,10 +65,29 @@ public:
, initialized_(false)
{ }
/**
* Merely prepares the class to work, doesn't do anything else.
* Must be called before the master can be used.
* Returns negative error code.
*/
int init();
/**
* Whether the master instance has been initialized.
*/
bool isInitialized() const { return initialized_; }
/**
* Publishes one sync message.
*
* Every call to this method hints the master to publish the next sync message once. Exact time will
* be obtained from the TX loopback timestamp field.
*
* This method shall be called with a proper interval - refer to the time sync message definition
* for min/max interval values.
*
* Returns negative error code.
*/
int publish();
};
@@ -11,6 +11,14 @@
namespace uavcan
{
/**
* Please read the specs to learn how the time synchronization works.
*
* No more than one object of this class is allowed per node; otherwise a disaster is bound to happen.
*
* NOTE: In order for this class to work, the platform driver must implement:
* - CAN bus RX UTC timestamping;
* - Clock adjustment method in the system clock interface @ref ISystemClock::adjustUtc().
*
* Ref. M. Gergeleit, H. Streich - "Implementing a Distributed High-Resolution Real-Time Clock using the CAN-Bus"
* http://modecs.cs.uni-salzburg.at/results/related_documents/CAN_clock.pdf
*/
@@ -50,15 +58,47 @@ public:
, suppressed_(false)
{ }
/**
* Starts the time sync slave. Once started, it works on its own and does not require any
* attention from the application, other than to handle a clock adjustment request occasionally.
* Returns negative error code.
*/
int start();
/**
* Enable or disable the suppressed mode.
*
* In suppressed mode the slave will continue tracking time sync masters in the network, but will not
* perform local clock adjustments. So it's kind of a dry run - all the time sync logic works except
* the local clock will not receive adjustments.
*
* Suppressed mode is useful for nodes that can act as a back-up clock sync masters - as long as the
* node sees a higher priority time sync master in the network, its slave will be NOT suppressed
* in order to sync the local clock with the global master. As soon as all other higher priority
* masters go down, the local node will suppress its time sync slave instance and become a new master.
*
* Suppressed mode is disabled by default.
*/
void suppress(bool suppressed) { suppressed_ = suppressed; }
bool isSuppressed() const { return suppressed_; }
/**
* If the clock sync slave sees any clock sync masters in the network, it is ACTIVE.
* When the last master times out (PUBLISHER_TIMEOUT), the slave will be INACTIVE.
* Note that immediately after start up the slave will be INACTIVE until it finds a master.
* Please read the specs to learn more.
*/
bool isActive() const;
/**
* Node ID of the master the slave is currently locked on.
* Returns an invalid Node ID if there's no active master.
*/
NodeID getMasterNodeID() const;
/**
* Last time when the local clock adjustment was performed.
*/
MonotonicTime getLastAdjustmentTime() const { return last_adjustment_ts_; }
};
+77 -4
View File
@@ -15,7 +15,12 @@
namespace uavcan
{
/**
* External log sink interface.
* External log sink allows the application to install a hook on the logger output.
* This can be used for application-wide logging.
* Please refer to the @ref Logger class docs.
*/
class UAVCAN_EXPORT ILogSink
{
public:
@@ -24,22 +29,38 @@ public:
virtual ~ILogSink() { }
/**
* Logger will not sink messages with level lower than returned by this method.
* Logger will not sink messages with a severity level lower than returned by this method.
* Default level is DEBUG.
*/
virtual LogLevel getLogLevel() const { return protocol::debug::LogLevel::DEBUG; }
/**
* Logger will call this method for every log message with level not less than the current level of this sink.
* Logger will call this method for every log message which severity level
* is not less than the current level of this sink.
*/
virtual void log(const protocol::debug::LogMessage& message) = 0;
};
/**
* Node logging convenience class.
*
* This class is based on the standard UAVCAN message type for logging - uavcan.protocol.debug.LogMessage.
*
* Provides logging methods of different severity; implements two sinks for the log messages:
* - Broadcast via the UAVCAN bus;
* - Sink into the application via @ref ILogSink.
*
* For each sink an individual severity threshold filter can be configured.
*/
class UAVCAN_EXPORT Logger
{
public:
typedef ILogSink::LogLevel LogLevel;
/**
* This value is higher than any valid severity value.
* Use it to completely suppress the output.
*/
static const LogLevel LevelAboveAll = (1 << protocol::debug::LogLevel::FieldTypes::value::BitLen) - 1;
private:
@@ -62,19 +83,68 @@ public:
UAVCAN_ASSERT(getTxTimeout() == MonotonicDuration::fromMSec(DefaultTxTimeoutMs));
}
/**
* Initializes the logger, does not perform any network activity.
* Must be called once before use.
* Returns negative error code.
*/
int init();
/**
* Logs one message. Please consider using helper methods instead of this one.
*
* The message will be broadcasted via the UAVCAN bus if the severity level of the
* message is >= severity level of the logger.
*
* The message will be reported into the external log sink if the external sink is
* installed and the severity level of the message is >= severity level of the external sink.
*
* Returns negative error code.
*/
int log(const protocol::debug::LogMessage& message);
/**
* Severity filter for UAVCAN broadcasting.
* Log message will be broadcasted via the UAVCAN network only if its severity is >= getLevel().
* This does not affect the external sink.
* Default level is ERROR.
*/
LogLevel getLevel() const { return level_; }
void setLevel(LogLevel level) { level_ = level; }
/**
* External log sink allows the application to install a hook on the logger output.
* This can be used for application-wide logging.
* Null pointer means that there's no log sink (can be used to remove it).
* By default there's no log sink.
*/
ILogSink* getExternalSink() const { return external_sink_; }
void setExternalSink(ILogSink* sink) { external_sink_ = sink; }
/**
* Log message broadcast transmission timeout.
* The default value should be acceptable for any use case.
*/
MonotonicDuration getTxTimeout() const { return logmsg_pub_.getTxTimeout(); }
void setTxTimeout(MonotonicDuration val) { logmsg_pub_.setTxTimeout(val); }
/**
* Helper methods for various severity levels and with formatting support.
* These methods build a formatted log message and pass it into the method @ref log().
*
* Format string usage is a bit unusual: use "%*" for any argument type, use "%%" to print a percent character.
* No other formating options are supported. Insufficient/extra arguments are ignored.
*
* Example format string:
* "What do you get if you %* %* by %*? %*. Extra arguments: %* %* %%"
* ...with the following arguments:
* "multiply", 6, 9.0F 4.2e1
* ...will likely produce this (floating point representation is platform dependent):
* "What do you get if you multiply 6 by 9.000000? 42.000000. Extra arguments: %* %* %"
*
* Formatting is not supported in C++03 mode.
* @{
*/
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
template <typename... Args>
@@ -129,6 +199,9 @@ public:
}
#endif
/**
* @}
*/
};
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
@@ -16,19 +16,25 @@ namespace uavcan
struct UAVCAN_EXPORT NetworkCompatibilityCheckResult
{
NodeID conflicting_node;
uint8_t num_failed_nodes;
NodeID conflicting_node; ///< First detected conflicting node
uint8_t num_failed_nodes; ///< Number of nodes that did not respond to service requests (probably not supporting)
NetworkCompatibilityCheckResult()
: num_failed_nodes(0)
{ }
/**
* Quick check if the network compatibility check did not discover any problems.
*/
bool isOk() const { return !conflicting_node.isValid(); }
};
/**
* Performs Network Compatibility Check. Please read the specs.
*
* This class does not issue GlobalDiscoveryRequest, assuming that it was done already by the caller.
* Instantiated object can execute() only once. Objects of this class are intended for stack allocation.
* Instantiated object can @ref execute() only once.
* Objects of this class are intended for stack allocation.
*/
class UAVCAN_EXPORT NetworkCompatibilityChecker : Noncopyable
{
@@ -72,10 +78,28 @@ public:
, last_cats_request_ok_(false)
{ }
/**
* Run the check.
* Beware: this method may block for a several seconds!
*
* If this method has been executed successfully, use @ref getResult() to get the actual check result.
*
* This method can be executed only once on a given instance of this class (shall be
* destroyed and reconstructed from scratch).
*
* Returns negative error code.
*/
int execute();
/**
* This method can return a meaningful result only if @ref execute() has been executed successfully once.
*/
const NetworkCompatibilityCheckResult& getResult() const { return result_; }
/**
* Convenience method. Should be called immediately before @ref execute().
* Returns negative error code.
*/
static int publishGlobalDiscoveryRequest(INode& node);
};
@@ -11,7 +11,10 @@
namespace uavcan
{
/**
* This class implements the core functionality of a network monitor.
* It can be extended by inheritance to add more complex logic, or used directly as is.
*/
class UAVCAN_EXPORT NodeStatusMonitor : protected TimerBase
{
public:
@@ -67,6 +70,8 @@ private:
protected:
/**
* Called when a node becomes online, changes status or goes offline.
* Refer to uavcan.protocol.NodeStatus for the offline timeout value.
* Overriding is not required.
*/
virtual void handleNodeStatusChange(const NodeStatusChangeEvent& event)
{
@@ -74,7 +79,9 @@ protected:
}
/**
* Called for every received message uavcan.protocol.NodeStatus after handleNodeStatusChange().
* Called for every received message uavcan.protocol.NodeStatus after handleNodeStatusChange(), even
* if the status code did not change.
* Overriding is not required.
*/
virtual void handleNodeStatusMessage(const ReceivedDataStructure<protocol::NodeStatus>& msg)
{
@@ -89,12 +96,28 @@ public:
virtual ~NodeStatusMonitor() { }
/**
* Starts the monitor.
* Destroy the object to stop it.
* Returns negative error code.
*/
int start();
/**
* Make the node unknown.
*/
void forgetNode(NodeID node_id);
/**
* Returns status of a given node.
* Unknown nodes are considered offline.
*/
NodeStatus getNodeStatus(NodeID node_id) const;
/**
* This helper method allows to quickly estimate the overall network health.
* Status of the local node is not considered.
*/
NodeID findNodeWithWorstStatus() const;
};
@@ -16,7 +16,10 @@
namespace uavcan
{
/**
* Provides the status and basic information about this node to other network participants.
* Usually the application does not need to deal with this class directly - it's instantiated by the node class.
*/
class UAVCAN_EXPORT NodeStatusProvider : private TimerBase
{
typedef MethodBinder<NodeStatusProvider*, void (NodeStatusProvider::*)(const protocol::GlobalDiscoveryRequest&)>
@@ -64,10 +67,21 @@ public:
node_status_pub_.setTxTimeout(MonotonicDuration::fromMSec(protocol::NodeStatus::PUBLICATION_PERIOD_MS - 10));
}
/**
* Starts the provider and immediately broadcasts uavcan.protocol.NodeStatus.
* Returns negative error code.
*/
int startAndPublish();
/**
* Publish the message uavcan.protocol.NodeStatus right now, out of schedule.
* Returns negative error code.
*/
int forcePublish() { return publish(); }
/**
* Local node status code control.
*/
uint8_t getStatusCode() const { return node_info_.status.status_code; }
void setStatusCode(uint8_t code);
void setStatusOk() { setStatusCode(protocol::NodeStatus::STATUS_OK); }
@@ -76,9 +90,18 @@ public:
void setStatusCritical() { setStatusCode(protocol::NodeStatus::STATUS_CRITICAL); }
void setStatusOffline() { setStatusCode(protocol::NodeStatus::STATUS_OFFLINE); }
/**
* Local node name control.
* Can be set only once before the provider is started.
* The provider will refuse to start if the node name is not set.
*/
const typename protocol::GetNodeInfo::Response::FieldTypes::name& getName() const { return node_info_.name; }
void setName(const char* name);
/**
* Node version information.
* Can be set only once before the provider is started.
*/
const protocol::SoftwareVersion& getSoftwareVersion() const { return node_info_.software_version; }
const protocol::HardwareVersion& getHardwareVersion() const { return node_info_.hardware_version; }
void setSoftwareVersion(const protocol::SoftwareVersion& version);
@@ -10,7 +10,9 @@
namespace uavcan
{
/**
* Helper for broadcasting the message uavcan.protocol.Panic.
*/
class UAVCAN_EXPORT PanicBroadcaster : private TimerBase
{
Publisher<protocol::Panic> pub_;
@@ -28,8 +30,15 @@ public:
pub_.setTxTimeout(MonotonicDuration::fromMSec(protocol::Panic::BROADCASTING_INTERVAL_MS - 10));
}
/**
* Begin broadcasting at the standard interval.
* This method does not block and can't fail.
*/
void panic(const char* short_reason);
/**
* Stop broadcasting immediately.
*/
void dontPanic(); // Where's my towel
bool isPanicking() const;
@@ -22,11 +22,13 @@
namespace uavcan
{
/**
* Callback prototype:
* void (const ReceivedDataStructure<protocol::Panic>&)
* Or:
* void (const protocol::Panic&)
* This class implements proper panic detector.
* Refer to uavcan.protocol.Panic for details.
* The listener can be stopped from the callback.
*
* @tparam Callback Possible callback prototypes:
* void (const ReceivedDataStructure<protocol::Panic>&)
* void (const protocol::Panic&)
*/
template <
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
@@ -95,6 +97,11 @@ public:
, num_subsequent_msgs_(0)
{ }
/**
* Start the listener.
* Once started it does not require further attention.
* Returns negative error code.
*/
int start(const Callback& callback)
{
stop();
@@ -11,7 +11,10 @@
namespace uavcan
{
/**
* Implement this interface in the application to support the standard remote reconfiguration services.
* Refer to @ref ParamServer.
*/
class UAVCAN_EXPORT IParamManager
{
public:
@@ -62,7 +65,10 @@ public:
virtual int eraseAllParams() = 0;
};
/**
* Convenience class for supporting the standard configuration services.
* Highly recommended to use.
*/
class UAVCAN_EXPORT ParamServer
{
typedef MethodBinder<ParamServer*, void (ParamServer::*)(const protocol::param::GetSet::Request&,
@@ -89,6 +95,10 @@ public:
, manager_(NULL)
{ }
/**
* Starts the parameter server with given param manager instance.
* Returns negative error code.
*/
int start(IParamManager* manager);
IParamManager* getParamManager() const { return manager_; }
@@ -10,15 +10,29 @@
namespace uavcan
{
/**
* Implement this interface in the application to support the standard node restart service.
*/
class UAVCAN_EXPORT IRestartRequestHandler
{
public:
virtual ~IRestartRequestHandler() { }
/**
* This method shall do either:
* - restart the local node immediately;
* - initiate the restart procedure to complete it asynchronously;
* - reject the restart request and return false.
*
* If the restart requets was accepted, this method shall either return true or don't return at all.
*/
virtual bool handleRestartRequest(NodeID request_source) = 0;
};
/**
* Convenience class for supporting the standard node restart service.
* Highly recommended to use.
*/
class UAVCAN_EXPORT RestartRequestServer : Noncopyable
{
typedef MethodBinder<const RestartRequestServer*,
@@ -37,9 +51,17 @@ public:
, handler_(NULL)
{ }
/**
* Restart request handler configuration.
* All restart requests will be explicitly rejected if there's no handler installed.
*/
IRestartRequestHandler* getHandler() const { return handler_; }
void setHandler(IRestartRequestHandler* handler) { handler_ = handler; }
/**
* Starts the server.
* Returns negative error code.
*/
int start();
};
@@ -10,7 +10,10 @@
namespace uavcan
{
/**
* This class provides statistics about the transport layer performance on the local node.
* The user's application does not deal with this class directly because it's instantiated by the node class.
*/
class UAVCAN_EXPORT TransportStatsProvider : Noncopyable
{
typedef MethodBinder<const TransportStatsProvider*,
@@ -28,6 +31,10 @@ public:
: srv_(node)
{ }
/**
* Once started, this class requires no further attention.
* Returns negative error code.
*/
int start();
};