mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-14 01:43:33 +08:00
libuavcan documentation
This commit is contained in:
@@ -98,7 +98,9 @@ public:
|
||||
bool operator!=(DataTypeSignature rhs) const { return !operator==(rhs); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This class contains complete description of a data type.
|
||||
*/
|
||||
class UAVCAN_EXPORT DataTypeDescriptor
|
||||
{
|
||||
DataTypeKind kind_;
|
||||
|
||||
@@ -18,8 +18,8 @@ namespace uavcan
|
||||
UAVCAN_PACKED_BEGIN
|
||||
struct UAVCAN_EXPORT CanFrame
|
||||
{
|
||||
static const uint32_t MaskStdID = 0x000007FF;
|
||||
static const uint32_t MaskExtID = 0x1FFFFFFF;
|
||||
static const uint32_t MaskStdID = 0x000007FFU;
|
||||
static const uint32_t MaskExtID = 0x1FFFFFFFU;
|
||||
static const uint32_t FlagEFF = 1U << 31; ///< Extended frame format
|
||||
static const uint32_t FlagRTR = 1U << 30; ///< Remote transmission request
|
||||
static const uint32_t FlagERR = 1U << 29; ///< Error frame
|
||||
@@ -37,13 +37,13 @@ struct UAVCAN_EXPORT CanFrame
|
||||
fill(data, data + MaxDataLen, 0);
|
||||
}
|
||||
|
||||
CanFrame(uint32_t arg_id, const uint8_t* arg_data, uint8_t data_len)
|
||||
: id(arg_id)
|
||||
CanFrame(uint32_t can_id, const uint8_t* can_data, uint8_t data_len)
|
||||
: id(can_id)
|
||||
, dlc((data_len > MaxDataLen) ? MaxDataLen : data_len)
|
||||
{
|
||||
UAVCAN_ASSERT(arg_data != NULL);
|
||||
UAVCAN_ASSERT(can_data != NULL);
|
||||
UAVCAN_ASSERT(data_len == dlc);
|
||||
(void)copy(arg_data, arg_data + dlc, this->data);
|
||||
(void)copy(can_data, can_data + dlc, this->data);
|
||||
}
|
||||
|
||||
bool operator!=(const CanFrame& rhs) const { return !operator==(rhs); }
|
||||
@@ -57,12 +57,16 @@ struct UAVCAN_EXPORT CanFrame
|
||||
bool isErrorFrame() const { return id & FlagERR; }
|
||||
|
||||
#if UAVCAN_TOSTRING
|
||||
enum StringRepresentation { StrTight, StrAligned };
|
||||
enum StringRepresentation
|
||||
{
|
||||
StrTight, ///< Minimum string length (default)
|
||||
StrAligned ///< Fixed formatting for any frame
|
||||
};
|
||||
std::string toString(StringRepresentation mode = StrTight) const;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* CAN frames arbitration rules, particularly STD vs EXT:
|
||||
* CAN frame arbitration rules, particularly STD vs EXT:
|
||||
* Marco Di Natale - "Understanding and using the Controller Area Network"
|
||||
* http://www6.in.tum.de/pub/Main/TeachingWs2013MSE/CANbus.pdf
|
||||
*/
|
||||
@@ -72,7 +76,9 @@ struct UAVCAN_EXPORT CanFrame
|
||||
UAVCAN_PACKED_END
|
||||
|
||||
/**
|
||||
* CAN hardware filter config struct. @ref ICanIface::configureFilters().
|
||||
* CAN hardware filter config struct.
|
||||
* Masks from @ref CanFrame can be applied to define frame type (EFF, EXT, etc.).
|
||||
* @ref ICanIface::configureFilters().
|
||||
*/
|
||||
struct UAVCAN_EXPORT CanFilterConfig
|
||||
{
|
||||
@@ -81,7 +87,8 @@ struct UAVCAN_EXPORT CanFilterConfig
|
||||
};
|
||||
|
||||
/**
|
||||
* Events to look for during @ref ICanDriver::select() call
|
||||
* Events to look for during @ref ICanDriver::select() call.
|
||||
* Bit position defines iface index, e.g. read = 1 << 2 to read from the third iface.
|
||||
*/
|
||||
struct UAVCAN_EXPORT CanSelectMasks
|
||||
{
|
||||
@@ -94,6 +101,9 @@ struct UAVCAN_EXPORT CanSelectMasks
|
||||
{ }
|
||||
};
|
||||
|
||||
/**
|
||||
* Special IO flags.
|
||||
*/
|
||||
typedef uint16_t CanIOFlags;
|
||||
static const CanIOFlags CanIOFlagLoopback = 1; ///< Send the frame back to RX with true TX timestamps
|
||||
|
||||
@@ -153,12 +163,13 @@ public:
|
||||
virtual ~ICanDriver() { }
|
||||
|
||||
/**
|
||||
* Returns the interface by index, or null pointer if the index is out of range.
|
||||
* Returns an interface by index, or null pointer if the index is out of range.
|
||||
*/
|
||||
virtual ICanIface* getIface(uint8_t iface_index) = 0;
|
||||
|
||||
/**
|
||||
* Total number of available CAN interfaces.
|
||||
* This value shall not change after initialization.
|
||||
*/
|
||||
virtual uint8_t getNumIfaces() const = 0;
|
||||
|
||||
@@ -166,6 +177,8 @@ public:
|
||||
* Block until the deadline, or one of the specified interfaces becomes available for read or write.
|
||||
* Iface masks will be modified by the driver to indicate which exactly interfaces are available for IO.
|
||||
* Bit position in the masks defines interface index.
|
||||
* Note that it is allowed to return from this method even if no requested events actually happened, or if
|
||||
* there are events that were not requested by the lirary.
|
||||
* @param [in,out] inout_masks Masks indicating which interfaces are needed/available for IO.
|
||||
* @param [in] blocking_deadline Zero means non-blocking operation.
|
||||
* @return Positive number of ready interfaces or negative error code.
|
||||
|
||||
@@ -31,7 +31,10 @@ public:
|
||||
virtual std::size_t getNumBlocks() const = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pool manager contains multiple pool allocators of different block sizes and
|
||||
* finds the most suitable allocator for every allocation request.
|
||||
*/
|
||||
template <unsigned MaxPools>
|
||||
class UAVCAN_EXPORT PoolManager : public IPoolAllocator, Noncopyable
|
||||
{
|
||||
@@ -67,7 +70,9 @@ public:
|
||||
virtual std::size_t getNumBlocks() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Classic implementation of a pool allocator (Meyers).
|
||||
*/
|
||||
template <std::size_t PoolSize, std::size_t BlockSize>
|
||||
class UAVCAN_EXPORT PoolAllocator : public IPoolAllocator, Noncopyable
|
||||
{
|
||||
@@ -103,7 +108,9 @@ public:
|
||||
unsigned getNumUsedBlocks() const { return NumBlocks - getNumFreeBlocks(); }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Limits the maximum number of blocks that can be allocated in a given allocator.
|
||||
*/
|
||||
class LimitedPoolAllocator : public IPoolAllocator
|
||||
{
|
||||
IPoolAllocator& allocator_;
|
||||
|
||||
@@ -13,26 +13,37 @@ namespace
|
||||
{
|
||||
/**
|
||||
* Common error codes.
|
||||
*
|
||||
* Functions that return signed integers may also return inverted error codes,
|
||||
* i.e. returned value should be inverted back to get the actual error code.
|
||||
*
|
||||
* Return code 0 (zero) means no error.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
const int16_t ErrFailure = 1;
|
||||
const int16_t ErrFailure = 1; ///< General failure
|
||||
const int16_t ErrInvalidParam = 2;
|
||||
const int16_t ErrMemory = 3;
|
||||
const int16_t ErrDriver = 4;
|
||||
const int16_t ErrDriver = 4; ///< Platform driver error
|
||||
const int16_t ErrUnknownDataType = 5;
|
||||
const int16_t ErrInvalidMarshalData = 6;
|
||||
const int16_t ErrInvalidTransferListener = 7;
|
||||
const int16_t ErrNotInited = 8;
|
||||
const int16_t ErrRecursiveCall = 9;
|
||||
const int16_t ErrLogic = 10;
|
||||
const int16_t ErrPassiveMode = 11;
|
||||
const int16_t ErrPassiveMode = 11; ///< Operation not permitted in passive mode
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fatal error handler.
|
||||
* Throws std::runtime_error() if exceptions are available, otherwise calls UAVCAN_ASSERT(0) then std::abort().
|
||||
* Behavior:
|
||||
* - If exceptions are enabled, throws std::runtime_error() with the supplied message text;
|
||||
* - If assertions are enabled (no NDEBUG), aborts execution using zero assertion.
|
||||
* - Otherwise aborts execution via std::abort().
|
||||
*/
|
||||
#if __GNUC__
|
||||
__attribute__ ((noreturn))
|
||||
|
||||
@@ -10,7 +10,12 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* This helper class stores status codes of multiple components, and provides a method to quickly retrieve the
|
||||
* worst status code.
|
||||
* It allows to easily assign the node status code with the worst component status code.
|
||||
* Refer to the standard message type uavcan.protocol.NodeStatus for available status codes.
|
||||
*/
|
||||
template <unsigned NumComponents_>
|
||||
class ComponentStatusManager
|
||||
{
|
||||
@@ -30,6 +35,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign the component status by index. Normally, an index would be defined by some enum constant.
|
||||
* @param component_index Normally an enum constant
|
||||
* @param status_code Status code from uavcan.protocol.NodeStatus
|
||||
*/
|
||||
template <typename ComponentIndexType>
|
||||
void setComponentStatus(ComponentIndexType component_index, StatusCode status_code)
|
||||
{
|
||||
@@ -40,6 +50,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns worst status code, i.e. highest value.
|
||||
*/
|
||||
StatusCode getWorstStatusCode() const
|
||||
{
|
||||
StatusCode result = 0;
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
/**
|
||||
* UAVCAN can be compiled in C++11 mode.
|
||||
* This macro allows to detect which version of the C++ standard is being used.
|
||||
*
|
||||
* UAVCAN_CPP_VERSION can be defined explicitly to override auto detection to force compilation in C++03 mode.
|
||||
* Valid values are listed below.
|
||||
*
|
||||
* Note that C++11 and newer requires C++ standard library, while C++03 does not. So, on platforms that
|
||||
* don't implement the standard C++ (e.g. NuttX) use of C++03 may be preferred.
|
||||
*/
|
||||
#define UAVCAN_CPP11 2011
|
||||
#define UAVCAN_CPP03 2003
|
||||
@@ -31,6 +37,8 @@
|
||||
|
||||
/**
|
||||
* UAVCAN can be explicitly told to ignore exceptions, or it can be detected automatically.
|
||||
* Autodetection is not expected to work with all compilers, so it's safer to define it explicitly.
|
||||
* If the autodetection fails, exceptions will be disabled by default.
|
||||
*/
|
||||
#ifndef UAVCAN_EXCEPTIONS
|
||||
# if __EXCEPTIONS || _HAS_EXCEPTIONS
|
||||
@@ -42,7 +50,8 @@
|
||||
|
||||
/**
|
||||
* Struct layout control.
|
||||
* Define UAVCAN_PACK_STRUCTS = 1 to reduce memory usage.
|
||||
* Set UAVCAN_PACK_STRUCTS=1 and define UAVCAN_PACKED_BEGIN and UAVCAN_PACKED_END to reduce memory usage.
|
||||
* THIS MAY BREAK THE CODE.
|
||||
*/
|
||||
#ifndef UAVCAN_PACK_STRUCTS
|
||||
# define UAVCAN_PACK_STRUCTS 0
|
||||
@@ -73,7 +82,8 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* It might make sense to remove toString() methods for an embedded system
|
||||
* It might make sense to remove toString() methods for an embedded system.
|
||||
* If the autodetect fails, toString() will be disabled, so it's pretty safe by default.
|
||||
*/
|
||||
#ifndef UAVCAN_TOSTRING
|
||||
// Objective is to make sure that we're NOT on a resource constrained platform
|
||||
@@ -90,10 +100,9 @@
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Some C++ implementations are half-broken and do not implement the placement new operator.
|
||||
* Setting this preprocessor symbol to 1 makes libuavcan implement its own operator new (std::size_t, void*),
|
||||
* and its delete counterpart.
|
||||
* This option may be removed in future.
|
||||
* Some C++ implementations are half-broken because they don't implement the placement new operator.
|
||||
* If UAVCAN_IMPLEMENT_PLACEMENT_NEW is defined, libuavcan will implement its own operator new (std::size_t, void*)
|
||||
* and its delete() counterpart, instead of relying on the standard header <new>.
|
||||
*/
|
||||
#ifndef UAVCAN_IMPLEMENT_PLACEMENT_NEW
|
||||
# define UAVCAN_IMPLEMENT_PLACEMENT_NEW 0
|
||||
@@ -102,7 +111,7 @@
|
||||
/**
|
||||
* Run time checks.
|
||||
* Resolves to the standard assert() by default.
|
||||
* Can be disabled completely.
|
||||
* Disabled completely if UAVCAN_NO_ASSERTIONS is defined.
|
||||
*/
|
||||
#ifndef UAVCAN_ASSERT
|
||||
# if UAVCAN_NO_ASSERTIONS
|
||||
@@ -116,9 +125,18 @@ namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Should be OK for any target arch up to AMD64 and any compiler.
|
||||
* Memory pool block size.
|
||||
*
|
||||
* The default of 64 bytes should be OK for any target arch up to AMD64 and any compiler.
|
||||
*
|
||||
* The library leverages compile-time checks to ensure that all types that are subject to dynamic allocation
|
||||
* fit this size; otherwise compilation fails.
|
||||
* fit this size, otherwise compilation fails.
|
||||
*
|
||||
* For platforms featuring small pointer width (16..32 bits), UAVCAN_MEM_POOL_BLOCK_SIZE can often be safely
|
||||
* reduced to 56 or even 48 bytes, which leads to lower memory footprint.
|
||||
*
|
||||
* Note that the pool block size shall be aligned at biggest alignment of the target platform (detected and
|
||||
* checked automatically at compile time).
|
||||
*/
|
||||
#if UAVCAN_MEM_POOL_BLOCK_SIZE
|
||||
/// Explicitly specified by the user.
|
||||
@@ -139,6 +157,10 @@ static const unsigned MemPoolAlignment = 16;
|
||||
|
||||
typedef char _alignment_check_for_MEM_POOL_BLOCK_SIZE[((MemPoolBlockSize & (MemPoolAlignment - 1)) == 0) ? 1 : -1];
|
||||
|
||||
/**
|
||||
* This class that allows to check at compile time whether type T can be allocated using the memory pool.
|
||||
* If the check fails, compilation fails.
|
||||
*/
|
||||
template <typename T>
|
||||
struct UAVCAN_EXPORT IsDynamicallyAllocatable
|
||||
{
|
||||
|
||||
@@ -122,7 +122,10 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Statically allocated array with optional dynamic-like behavior
|
||||
* Common functionality for both static and dynamic arrays.
|
||||
* Static arrays are of fixed size; methods that can alter the size (e.g. push_back() and such) will fail to compile.
|
||||
* Dynamic arrays contain a fixed-size buffer (it's size is enough to fit maximum number of elements) plus the
|
||||
* currently allocated number of elements.
|
||||
*/
|
||||
template <typename T, ArrayMode ArrayMode, unsigned MaxSize>
|
||||
class UAVCAN_EXPORT ArrayImpl : public Select<ArrayMode == ArrayModeDynamic,
|
||||
@@ -135,6 +138,7 @@ class UAVCAN_EXPORT ArrayImpl : public Select<ArrayMode == ArrayModeDynamic,
|
||||
public:
|
||||
enum
|
||||
{
|
||||
/// True if the array contents can be interpreted as a 8-bit string (ASCII or UTF8).
|
||||
IsStringLike = IsIntegerSpec<T>::Result && (T::MaxBitLen == 8 || T::MaxBitLen == 7) &&
|
||||
(ArrayMode == ArrayModeDynamic)
|
||||
};
|
||||
@@ -165,6 +169,10 @@ public:
|
||||
|
||||
ArrayImpl() { initialize<ValueType>(0); }
|
||||
|
||||
/**
|
||||
* Returns zero-terminated string, same as std::string::c_str().
|
||||
* This method will compile only if the array can be interpreted as 8-bit string (ASCII of UTF8).
|
||||
*/
|
||||
const char* c_str() const
|
||||
{
|
||||
StaticAssert<IsStringLike>::check();
|
||||
@@ -173,34 +181,53 @@ public:
|
||||
return reinterpret_cast<const char*>(data_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Range-checking subscript.
|
||||
* If the index is out of range:
|
||||
* - if exceptions are enabled, std::out_of_range will be thrown.
|
||||
* - if exceptions are disabled and assert() is enabled, execution will be aborted.
|
||||
* - if exceptions are disabled and assert() is disabled, index will be constrained to the closest valid value.
|
||||
*/
|
||||
ValueType& at(SizeType pos) { return data_[Base::validateRange(pos)]; }
|
||||
const ValueType& at(SizeType pos) const { return data_[Base::validateRange(pos)]; }
|
||||
|
||||
/**
|
||||
* Range-checking subscript. @ref at()
|
||||
*/
|
||||
ValueType& operator[](SizeType pos) { return at(pos); }
|
||||
const ValueType& operator[](SizeType pos) const { return at(pos); }
|
||||
|
||||
/**
|
||||
* Standard container methods. Applicable to both dynamic and static arrays.
|
||||
*/
|
||||
ValueType* begin() { return data_; }
|
||||
const ValueType* begin() const { return data_; }
|
||||
ValueType* end() { return data_ + Base::size(); }
|
||||
const ValueType* end() const { return data_ + Base::size(); }
|
||||
|
||||
ValueType& front() { return at(0); }
|
||||
const ValueType& front() const { return at(0); }
|
||||
ValueType& back() { return at(Base::size() - 1); }
|
||||
const ValueType& back() const { return at(Base::size() - 1); }
|
||||
|
||||
/**
|
||||
* Performs standard lexicographical compare of the elements.
|
||||
*/
|
||||
template <typename R>
|
||||
bool operator<(const R& rhs) const
|
||||
{
|
||||
return ::uavcan::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Aliases for compatibility with standard containers.
|
||||
*/
|
||||
typedef ValueType* iterator;
|
||||
typedef const ValueType* const_iterator;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bit array specialization
|
||||
* Memory-efficient specialization for bit arrays (each element maps to a single bit rather than single byte).
|
||||
* This should be compatible with std::bitset.
|
||||
*/
|
||||
template <unsigned MaxSize, ArrayMode ArrayMode, CastMode CastMode>
|
||||
class UAVCAN_EXPORT ArrayImpl<IntegerSpec<1, SignednessUnsigned, CastMode>, ArrayMode, MaxSize>
|
||||
@@ -219,9 +246,15 @@ public:
|
||||
using ArrayBase::size;
|
||||
using ArrayBase::capacity;
|
||||
|
||||
/**
|
||||
* Range-checking subscript. Throws if enabled; assert() if enabled; else constraints the position.
|
||||
*/
|
||||
Reference at(SizeType pos) { return BitSet<MaxSize>::operator[](ArrayBase::validateRange(pos)); }
|
||||
bool at(SizeType pos) const { return BitSet<MaxSize>::operator[](ArrayBase::validateRange(pos)); }
|
||||
|
||||
/**
|
||||
* @ref at()
|
||||
*/
|
||||
Reference operator[](SizeType pos) { return at(pos); }
|
||||
bool operator[](SizeType pos) const { return at(pos); }
|
||||
};
|
||||
@@ -231,7 +264,16 @@ public:
|
||||
*/
|
||||
template <typename T, ArrayMode ArrayMode> class ArrayImpl<T, ArrayMode, 0>;
|
||||
|
||||
|
||||
/**
|
||||
* Generic array implementation.
|
||||
* This class is compatible with most standard library functions operating on containers (e.g. std::sort(),
|
||||
* std::lexicographical_compare(), etc.).
|
||||
* No dynamic memory is used.
|
||||
* All functions that can modify the array or access elements are range checking. If the range error occurs:
|
||||
* - if exceptions are enabled, std::out_of_range will be thrown;
|
||||
* - if assert() is enabled, program will be terminated on assert(0);
|
||||
* - otherwise the index value will be constrained to the closest valid value.
|
||||
*/
|
||||
template <typename T, ArrayMode ArrayMode, unsigned MaxSize_>
|
||||
class UAVCAN_EXPORT Array : public ArrayImpl<T, ArrayMode, MaxSize_>
|
||||
{
|
||||
@@ -446,9 +488,9 @@ class UAVCAN_EXPORT Array : public ArrayImpl<T, ArrayMode, MaxSize_>
|
||||
}
|
||||
|
||||
public:
|
||||
typedef T RawValueType;
|
||||
typedef typename StorageType<T>::Type ValueType;
|
||||
typedef typename Base::SizeType SizeType;
|
||||
typedef T RawValueType; ///< This may be not the same as the element type.
|
||||
typedef typename StorageType<T>::Type ValueType; ///< This is the actual stored element type.
|
||||
typedef typename Base::SizeType SizeType; ///< Minimal width size type.
|
||||
|
||||
using Base::size;
|
||||
using Base::capacity;
|
||||
@@ -484,6 +526,9 @@ public:
|
||||
|
||||
bool empty() const { return size() == 0; }
|
||||
|
||||
/**
|
||||
* Only for dynamic arrays. Range checking.
|
||||
*/
|
||||
void pop_back() { Base::shrink(); }
|
||||
void push_back(const ValueType& value)
|
||||
{
|
||||
@@ -491,6 +536,9 @@ public:
|
||||
Base::at(size() - 1) = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for dynamic arrays. Range checking.
|
||||
*/
|
||||
void resize(SizeType new_size, const ValueType& filler)
|
||||
{
|
||||
if (new_size > size())
|
||||
@@ -515,13 +563,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for dynamic arrays. Range checking.
|
||||
*/
|
||||
void resize(SizeType new_size)
|
||||
{
|
||||
resize(new_size, ValueType());
|
||||
}
|
||||
|
||||
/*
|
||||
* Comparison operators
|
||||
/**
|
||||
* This operator accepts any container with size() and [].
|
||||
*/
|
||||
template <typename R>
|
||||
typename EnableIf<sizeof(((const R*)(0U))->size()) && sizeof((*((const R*)(0U)))[0]), bool>::Type
|
||||
@@ -541,6 +592,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This operator can only be used with string-like arrays; otherwise it will fail to compile.
|
||||
* @ref c_str()
|
||||
*/
|
||||
bool operator==(const char* ch) const
|
||||
{
|
||||
if (ch == NULL)
|
||||
@@ -552,8 +607,9 @@ public:
|
||||
|
||||
template <typename R> bool operator!=(const R& rhs) const { return !operator==(rhs); }
|
||||
|
||||
/*
|
||||
* Assign/append operators
|
||||
/**
|
||||
* This operator can only be used with string-like arrays; otherwise it will fail to compile.
|
||||
* @ref c_str()
|
||||
*/
|
||||
SelfType& operator=(const char* ch)
|
||||
{
|
||||
@@ -571,6 +627,10 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This operator can only be used with string-like arrays; otherwise it will fail to compile.
|
||||
* @ref c_str()
|
||||
*/
|
||||
SelfType& operator+=(const char* ch)
|
||||
{
|
||||
StaticAssert<Base::IsStringLike>::check();
|
||||
@@ -586,6 +646,9 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends another Array<> with the same element type. Mode and max size can be different.
|
||||
*/
|
||||
template <uavcan::ArrayMode RhsArrayMode, unsigned RhsMaxSize>
|
||||
SelfType& operator+=(const Array<T, RhsArrayMode, RhsMaxSize>& rhs)
|
||||
{
|
||||
@@ -600,9 +663,12 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Formatting appender.
|
||||
* This method doesn't raise an overflow error; instead it silently truncates the data to fit the array capacity.
|
||||
* Works only with string-like arrays, otherwise fails to compile.
|
||||
* @param format Format string for std::snprintf(), e.g. "%08x", "%f"
|
||||
* @param value Arbitrary value of a primitive type (should fail to compile if there's a non-primitive type)
|
||||
*/
|
||||
template <typename A>
|
||||
void appendFormatted(const char* const format, const A value)
|
||||
@@ -610,8 +676,8 @@ public:
|
||||
StaticAssert<Base::IsStringLike>::check();
|
||||
StaticAssert<IsDynamic>::check();
|
||||
|
||||
StaticAssert<sizeof(A() == A(0))>::check(); // This check allows to weed out most non-trivial types
|
||||
StaticAssert<sizeof(A) <= sizeof(long double)>::check(); // Another stupid check to catch non-trivial types
|
||||
StaticAssert<sizeof(A() == A(0))>::check(); // This check allows to weed out most compound types
|
||||
StaticAssert<sizeof(A) <= sizeof(long double)>::check(); // Another stupid check to catch non-primitive types
|
||||
|
||||
if (!format)
|
||||
{
|
||||
@@ -634,13 +700,14 @@ public:
|
||||
}
|
||||
if (ret < 0)
|
||||
{
|
||||
UAVCAN_ASSERT(0); // Likely an invalid format string
|
||||
UAVCAN_ASSERT(0); // Likely an invalid format string
|
||||
(*this) += format; // So we print it as is in release builds
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills this array as a packed square matrix from a static array.
|
||||
* Please refer to the specification to learn more about matrix packing.
|
||||
*/
|
||||
template <typename ScalarType>
|
||||
void packSquareMatrix(const ScalarType (&src_row_major)[MaxSize])
|
||||
@@ -650,6 +717,7 @@ public:
|
||||
|
||||
/**
|
||||
* Fills this array as a packed square matrix in place.
|
||||
* Please refer to the specification to learn more about matrix packing.
|
||||
*/
|
||||
void packSquareMatrix()
|
||||
{
|
||||
@@ -680,6 +748,7 @@ public:
|
||||
|
||||
/**
|
||||
* Fills this array as a packed square matrix from any container that implements the methods begin() and size().
|
||||
* Please refer to the specification to learn more about matrix packing.
|
||||
*/
|
||||
template <typename R>
|
||||
typename EnableIf<sizeof(((const R*)(0U))->begin()) && sizeof(((const R*)(0U))->size())>::Type
|
||||
@@ -706,6 +775,7 @@ public:
|
||||
|
||||
/**
|
||||
* Reconstructs full matrix, result will be saved into a static array.
|
||||
* Please refer to the specification to learn more about matrix packing.
|
||||
*/
|
||||
template <typename ScalarType>
|
||||
void unpackSquareMatrix(ScalarType (&dst_row_major)[MaxSize]) const
|
||||
@@ -715,6 +785,7 @@ public:
|
||||
|
||||
/**
|
||||
* Reconstructs full matrix in place.
|
||||
* Please refer to the specification to learn more about matrix packing.
|
||||
*/
|
||||
void unpackSquareMatrix()
|
||||
{
|
||||
@@ -730,6 +801,7 @@ public:
|
||||
|
||||
/**
|
||||
* Reconstructs full matrix, result will be saved into container that implements begin() and size().
|
||||
* Please refer to the specification to learn more about matrix packing.
|
||||
*/
|
||||
template <typename R>
|
||||
typename EnableIf<sizeof(((const R*)(0U))->begin()) && sizeof(((const R*)(0U))->size())>::Type
|
||||
@@ -749,7 +821,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Aliases for compatibility with standard containers.
|
||||
*/
|
||||
typedef ValueType value_type;
|
||||
typedef SizeType size_type;
|
||||
};
|
||||
@@ -768,7 +842,9 @@ inline bool operator!=(const R& rhs, const Array<T, ArrayMode, MaxSize>& lhs)
|
||||
return lhs.operator!=(rhs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* YAML streamer specification for any Array<>
|
||||
*/
|
||||
template <typename T, ArrayMode ArrayMode, unsigned MaxSize>
|
||||
class UAVCAN_EXPORT YamlStreamer<Array<T, ArrayMode, MaxSize> >
|
||||
{
|
||||
@@ -893,6 +969,9 @@ class UAVCAN_EXPORT YamlStreamer<Array<T, ArrayMode, MaxSize> >
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Prints Array<> into the stream in YAML format.
|
||||
*/
|
||||
template <typename Stream>
|
||||
static void stream(Stream& s, const ArrayType& array, int level)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,10 @@ namespace uavcan
|
||||
|
||||
void bitarrayCopy(const unsigned char* src_org, int src_offset, int src_len, unsigned char* dst_org, int dst_offset);
|
||||
|
||||
/**
|
||||
* This class treats a chunk of memory as an array of bits.
|
||||
* It is used by the bit codec for serialization/deserialization.
|
||||
*/
|
||||
class UAVCAN_EXPORT BitStream
|
||||
{
|
||||
static const unsigned MaxBytesPerRW = 16;
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* This class implements fast encoding/decoding of primitive type scalars into/from bit arrays.
|
||||
* It uses the compile-time type information to eliminate run-time operations where possible.
|
||||
*/
|
||||
class UAVCAN_EXPORT ScalarCodec
|
||||
{
|
||||
BitStream& stream_;
|
||||
|
||||
@@ -9,12 +9,19 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Read the specs to learn more about cast modes.
|
||||
*/
|
||||
enum CastMode { CastModeSaturate, CastModeTruncate };
|
||||
|
||||
/**
|
||||
* Read the specs to learn more about tail array optimizations.
|
||||
*/
|
||||
enum TailArrayOptimizationMode { TailArrayOptDisabled, TailArrayOptEnabled };
|
||||
|
||||
|
||||
/**
|
||||
* Compile-time: Returns the number of bits needed to represent an integer value.
|
||||
*/
|
||||
template <unsigned long Num>
|
||||
struct IntegerBitLen
|
||||
{
|
||||
@@ -26,27 +33,32 @@ struct IntegerBitLen<0>
|
||||
enum { Result = 0 };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compile-time: Returns the number of bytes needed to contain the given number of bits. Assumes 1 byte == 8 bit.
|
||||
*/
|
||||
template <unsigned long BitLen>
|
||||
struct BitLenToByteLen
|
||||
{
|
||||
enum { Result = (BitLen + 7) / 8 };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compile-time: Helper for integer and float specialization classes. Returns the platform-specific storage type.
|
||||
*/
|
||||
template <typename T, typename Enable = void>
|
||||
struct StorageType
|
||||
{
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct StorageType<T, typename EnableIfType<typename T::StorageType>::Type>
|
||||
{
|
||||
typedef typename T::StorageType Type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compile-time: Whether T is a primitive type on this platform.
|
||||
*/
|
||||
template <typename T>
|
||||
class IsPrimitiveType
|
||||
{
|
||||
@@ -63,7 +75,9 @@ public:
|
||||
enum { Result = sizeof(test<T>(0)) == sizeof(Yes) };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Streams a given value into YAML string. Please see the specializations.
|
||||
*/
|
||||
template <typename T>
|
||||
class UAVCAN_EXPORT YamlStreamer;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_; }
|
||||
};
|
||||
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ typedef std::int64_t int64_t;
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* C++03 doesn't define standard integer types, so we pull it from the C library as a workaround.
|
||||
*/
|
||||
# include <stdint.h>
|
||||
|
||||
namespace uavcan
|
||||
|
||||
@@ -83,9 +83,9 @@ public:
|
||||
}
|
||||
|
||||
static const unsigned StringBufSize = 32;
|
||||
void toString(char buf[StringBufSize]) const;
|
||||
void toString(char buf[StringBufSize]) const; ///< Prints time in seconds with microsecond resolution
|
||||
#if UAVCAN_TOSTRING
|
||||
std::string toString() const;
|
||||
std::string toString() const; ///< Prints time in seconds with microsecond resolution
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -169,9 +169,9 @@ public:
|
||||
}
|
||||
|
||||
static const unsigned StringBufSize = 32;
|
||||
void toString(char buf[StringBufSize]) const;
|
||||
void toString(char buf[StringBufSize]) const; ///< Prints time in seconds with microsecond resolution
|
||||
#if UAVCAN_TOSTRING
|
||||
std::string toString() const;
|
||||
std::string toString() const; ///< Prints time in seconds with microsecond resolution
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -187,7 +187,7 @@ class UAVCAN_EXPORT MonotonicTime : public TimeBase<MonotonicTime, MonotonicDura
|
||||
*/
|
||||
class UAVCAN_EXPORT UtcDuration : public DurationBase<UtcDuration> { };
|
||||
|
||||
class UAVCAN_EXPORT UtcTime : public TimeBase<UtcTime, UtcDuration>
|
||||
class UAVCAN_EXPORT UtcTime : public TimeBase<UtcTime, UtcDuration> /// Implicitly convertible to/from uavcan.Timestamp
|
||||
{
|
||||
public:
|
||||
UtcTime() { }
|
||||
|
||||
@@ -19,6 +19,9 @@ namespace uavcan
|
||||
|
||||
class UAVCAN_EXPORT Dispatcher;
|
||||
|
||||
/**
|
||||
* Inherit this class to receive notifications about all TX CAN frames that were transmitted with the loopback flag.
|
||||
*/
|
||||
class UAVCAN_EXPORT LoopbackFrameListenerBase : public LinkedListNode<LoopbackFrameListenerBase>, Noncopyable
|
||||
{
|
||||
Dispatcher& dispatcher_;
|
||||
@@ -54,7 +57,9 @@ public:
|
||||
void invokeListeners(RxFrame& frame);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This class performs low-level CAN frame routing.
|
||||
*/
|
||||
class UAVCAN_EXPORT Dispatcher : Noncopyable
|
||||
{
|
||||
CanIOManager canio_;
|
||||
|
||||
@@ -53,6 +53,9 @@ public:
|
||||
UAVCAN_ASSERT(frame_index <= MaxIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Max payload length depends on the transfer type and frame index.
|
||||
*/
|
||||
int getMaxPayloadLen() const;
|
||||
int setPayload(const uint8_t* data, unsigned len);
|
||||
|
||||
@@ -107,7 +110,14 @@ public:
|
||||
|
||||
bool parse(const CanRxFrame& can_frame);
|
||||
|
||||
/**
|
||||
* Can't be zero.
|
||||
*/
|
||||
MonotonicTime getMonotonicTimestamp() const { return ts_mono_; }
|
||||
|
||||
/**
|
||||
* Can be zero if not supported by the platform driver.
|
||||
*/
|
||||
UtcTime getUtcTimestamp() const { return ts_utc_; }
|
||||
|
||||
uint8_t getIfaceIndex() const { return iface_index_; }
|
||||
|
||||
@@ -57,7 +57,11 @@ public:
|
||||
};
|
||||
UAVCAN_PACKED_END
|
||||
|
||||
|
||||
/**
|
||||
* Outgoing transfer registry keeps track of Transfer ID values for all currently existing local transfer senders.
|
||||
* If a local transfer sender was inactive for a sufficiently long time, the outgoing transfer registry will
|
||||
* remove the respective Transfer ID tracking object.
|
||||
*/
|
||||
class UAVCAN_EXPORT IOutgoingTransferRegistry
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
static const unsigned MaxTransferPayloadLen = 439; ///< According to the RFC
|
||||
static const unsigned MaxTransferPayloadLen = 439; ///< According to the specification.
|
||||
|
||||
static const unsigned MaxSingleFrameTransferPayloadLen = 7;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal, refer to transport dispatcher.
|
||||
* Internal, refer to the transport dispatcher class.
|
||||
*/
|
||||
class UAVCAN_EXPORT TransferListenerBase : public LinkedListNode<TransferListenerBase>, Noncopyable
|
||||
{
|
||||
|
||||
@@ -15,7 +15,13 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* This class allows to postpone the object contruction.
|
||||
* It statically allocates a pool of memory of just enough size to fit the object being constructed.
|
||||
* Later call to construct<>() calls the constructor of the object.
|
||||
* The object will be destroyed automatically when the container class destructor is called.
|
||||
* The memory pool is aligned at the size of the largest primitive type (long double or long long int).
|
||||
*/
|
||||
template <typename T>
|
||||
class UAVCAN_EXPORT LazyConstructor
|
||||
{
|
||||
|
||||
@@ -51,17 +51,27 @@ public:
|
||||
T* get() const { return root_; }
|
||||
bool isEmpty() const { return get() == NULL; }
|
||||
|
||||
/**
|
||||
* Complexity: O(N)
|
||||
*/
|
||||
unsigned getLength() const;
|
||||
|
||||
/**
|
||||
* Complexity: O(N) (calls remove())
|
||||
*/
|
||||
void insert(T* node);
|
||||
|
||||
/**
|
||||
* Inserts node A immediately before the node B where
|
||||
* Inserts the node immediately before the node B where
|
||||
* predicate(B) -> true.
|
||||
* Complexity: O(2N) (calls remove())
|
||||
*/
|
||||
template <typename Predicate>
|
||||
void insertBefore(T* node, Predicate predicate);
|
||||
|
||||
/**
|
||||
* Complexity: O(N)
|
||||
*/
|
||||
void remove(const T* node);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,14 @@ namespace uavcan
|
||||
{
|
||||
/**
|
||||
* Slow but memory efficient KV container.
|
||||
*
|
||||
* KV pairs can be allocated in a static buffer or in the node's memory pool if the static buffer is exhausted.
|
||||
* When a KV pair is deleted from the static buffer, one pair from the memory pool will be moved in the free
|
||||
* slot of the static buffer, so the use of the memory pool is minimized.
|
||||
*
|
||||
* Please be aware that this container does not perform any speed optimizations to minimize memory footprint,
|
||||
* so the complexity of most operations is O(N).
|
||||
*
|
||||
* Type requirements:
|
||||
* Both key and value must be copyable, assignable and default constructible.
|
||||
* Key must implement a comparison operator.
|
||||
@@ -124,21 +132,34 @@ protected:
|
||||
~MapBase() { }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Returns null pointer if there's no such entry.
|
||||
*/
|
||||
Value* access(const Key& key);
|
||||
|
||||
/// If entry with the same key already exists, it will be replaced
|
||||
/**
|
||||
* If entry with the same key already exists, it will be replaced
|
||||
*/
|
||||
Value* insert(const Key& key, const Value& value);
|
||||
|
||||
/**
|
||||
* Does nothing if there's no such entry.
|
||||
*/
|
||||
void remove(const Key& key);
|
||||
|
||||
/**
|
||||
* Remove entries where predicate returns true.
|
||||
* Removes entries where the predicate returns true.
|
||||
* Predicate prototype:
|
||||
* bool (const Key& key, const Value& value)
|
||||
*/
|
||||
template <typename Predicate>
|
||||
void removeWhere(Predicate predicate);
|
||||
|
||||
/**
|
||||
* Returns first entry where the predicate returns true.
|
||||
* Predicate prototype:
|
||||
* bool (const Key& key, const Value& value)
|
||||
*/
|
||||
template <typename Predicate>
|
||||
const Key* findFirstKey(Predicate predicate) const;
|
||||
|
||||
|
||||
@@ -10,7 +10,11 @@
|
||||
|
||||
namespace uavcan
|
||||
{
|
||||
|
||||
/**
|
||||
* Use this to call member functions as callbacks in C++03 mode.
|
||||
*
|
||||
* In C++11 or newer you don't need it because you can use std::function<>/std::bind<> instead.
|
||||
*/
|
||||
template <typename ObjectPtr, typename MemFunPtr>
|
||||
class UAVCAN_EXPORT MethodBinder
|
||||
{
|
||||
@@ -36,17 +40,26 @@ public:
|
||||
, fun_(f)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Returns true if the binder is initialized (doesn't contain null pointers).
|
||||
*/
|
||||
operator bool() const
|
||||
{
|
||||
return try_implicit_cast<bool>(obj_, true) && try_implicit_cast<bool>(fun_, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will raise a fatal error if either method pointer or object pointer are null.
|
||||
*/
|
||||
void operator()()
|
||||
{
|
||||
validateBeforeCall();
|
||||
(obj_->*fun_)();
|
||||
}
|
||||
|
||||
/**
|
||||
* Will raise a fatal error if either method pointer or object pointer are null.
|
||||
*/
|
||||
template <typename Par1>
|
||||
void operator()(Par1& p1)
|
||||
{
|
||||
@@ -54,6 +67,9 @@ public:
|
||||
(obj_->*fun_)(p1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Will raise a fatal error if either method pointer or object pointer are null.
|
||||
*/
|
||||
template <typename Par1, typename Par2>
|
||||
void operator()(Par1& p1, Par2& p2)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
#include <cstddef>
|
||||
#include <uavcan/impl_constants.hpp>
|
||||
|
||||
/*
|
||||
* Some embedded C++ implementations don't implement the placement new operator.
|
||||
* Define UAVCAN_IMPLEMENT_PLACEMENT_NEW to apply this workaround.
|
||||
*/
|
||||
|
||||
#ifndef UAVCAN_IMPLEMENT_PLACEMENT_NEW
|
||||
# error UAVCAN_IMPLEMENT_PLACEMENT_NEW
|
||||
#endif
|
||||
|
||||
@@ -63,14 +63,18 @@ struct UAVCAN_EXPORT EnableIf<true, T>
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Lightweight type categorization.
|
||||
*/
|
||||
template <typename T, typename R = void>
|
||||
struct UAVCAN_EXPORT EnableIfType
|
||||
{
|
||||
typedef R Type;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compile-time type selection (Alexandrescu)
|
||||
*/
|
||||
template <bool Condition, typename TrueType, typename FalseType>
|
||||
struct UAVCAN_EXPORT Select;
|
||||
|
||||
@@ -111,7 +115,11 @@ public:
|
||||
enum { Result = sizeof(True_) == sizeof(IsImplicitlyConvertibleFromTo<T1, T2>::test(returner<T1>())) };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* try_implicit_cast<>(From)
|
||||
* try_implicit_cast<>(From, To)
|
||||
* @{
|
||||
*/
|
||||
template <typename From, typename To>
|
||||
struct UAVCAN_EXPORT TryImplicitCastImpl
|
||||
{
|
||||
@@ -119,6 +127,10 @@ struct UAVCAN_EXPORT TryImplicitCastImpl
|
||||
static To impl(const From&, const To& default_, FalseType) { return default_; }
|
||||
};
|
||||
|
||||
/**
|
||||
* If possible, performs an implicit cast from the type From to the type To.
|
||||
* If the cast is not possible, returns default_ of type To.
|
||||
*/
|
||||
template <typename To, typename From>
|
||||
UAVCAN_EXPORT
|
||||
To try_implicit_cast(const From& from, const To& default_)
|
||||
@@ -127,6 +139,10 @@ To try_implicit_cast(const From& from, const To& default_)
|
||||
BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>());
|
||||
}
|
||||
|
||||
/**
|
||||
* If possible, performs an implicit cast from the type From to the type To.
|
||||
* If the cast is not possible, returns a default constructed object of the type To.
|
||||
*/
|
||||
template <typename To, typename From>
|
||||
UAVCAN_EXPORT
|
||||
To try_implicit_cast(const From& from)
|
||||
@@ -134,9 +150,13 @@ To try_implicit_cast(const From& from)
|
||||
return TryImplicitCastImpl<From, To>::impl(from, To(),
|
||||
BooleanType<IsImplicitlyConvertibleFromTo<From, To>::Result>());
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Some arithmetics
|
||||
* Compile time square root for integers.
|
||||
* Useful for operations on square matrices.
|
||||
*/
|
||||
template <unsigned Value> struct UAVCAN_EXPORT CompileTimeIntSqrt;
|
||||
template <> struct UAVCAN_EXPORT CompileTimeIntSqrt<4> { enum { Result = 2 }; };
|
||||
|
||||
Reference in New Issue
Block a user