mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-19 06:43:34 +08:00
libuavcan documentation
This commit is contained in:
@@ -10,7 +10,11 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* This is the abstract node class. If you're going to implement your own node class for your application,
|
||||
* please inherit this class so it can be used with default publisher, subscriber, server, etc. classes.
|
||||
* Normally you don't need to use directly though - please refer to the class Node<>.
|
||||
*/
|
||||
class UAVCAN_EXPORT INode
|
||||
{
|
||||
public:
|
||||
@@ -28,19 +32,44 @@ public:
|
||||
MonotonicTime getMonotonicTime() const { return getScheduler().getMonotonicTime(); }
|
||||
UtcTime getUtcTime() const { return getScheduler().getUtcTime(); }
|
||||
|
||||
/**
|
||||
* Returns the Node ID of this node.
|
||||
* If Node ID was not set yet, an invalid value will be returned.
|
||||
*/
|
||||
NodeID getNodeID() const { return getScheduler().getDispatcher().getNodeID(); }
|
||||
|
||||
/**
|
||||
* Sets the Node ID of this node.
|
||||
* Node ID can be assigned only once. This method returns true if the Node ID was successfully assigned, otherwise
|
||||
* it returns false (e.g. the argument does not represent a valid Node ID, or it was already assigned earlier).
|
||||
* As long as a valid Node ID is not set, the node will remain in passive mode.
|
||||
*/
|
||||
bool setNodeID(NodeID nid)
|
||||
{
|
||||
return getScheduler().getDispatcher().setNodeID(nid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the node is in passive mode, i.e. can't transmit anything to the bus.
|
||||
* Please read the specs to learn more.
|
||||
*/
|
||||
bool isPassiveMode() const { return getScheduler().getDispatcher().isPassiveMode(); }
|
||||
|
||||
/**
|
||||
* Same as @ref spin(MonotonicDuration), but the deadline is specified as an absolute time value
|
||||
* rather than duration.
|
||||
*/
|
||||
int spin(MonotonicTime deadline)
|
||||
{
|
||||
return getScheduler().spin(deadline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the node.
|
||||
* Normally your application should not block anywhere else.
|
||||
* Block inside this method forever or call it periodically.
|
||||
* This method returns 0 if no errors occurred, or a negative error code if something failed (see error.hpp).
|
||||
*/
|
||||
int spin(MonotonicDuration duration)
|
||||
{
|
||||
return getScheduler().spin(getMonotonicTime() + duration);
|
||||
|
||||
@@ -84,6 +84,9 @@ class UAVCAN_EXPORT GenericPublisher : public GenericPublisherBase
|
||||
TransferID* tid, MonotonicTime blocking_deadline);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param max_transfer_interval Maximum expected time interval between subsequent publications. Leave default.
|
||||
*/
|
||||
GenericPublisher(INode& node, MonotonicDuration tx_timeout,
|
||||
MonotonicDuration max_transfer_interval = TransferSender::getDefaultMaxTransferInterval())
|
||||
: GenericPublisherBase(node, tx_timeout, max_transfer_interval)
|
||||
@@ -91,6 +94,10 @@ public:
|
||||
|
||||
~GenericPublisher() { }
|
||||
|
||||
/**
|
||||
* Init method can be called prior first publication, but it's not necessary
|
||||
* because the publisher can be automatically initialized ad-hoc.
|
||||
*/
|
||||
int init()
|
||||
{
|
||||
return checkInit();
|
||||
|
||||
@@ -17,7 +17,18 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* This class extends the data structure with extra information obtained from the transport layer,
|
||||
* such as Source Node ID, timestamps, Transfer ID, index of the interface this transfer was picked up from, etc.
|
||||
*
|
||||
* PLEASE NOTE that since this class inherits the data structure type, subscription callbacks can accept either
|
||||
* object of this class or the data structure type directly if the extra information is not needed.
|
||||
*
|
||||
* For example, both of these callbacks can be used with the same data structure 'Foo':
|
||||
* void first(const ReceivedDataStructure<Foo>& msg);
|
||||
* void second(const Foo& msg);
|
||||
* In the latter case, an implicit cast will happen before the callback is invoked.
|
||||
*/
|
||||
template <typename DataType_>
|
||||
class UAVCAN_EXPORT ReceivedDataStructure : public DataType_
|
||||
{
|
||||
@@ -57,6 +68,10 @@ public:
|
||||
uint8_t getIfaceIndex() const { return safeget<uint8_t, &IncomingTransfer::getIfaceIndex>(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* This operator neatly prints the data structure prepended with extra data from the transport layer.
|
||||
* The extra data will be represented as YAML comment.
|
||||
*/
|
||||
template <typename Stream, typename DataType>
|
||||
static Stream& operator<<(Stream& s, const ReceivedDataStructure<DataType>& rds)
|
||||
{
|
||||
@@ -86,12 +101,19 @@ protected:
|
||||
void stop(TransferListenerBase* listener);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the number of failed attempts to decode received message. Generally, a failed attempt means either:
|
||||
* - Transient failure in the transport layer.
|
||||
* - Incompatible data types.
|
||||
*/
|
||||
uint32_t getFailureCount() const { return failure_count_; }
|
||||
|
||||
INode& getNode() const { return node_; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This helper class does some compile-time magic on the transport layer machinery. For authorized personnel only.
|
||||
*/
|
||||
template <typename DataStruct_, unsigned NumStaticReceivers_, unsigned NumStaticBufs_>
|
||||
class UAVCAN_EXPORT TransferListenerInstantiationHelper
|
||||
{
|
||||
@@ -173,6 +195,10 @@ protected:
|
||||
return genericStart(&Dispatcher::registerServiceResponseListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate the subscription.
|
||||
* Dispatcher core will remove this instance from the subscribers list.
|
||||
*/
|
||||
void stop()
|
||||
{
|
||||
GenericSubscriberBase::stop(forwarder_);
|
||||
@@ -180,6 +206,10 @@ protected:
|
||||
|
||||
TransferListenerType* getTransferListener() { return forwarder_; }
|
||||
|
||||
/**
|
||||
* Returns the mutable reference to the temporary storage for decoded received messages.
|
||||
* Reference to this storage is used as a parameter for subscription callbacks.
|
||||
*/
|
||||
ReceivedDataStructure<DataStruct>& getReceivedStructStorage() { return message_; }
|
||||
};
|
||||
|
||||
|
||||
@@ -17,9 +17,26 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Bit mask where bit at index X is set if there's a Data Type with ID X.
|
||||
*/
|
||||
typedef BitSet<DataTypeID::Max + 1> DataTypeIDMask;
|
||||
|
||||
/**
|
||||
* This singleton is shared among all existing node instances. It is instantiated automatically
|
||||
* when the C++ runtime executes contstructors before main().
|
||||
*
|
||||
* Its purpose is to keep the list of all UAVCAN data types known and used by this application.
|
||||
*
|
||||
* Also, the mapping between Data Type name and its Data Type ID is also stored in this singleton.
|
||||
* UAVCAN data types with default Data Type ID that are autogenerated by the libuavcan DSDL compiler
|
||||
* are registered automatically before main() (refer to the generated headers to see how exactly).
|
||||
* Data types that don't have a default Data Type ID must be registered manually using the methods
|
||||
* of this class (read the method documentation).
|
||||
*
|
||||
* Attempt to use a data type that was not registered with this singleton (e.g. publish, subscribe,
|
||||
* perform a service call etc.) will fail with an error code @ref ErrUnknownDataType.
|
||||
*/
|
||||
class UAVCAN_EXPORT GlobalDataTypeRegistry : Noncopyable
|
||||
{
|
||||
struct Entry : public LinkedListNode<Entry>
|
||||
@@ -49,12 +66,15 @@ class UAVCAN_EXPORT GlobalDataTypeRegistry : Noncopyable
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Result of data type registration
|
||||
*/
|
||||
enum RegistResult
|
||||
{
|
||||
RegistResultOk,
|
||||
RegistResultCollision,
|
||||
RegistResultInvalidParams,
|
||||
RegistResultFrozen
|
||||
RegistResultOk, ///< Success, data type is now registered and can be used.
|
||||
RegistResultCollision, ///< Data type name or ID is not unique.
|
||||
RegistResultInvalidParams, ///< Invalid input parameters.
|
||||
RegistResultFrozen ///< Data Type Registery has been frozen and can't be modified anymore.
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -71,24 +91,85 @@ private:
|
||||
RegistResult registImpl(Entry* dtd);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns the reference to the singleton.
|
||||
*/
|
||||
static GlobalDataTypeRegistry& instance();
|
||||
|
||||
/// Last call wins
|
||||
/**
|
||||
* Register a data type 'Type' with ID 'id'.
|
||||
* If this data type was registered earlier, its old registration will be overridden.
|
||||
* This method will fail if the data type registry is frozen.
|
||||
*
|
||||
* @tparam Type Autogenerated UAVCAN data type to register. Data types are generated by the
|
||||
* libuavcan DSDL compiler from DSDL definitions.
|
||||
*
|
||||
* @param id Data Type ID for this data type.
|
||||
*/
|
||||
template <typename Type>
|
||||
RegistResult regist(DataTypeID id);
|
||||
|
||||
/// Further calls to regist<>() will fail
|
||||
/**
|
||||
* Data Type registry needs to be frozen before a node instance can use it in
|
||||
* order to prevent accidental change in data type configuration on a running
|
||||
* node.
|
||||
*
|
||||
* This method will be called automatically by the node during start up, so
|
||||
* the user does not need to call it from the application manually. Subsequent
|
||||
* calls will not have any effect.
|
||||
*
|
||||
* Once frozen, data type registry can't be unfrozen.
|
||||
*/
|
||||
void freeze();
|
||||
bool isFrozen() const { return frozen_; }
|
||||
|
||||
/**
|
||||
* Finds data type descriptor by full data type name, e.g. "uavcan.protocol.NodeStatus".
|
||||
* Returns null pointer if the data type with this name is not registered.
|
||||
* @param kind Data Type Kind - message or service
|
||||
* @param name Full data type name
|
||||
* @return Descriptor for this data type or null pointer if not found
|
||||
*/
|
||||
const DataTypeDescriptor* find(DataTypeKind kind, const char* name) const;
|
||||
|
||||
/**
|
||||
* Finds data type descriptor by data type ID.
|
||||
* Returns null pointer if the data type with this ID is not registered.
|
||||
* @param kind Data Type Kind - message or service
|
||||
* @param dtid Data Type ID
|
||||
* @return Descriptor for this data type or null pointer if not found
|
||||
*/
|
||||
const DataTypeDescriptor* find(DataTypeKind kind, DataTypeID dtid) const;
|
||||
|
||||
/**
|
||||
* Computes Aggregate Signature for all known data types selected by the mask.
|
||||
* Please read the DSDL specification.
|
||||
* @param[in] kind Data Type Kind - messages or services.
|
||||
* @param[inout] inout_id_mask Data types to compute aggregate signature for; bits at
|
||||
* the positions of unknown data types will be cleared.
|
||||
* @return Computed data type signature.
|
||||
*/
|
||||
DataTypeSignature computeAggregateSignature(DataTypeKind kind, DataTypeIDMask& inout_id_mask) const;
|
||||
|
||||
/**
|
||||
* Sets the mask so that only bits corresponding to known data types will be set.
|
||||
* In other words:
|
||||
* for data_type_id := [0, 1023]
|
||||
* mask[data_type_id] := data_type_exists(data_type_id)
|
||||
*
|
||||
* @param[in] kind Data Type Kind - messages or services.
|
||||
* @param[out] mask Output mask of known data types.
|
||||
*/
|
||||
void getDataTypeIDMask(DataTypeKind kind, DataTypeIDMask& mask) const;
|
||||
|
||||
/**
|
||||
* Returns the number of registered message types.
|
||||
*/
|
||||
unsigned getNumMessageTypes() const { return msgs_.getLength(); }
|
||||
|
||||
/**
|
||||
* Returns the number of registered service types.
|
||||
*/
|
||||
unsigned getNumServiceTypes() const { return srvs_.getLength(); }
|
||||
|
||||
#if UAVCAN_DEBUG
|
||||
@@ -110,7 +191,14 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This class is used by autogenerated data types to register with the
|
||||
* data type registry automatically before main() is called. Note that
|
||||
* if a generated data type header file is not included by any translation
|
||||
* unit of the application, the data type will not be registered.
|
||||
*
|
||||
* Data type needs to have a default ID to be registrable by this class.
|
||||
*/
|
||||
template <typename Type>
|
||||
struct UAVCAN_EXPORT DefaultDataTypeRegistrator
|
||||
{
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Abstract temporary buffer for data marshalling.
|
||||
*/
|
||||
class UAVCAN_EXPORT IMarshalBuffer : public ITransferBuffer
|
||||
{
|
||||
public:
|
||||
@@ -18,15 +20,31 @@ public:
|
||||
virtual unsigned getDataLength() const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Abstract provider of abstract buffer for data marshalling.
|
||||
*/
|
||||
class UAVCAN_EXPORT IMarshalBufferProvider
|
||||
{
|
||||
public:
|
||||
virtual ~IMarshalBufferProvider() { }
|
||||
|
||||
/**
|
||||
* Returns pointer to abstract buffer for data marshalling,
|
||||
* but does not transfer ownership.
|
||||
* If the requested buffer size is larger than available,
|
||||
* null pointer will be returned.
|
||||
* @param size Maximum buffer size needed for marshaling.
|
||||
* @return Pointer to the buffer, or null pointer if
|
||||
* the requested size is too large.
|
||||
*/
|
||||
virtual IMarshalBuffer* getBuffer(unsigned size) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of marshal buffer provider.
|
||||
* This implementation provides the buffer large enough to
|
||||
* serialize any UAVCAN data structure.
|
||||
*/
|
||||
template <unsigned MaxSize_ = MaxTransferPayloadLen>
|
||||
class UAVCAN_EXPORT MarshalBufferProvider : public IMarshalBufferProvider
|
||||
{
|
||||
|
||||
@@ -28,7 +28,31 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* This is the top-level node API.
|
||||
* A custom node class can be implemented if needed, in which case it shall inherit INode.
|
||||
*
|
||||
* @tparam MemPoolSize_ Size of memory pool for this node, in bytes.
|
||||
* Minimum recommended size is 4K * (number of CAN ifaces + 1).
|
||||
* For simple nodes this number can be reduced.
|
||||
* For high-traffic nodes the recommended minimum is
|
||||
* like 16K * (number of CAN ifaces + 1).
|
||||
*
|
||||
* @tparam OutgoingTransferRegistryStaticEntries Number of statically allocated objects
|
||||
* to track Transfer ID for outgoing transfers.
|
||||
* Normally it should be equal to expected number of
|
||||
* publishers and service callers, but it's not necessary.
|
||||
* Additional objects for Transfer ID tracking will
|
||||
* be allocated in the memory pool if needed.
|
||||
* Default value is acceptable for any use case.
|
||||
*
|
||||
* @tparam OutgoingTransferMaxPayloadLen Maximum outgoing transfer payload length.
|
||||
* It's pointless to make this value larger than
|
||||
* @ref MaxTransferPayloadLen, which is default.
|
||||
* Note that in tiny mode the default value is actually
|
||||
* smaller than @ref MaxTransferPayloadLen (may cause
|
||||
* run-time failures).
|
||||
*/
|
||||
template <std::size_t MemPoolSize_,
|
||||
#if UAVCAN_TINY
|
||||
unsigned OutgoingTransferRegistryStaticEntries = 0,
|
||||
@@ -114,42 +138,68 @@ public:
|
||||
|
||||
bool isStarted() const { return started_; }
|
||||
|
||||
/**
|
||||
* Starts the node and publishes uavcan.protocol.NodeStatus immediately.
|
||||
* Does not so anything if the node is already started.
|
||||
* Once started, the node can't stop.
|
||||
* If the node failed to start up, it's recommended to destroy the current node instance and start over.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int start();
|
||||
|
||||
#if !UAVCAN_TINY
|
||||
/**
|
||||
* Please read the specs to learn about Network Compatibility Check.
|
||||
* Returns negative error code.
|
||||
* @param[out] result Check result (output).
|
||||
*/
|
||||
int checkNetworkCompatibility(NetworkCompatibilityCheckResult& result);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialization methods
|
||||
/**
|
||||
* Sets the node name, e.g. "com.example.product_name". The node name can be set only once.
|
||||
* Must be executed before the node is started, otherwise the node will refuse to start up.
|
||||
*/
|
||||
void setName(const char* name) { proto_nsp_.setName(name); }
|
||||
|
||||
/**
|
||||
* Status code helpers.
|
||||
*/
|
||||
void setStatusOk() { proto_nsp_.setStatusOk(); }
|
||||
void setStatusInitializing() { proto_nsp_.setStatusInitializing(); }
|
||||
void setStatusWarning() { proto_nsp_.setStatusWarning(); }
|
||||
void setStatusCritical() { proto_nsp_.setStatusCritical(); }
|
||||
|
||||
/**
|
||||
* Sets the status OFFLINE and publishes it immediately.
|
||||
*/
|
||||
void setStatusOffline()
|
||||
{
|
||||
proto_nsp_.setStatusOffline();
|
||||
(void)proto_nsp_.forcePublish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node version information.
|
||||
*/
|
||||
void setSoftwareVersion(const protocol::SoftwareVersion& version) { proto_nsp_.setSoftwareVersion(version); }
|
||||
void setHardwareVersion(const protocol::HardwareVersion& version) { proto_nsp_.setHardwareVersion(version); }
|
||||
|
||||
NodeStatusProvider& getNodeStatusProvider() { return proto_nsp_; }
|
||||
|
||||
#if !UAVCAN_TINY
|
||||
/*
|
||||
* Restart handler
|
||||
/**
|
||||
* Restart handler can be installed to handle external node restart requests (highly recommended).
|
||||
*/
|
||||
void setRestartRequestHandler(IRestartRequestHandler* handler) { proto_rrs_.setHandler(handler); }
|
||||
|
||||
RestartRequestServer& getRestartRequestServer() { return proto_rrs_; }
|
||||
|
||||
/*
|
||||
* Logging
|
||||
/**
|
||||
* Node logging.
|
||||
* Logging calls are passed directly into the @ref Logger instance.
|
||||
* Type safe log formatting is supported only in C++11 mode.
|
||||
* @{
|
||||
*/
|
||||
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
|
||||
|
||||
@@ -185,7 +235,13 @@ public:
|
||||
void logError(const char* source, const char* text) { (void)proto_logger_.logError(source, text); }
|
||||
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Use this method to configure logging.
|
||||
*/
|
||||
Logger& getLogger() { return proto_logger_; }
|
||||
|
||||
#endif // UAVCAN_TINY
|
||||
|
||||
@@ -8,15 +8,32 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Use this class to publish messages to the bus (broadcast, unicast, or both).
|
||||
*
|
||||
* @tparam DataType_ Message data type
|
||||
*/
|
||||
template <typename DataType_>
|
||||
class UAVCAN_EXPORT Publisher : protected GenericPublisher<DataType_, DataType_>
|
||||
{
|
||||
typedef GenericPublisher<DataType_, DataType_> BaseType;
|
||||
|
||||
public:
|
||||
typedef DataType_ DataType;
|
||||
typedef DataType_ DataType; ///< Message data type
|
||||
|
||||
/**
|
||||
* @param node Node instance this publisher will be registered with.
|
||||
*
|
||||
* @param tx_timeout If CAN frames of this message are not delivered to the bus
|
||||
* in this amount of time, they will be discarded. Default value
|
||||
* is good enough for rather high-frequency, high-priority messages.
|
||||
*
|
||||
* @param max_transfer_interval Maximum expected transfer interval. It's absolutely safe
|
||||
* to leave default value here. It just defines how soon the
|
||||
* Transfer ID tracking objects associated with this message type
|
||||
* will be garbage collected by the library if it's no longer
|
||||
* being published.
|
||||
*/
|
||||
explicit Publisher(INode& node, MonotonicDuration tx_timeout = getDefaultTxTimeout(),
|
||||
MonotonicDuration max_transfer_interval = TransferSender::getDefaultMaxTransferInterval())
|
||||
: BaseType(node, tx_timeout, max_transfer_interval)
|
||||
@@ -27,16 +44,30 @@ public:
|
||||
StaticAssert<DataTypeKind(DataType::DataTypeKind) == DataTypeKindMessage>::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast the message.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int broadcast(const DataType& message)
|
||||
{
|
||||
return BaseType::publish(message, TransferTypeMessageBroadcast, NodeID::Broadcast);
|
||||
}
|
||||
|
||||
/**
|
||||
* Warning: You probably don't want to use this method; it's for advanced use cases like
|
||||
* e.g. network time synchronization. Use the overloaded method with fewer arguments instead.
|
||||
* This overload allows to explicitly specify Transfer ID.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int broadcast(const DataType& message, TransferID tid)
|
||||
{
|
||||
return BaseType::publish(message, TransferTypeMessageBroadcast, NodeID::Broadcast, tid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unicast the message to the specified destination Node ID.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int unicast(const DataType& message, NodeID dst_node_id)
|
||||
{
|
||||
if (!dst_node_id.isUnicast())
|
||||
@@ -49,7 +80,12 @@ public:
|
||||
|
||||
static MonotonicDuration getDefaultTxTimeout() { return MonotonicDuration::fromMSec(10); }
|
||||
|
||||
/**
|
||||
* Init method can be called prior first publication, but it's not necessary
|
||||
* because the publisher can be automatically initialized ad-hoc.
|
||||
*/
|
||||
using BaseType::init;
|
||||
|
||||
using BaseType::getTransferSender;
|
||||
using BaseType::getMinTxTimeout;
|
||||
using BaseType::getMaxTxTimeout;
|
||||
|
||||
@@ -55,7 +55,9 @@ public:
|
||||
MonotonicTime getEarliestDeadline() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This class distributes processing time between library components (IO handling, deadline callbacks, ...).
|
||||
*/
|
||||
class UAVCAN_EXPORT Scheduler : Noncopyable
|
||||
{
|
||||
enum { DefaultDeadlineResolutionMs = 5 };
|
||||
@@ -85,6 +87,10 @@ public:
|
||||
, inside_spin_(false)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Spin until the deadline, or until some error occurs.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int spin(MonotonicTime deadline);
|
||||
|
||||
DeadlineScheduler& getDeadlineScheduler() { return deadline_scheduler_; }
|
||||
@@ -96,6 +102,10 @@ public:
|
||||
MonotonicTime getMonotonicTime() const { return dispatcher_.getSystemClock().getMonotonic(); }
|
||||
UtcTime getUtcTime() const { return dispatcher_.getSystemClock().getUtc(); }
|
||||
|
||||
/**
|
||||
* Worst case deadline callback resolution.
|
||||
* Higher resolution increases CPU usage.
|
||||
*/
|
||||
MonotonicDuration getDeadlineResolution() const { return deadline_resolution_; }
|
||||
void setDeadlineResolution(MonotonicDuration res)
|
||||
{
|
||||
@@ -104,6 +114,12 @@ public:
|
||||
deadline_resolution_ = res;
|
||||
}
|
||||
|
||||
/**
|
||||
* How often the scheduler will run cleanup (listeners, outgoing transfer registry, ...).
|
||||
* Cleanup execution time grows linearly with number of listeners and number of items
|
||||
* in the Outgoing Transfer ID registry.
|
||||
* Lower period increases CPU usage.
|
||||
*/
|
||||
MonotonicDuration getCleanupPeriod() const { return cleanup_period_; }
|
||||
void setCleanupPeriod(MonotonicDuration period)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,10 @@ public:
|
||||
typedef ServiceResponseTransferListener<DataTypeMaxByteLen> Type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Object of this type will be returned to the application as a result of service call.
|
||||
* Note that application ALWAYS gets this result, even when it times out or fails because of some other reason.
|
||||
*/
|
||||
template <typename DataType>
|
||||
struct UAVCAN_EXPORT ServiceCallResult
|
||||
{
|
||||
@@ -35,9 +38,9 @@ struct UAVCAN_EXPORT ServiceCallResult
|
||||
|
||||
enum Status { Success, ErrorTimeout };
|
||||
|
||||
const Status status;
|
||||
NodeID server_node_id;
|
||||
ResponseFieldType& response; ///< Either response contents or unspecified response structure
|
||||
const Status status; ///< Whether successful or not. Failure to decode the response causes timeout.
|
||||
NodeID server_node_id; ///< Node ID of the server this call was addressed to.
|
||||
ResponseFieldType& response; ///< Returned data structure. Undefined if the service call has failed.
|
||||
|
||||
ServiceCallResult(Status arg_status, NodeID arg_server_node_id, ResponseFieldType& arg_response)
|
||||
: status(arg_status)
|
||||
@@ -48,9 +51,16 @@ struct UAVCAN_EXPORT ServiceCallResult
|
||||
UAVCAN_ASSERT((status == Success) || (status == ErrorTimeout));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut to quickly check whether the call was successful.
|
||||
*/
|
||||
bool isSuccessful() const { return status == Success; }
|
||||
};
|
||||
|
||||
/**
|
||||
* This operator neatly prints the service call result prepended with extra data like Server Node ID.
|
||||
* The extra data will be represented as YAML comment.
|
||||
*/
|
||||
template <typename Stream, typename DataType>
|
||||
static Stream& operator<<(Stream& s, const ServiceCallResult<DataType>& scr)
|
||||
{
|
||||
@@ -68,7 +78,9 @@ static Stream& operator<<(Stream& s, const ServiceCallResult<DataType>& scr)
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Do not use directly.
|
||||
*/
|
||||
class ServiceClientBase : protected DeadlineHandler
|
||||
{
|
||||
protected:
|
||||
@@ -86,16 +98,34 @@ protected:
|
||||
int prepareToCall(INode& node, const char* dtname, NodeID server_node_id, TransferID& out_transfer_id);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns true if the service call is currently in progress.
|
||||
*/
|
||||
bool isPending() const { return pending_; }
|
||||
|
||||
/**
|
||||
* It's not recommended to override default timeouts.
|
||||
*/
|
||||
static MonotonicDuration getDefaultRequestTimeout() { return MonotonicDuration::fromMSec(1000); }
|
||||
static MonotonicDuration getMinRequestTimeout() { return MonotonicDuration::fromMSec(10); }
|
||||
static MonotonicDuration getMaxRequestTimeout() { return MonotonicDuration::fromMSec(60000); }
|
||||
|
||||
/**
|
||||
* Returns the service response waiting deadline, if pending.
|
||||
*/
|
||||
using DeadlineHandler::getDeadline;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Use this class to invoke services on remote nodes.
|
||||
*
|
||||
* @tparam DataType_ Service data type.
|
||||
*
|
||||
* @tparam Callback_ Service response will be delivered through the callback of this type.
|
||||
* In C++11 mode this type defaults to std::function<>.
|
||||
* In C++03 mode this type defaults to a plain function pointer; use binder to
|
||||
* call member functions as callbacks.
|
||||
*/
|
||||
template <typename DataType_,
|
||||
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
|
||||
typename Callback_ = std::function<void (const ServiceCallResult<DataType_>&)>
|
||||
@@ -133,6 +163,10 @@ private:
|
||||
virtual void handleDeadline(MonotonicTime);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param node Node instance this client will be registered with.
|
||||
* @param callback Callback instance. Optional, can be assigned later.
|
||||
*/
|
||||
explicit ServiceClient(INode& node, const Callback& callback = Callback())
|
||||
: SubscriberType(node)
|
||||
, ServiceClientBase(node)
|
||||
@@ -147,23 +181,53 @@ public:
|
||||
|
||||
virtual ~ServiceClient() { cancel(); }
|
||||
|
||||
/**
|
||||
* Shall be called before first use.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int init()
|
||||
{
|
||||
return publisher_.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs non-blocking service call.
|
||||
* This method transmits the service request and returns immediately.
|
||||
*
|
||||
* Service response will be delivered into the application via the callback.
|
||||
* Note that the callback will ALWAYS be called even if the service call has timed out; the
|
||||
* actual result of the call (success/failure) will be passed to the callback as well.
|
||||
*
|
||||
* If this client instance is already pending service response, it will be cancelled and the new
|
||||
* call will be performed.
|
||||
*
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int call(NodeID server_node_id, const RequestType& request);
|
||||
|
||||
/**
|
||||
* Cancel the pending service call.
|
||||
* Does nothing if it is not pending.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Service response callback must be set prior service call.
|
||||
*/
|
||||
const Callback& getCallback() const { return callback_; }
|
||||
void setCallback(const Callback& cb) { callback_ = cb; }
|
||||
|
||||
/**
|
||||
* Returns the number of failed attempts to decode received response. Generally, a failed attempt means either:
|
||||
* - Transient failure in the transport layer.
|
||||
* - Incompatible data types.
|
||||
*/
|
||||
uint32_t getResponseFailureCount() const { return SubscriberType::getFailureCount(); }
|
||||
|
||||
/*
|
||||
* Request timeouts
|
||||
* There is no such config as TX timeout - TX timeouts are configured automagically according to request timeouts
|
||||
/**
|
||||
* Request timeouts.
|
||||
* There is no such config as TX timeout - TX timeouts are configured automagically according to request timeouts.
|
||||
* Not recommended to change.
|
||||
*/
|
||||
MonotonicDuration getRequestTimeout() const { return request_timeout_; }
|
||||
void setRequestTimeout(MonotonicDuration timeout)
|
||||
|
||||
@@ -18,7 +18,26 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Use this class to implement UAVCAN service servers.
|
||||
*
|
||||
* @tparam DataType_ Service data type.
|
||||
*
|
||||
* @tparam Callback_ Service calls will be delivered through the callback of this type, and service
|
||||
* response will be returned via the output parameter of the callback. Note that
|
||||
* the reference to service response data struct passed to the callback always points
|
||||
* to a default initialized response object.
|
||||
* Please also refer to @ref ReceivedDataStructure<>.
|
||||
* In C++11 mode this type defaults to std::function<>.
|
||||
* In C++03 mode this type defaults to a plain function pointer; use binder to
|
||||
* call member functions as callbacks.
|
||||
*
|
||||
* @tparam NumStaticReceivers Number of statically allocated receiver objects. If there's more service
|
||||
* clients for this service, extra receivers will be allocated in the memory pool.
|
||||
*
|
||||
* @tparam NumStaticBufs Number of statically allocated receiver buffers. If there's more concurrent
|
||||
* incoming transfers, extra buffers will be allocated in the memory pool.
|
||||
*/
|
||||
template <typename DataType_,
|
||||
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
|
||||
typename Callback_ = std::function<void (const ReceivedDataStructure<typename DataType_::Request>&,
|
||||
@@ -92,6 +111,10 @@ public:
|
||||
StaticAssert<DataTypeKind(DataType::DataTypeKind) == DataTypeKindService>::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the server.
|
||||
* Incoming service requests will be passed to the application via the callback.
|
||||
*/
|
||||
int start(const Callback& callback)
|
||||
{
|
||||
stop();
|
||||
@@ -112,6 +135,9 @@ public:
|
||||
return SubscriberType::startAsServiceRequestListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the server.
|
||||
*/
|
||||
using SubscriberType::stop;
|
||||
|
||||
static MonotonicDuration getDefaultTxTimeout() { return MonotonicDuration::fromMSec(1000); }
|
||||
@@ -121,6 +147,11 @@ public:
|
||||
MonotonicDuration getTxTimeout() const { return publisher_.getTxTimeout(); }
|
||||
void setTxTimeout(MonotonicDuration tx_timeout) { publisher_.setTxTimeout(tx_timeout); }
|
||||
|
||||
/**
|
||||
* Returns the number of failed attempts to decode data structs. Generally, a failed attempt means either:
|
||||
* - Transient failure in the transport layer.
|
||||
* - Incompatible data types.
|
||||
*/
|
||||
uint32_t getRequestFailureCount() const { return SubscriberType::getFailureCount(); }
|
||||
uint32_t getResponseFailureCount() const { return response_failure_count_; }
|
||||
};
|
||||
|
||||
@@ -18,7 +18,28 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Use this class to subscribe to a message.
|
||||
*
|
||||
* @tparam DataType_ Message data type.
|
||||
*
|
||||
* @tparam Callback_ Type of the callback that will be used to deliver received messages
|
||||
* into the application. Type of the argument of the callback can be either:
|
||||
* - DataType_&
|
||||
* - const DataType_&
|
||||
* - ReceivedDataStructure<DataType_>&
|
||||
* - const ReceivedDataStructure<DataType_>&
|
||||
* For the first two options, @ref ReceivedDataStructure<> will be casted implicitly.
|
||||
* In C++11 mode this type defaults to std::function<>.
|
||||
* In C++03 mode this type defaults to a plain function pointer; use binder to
|
||||
* call member functions as callbacks.
|
||||
*
|
||||
* @tparam NumStaticReceivers Number of statically allocated receiver objects. If there's more publishers
|
||||
* of this message, extra receivers will be allocated in the memory pool.
|
||||
*
|
||||
* @tparam NumStaticBufs Number of statically allocated receiver buffers. If there's more concurrent
|
||||
* incoming transfers, extra buffers will be allocated in the memory pool.
|
||||
*/
|
||||
template <typename DataType_,
|
||||
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
|
||||
typename Callback_ = std::function<void (const ReceivedDataStructure<DataType_>&)>,
|
||||
@@ -70,6 +91,11 @@ public:
|
||||
StaticAssert<DataTypeKind(DataType::DataTypeKind) == DataTypeKindMessage>::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin receiving messages.
|
||||
* Each message will be passed to the application via the callback.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int start(const Callback& callback)
|
||||
{
|
||||
stop();
|
||||
|
||||
@@ -25,10 +25,13 @@ namespace uavcan
|
||||
|
||||
class UAVCAN_EXPORT TimerBase;
|
||||
|
||||
/**
|
||||
* Objects of this type will be supplied into timer callbacks.
|
||||
*/
|
||||
struct UAVCAN_EXPORT TimerEvent
|
||||
{
|
||||
MonotonicTime scheduled_time;
|
||||
MonotonicTime real_time;
|
||||
MonotonicTime scheduled_time; ///< Time when the timer callback was expected to be invoked
|
||||
MonotonicTime real_time; ///< True time when the timer callback was invoked
|
||||
|
||||
TimerEvent(MonotonicTime arg_scheduled_time, MonotonicTime arg_real_time)
|
||||
: scheduled_time(arg_scheduled_time)
|
||||
@@ -36,7 +39,9 @@ struct UAVCAN_EXPORT TimerEvent
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Inherit this class if you need a timer callback method in your class.
|
||||
*/
|
||||
class UAVCAN_EXPORT TimerBase : private DeadlineHandler
|
||||
{
|
||||
MonotonicDuration period_;
|
||||
@@ -54,16 +59,35 @@ public:
|
||||
, period_(MonotonicDuration::getInfinite())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Various ways to start the timer - periodically or once.
|
||||
*/
|
||||
void startOneShotWithDeadline(MonotonicTime deadline);
|
||||
void startOneShotWithDelay(MonotonicDuration delay);
|
||||
void startPeriodic(MonotonicDuration period);
|
||||
|
||||
/**
|
||||
* Returns period if the timer is in periodic mode.
|
||||
* Returns infinite duration if the timer is in one-shot mode or stopped.
|
||||
*/
|
||||
MonotonicDuration getPeriod() const { return period_; }
|
||||
|
||||
/**
|
||||
* Implement this method in your class to receive callbacks.
|
||||
*/
|
||||
virtual void handleTimerEvent(const TimerEvent& event) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper over TimerBase that forwards callbacks into arbitrary handlers, like
|
||||
* functor objects, member functions or static functions.
|
||||
*
|
||||
* Callback must be set before the first event; otherwise the event will generate a fatal error.
|
||||
*
|
||||
* Also take a look at @ref MethodBinder<>, which may come useful if C++11 features are not available.
|
||||
*
|
||||
* @tparam Callback_ Callback type. Shall accept const reference to TimerEvent as its argument.
|
||||
*/
|
||||
template <typename Callback_>
|
||||
class UAVCAN_EXPORT TimerEventForwarder : public TimerBase
|
||||
{
|
||||
@@ -96,6 +120,10 @@ public:
|
||||
, callback_(callback)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Get/set the callback object.
|
||||
* Callback must be set before the first event; otherwise the event will generate a fatal error.
|
||||
*/
|
||||
const Callback& getCallback() const { return callback_; }
|
||||
void setCallback(const Callback& callback) { callback_ = callback; }
|
||||
};
|
||||
@@ -103,6 +131,10 @@ public:
|
||||
|
||||
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
|
||||
|
||||
/**
|
||||
* Use this timer in C++11 mode.
|
||||
* Callback type is std::function<>.
|
||||
*/
|
||||
typedef TimerEventForwarder<std::function<void (const TimerEvent& event)> > Timer;
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user