mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-10 01:58:53 +08:00
libuavcan docs
This commit is contained in:
@@ -17,14 +17,19 @@
|
||||
|
||||
namespace uavcan_linux
|
||||
{
|
||||
|
||||
/**
|
||||
* Different adjustment modes can be used for time synchronization
|
||||
*/
|
||||
enum class ClockAdjustmentMode
|
||||
{
|
||||
SystemWide,
|
||||
PerDriverPrivate
|
||||
SystemWide, ///< Adjust the clock globally for the whole system; requires root privileges
|
||||
PerDriverPrivate ///< Adjust the clock only for the current driver instance
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Linux system clock driver.
|
||||
* Requires librt.
|
||||
*/
|
||||
class SystemClock : public uavcan::ISystemClock
|
||||
{
|
||||
uavcan::UtcDuration private_adj_;
|
||||
@@ -61,6 +66,9 @@ class SystemClock : public uavcan::ISystemClock
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* By default, the clock adjustment mode will be selected automatically - global if root, private otherwise.
|
||||
*/
|
||||
explicit SystemClock(ClockAdjustmentMode adj_mode = detectPreferredClockAdjustmentMode())
|
||||
: gradual_adj_limit_(uavcan::UtcDuration::fromMSec(4000))
|
||||
, adj_mode_(adj_mode)
|
||||
@@ -68,6 +76,10 @@ public:
|
||||
, gradual_adj_cnt_(0)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Returns monotonic timestamp from librt.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
virtual uavcan::MonotonicTime getMonotonic() const
|
||||
{
|
||||
timespec ts;
|
||||
@@ -78,6 +90,10 @@ public:
|
||||
return uavcan::MonotonicTime::fromUSec(std::uint64_t(ts.tv_sec) * UInt1e6 + ts.tv_nsec / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns wall time from gettimeofday().
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
virtual uavcan::UtcTime getUtc() const
|
||||
{
|
||||
timeval tv;
|
||||
@@ -93,6 +109,18 @@ public:
|
||||
return utc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the wall clock.
|
||||
* Behavior depends on the selected clock adjustment mode - @ref ClockAdjustmentMode.
|
||||
* Clock adjustment mode can be set only once via constructor.
|
||||
*
|
||||
* If the system wide adjustment mode is selected, two ways for performing adjustment exist:
|
||||
* - Gradual adjustment using adjtime(), if the phase error is less than gradual adjustment limit.
|
||||
* - Step adjustment using settimeofday(), if the phase error is above gradual adjustment limit.
|
||||
* The gradual adjustment limit can be configured at any time via the setter method.
|
||||
*
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
virtual void adjustUtc(const uavcan::UtcDuration adjustment)
|
||||
{
|
||||
if (adj_mode_ == ClockAdjustmentMode::PerDriverPrivate)
|
||||
@@ -120,6 +148,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum phase error to use adjtime().
|
||||
* If the phase error exceeds this value, settimeofday() will be used instead.
|
||||
*/
|
||||
void setGradualAdjustmentLimit(uavcan::UtcDuration limit)
|
||||
{
|
||||
if (limit.isNegative())
|
||||
@@ -133,8 +165,15 @@ public:
|
||||
|
||||
ClockAdjustmentMode getAdjustmentMode() const { return adj_mode_; }
|
||||
|
||||
/**
|
||||
* This is only applicable if the selected clock adjustment mode is private.
|
||||
* In system wide mode this method will always return zero duration.
|
||||
*/
|
||||
uavcan::UtcDuration getPrivateAdjustment() const { return private_adj_; }
|
||||
|
||||
/**
|
||||
* Statistics that allows to evaluate clock sync preformance.
|
||||
*/
|
||||
std::uint64_t getStepAdjustmentCount() const { return step_adj_cnt_; }
|
||||
std::uint64_t getGradualAdjustmentCount() const { return gradual_adj_cnt_; }
|
||||
std::uint64_t getAdjustmentCount() const
|
||||
@@ -142,6 +181,11 @@ public:
|
||||
return getStepAdjustmentCount() + getGradualAdjustmentCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* This static method decides what is the optimal clock sync adjustment mode for the current configuration.
|
||||
* It selects system wide mode if the application is running as root; otherwise it prefers
|
||||
* the private adjustment mode because the system wide mode requires root privileges.
|
||||
*/
|
||||
static ClockAdjustmentMode detectPreferredClockAdjustmentMode()
|
||||
{
|
||||
const bool godmode = geteuid() == 0;
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
|
||||
namespace uavcan_linux
|
||||
{
|
||||
|
||||
/**
|
||||
* This is the root exception class for all exceptions that can be thrown from the libuavcan Linux driver.
|
||||
*/
|
||||
class Exception : public std::runtime_error
|
||||
{
|
||||
const int errno_;
|
||||
@@ -20,6 +22,10 @@ public:
|
||||
, errno_(errno)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Returns standard UNIX errno value captured at the moment
|
||||
* when this exception object was constructed.
|
||||
*/
|
||||
int getErrno() const { return errno_; }
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
namespace uavcan_linux
|
||||
{
|
||||
/**
|
||||
* Default log sink will dump everything into stderr
|
||||
* Default log sink will dump everything into stderr.
|
||||
* It is installed by default.
|
||||
*/
|
||||
class DefaultLogSink : public uavcan::ILogSink
|
||||
{
|
||||
@@ -29,7 +30,7 @@ class DefaultLogSink : public uavcan::ILogSink
|
||||
|
||||
/**
|
||||
* Wrapper over uavcan::ServiceClient<> for blocking calls.
|
||||
* Calls spin() internally.
|
||||
* Blocks on uavcan::Node::spin() internally until the call is complete.
|
||||
*/
|
||||
template <typename DataType>
|
||||
class BlockingServiceClient : public uavcan::ServiceClient<DataType>
|
||||
@@ -60,6 +61,11 @@ public:
|
||||
setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a blocking service call using default timeout (see the specs).
|
||||
* Use @ref getResponse() to get the actual response.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int blockingCall(uavcan::NodeID server_node_id, const typename DataType::Request& request)
|
||||
{
|
||||
const auto SpinDuration = uavcan::MonotonicDuration::fromMSec(2);
|
||||
@@ -79,6 +85,11 @@ public:
|
||||
return call_res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a blocking service call using the specified timeout. Please consider using default timeout instead.
|
||||
* Use @ref getResponse() to get the actual response.
|
||||
* Returns negative error code.
|
||||
*/
|
||||
int blockingCall(uavcan::NodeID server_node_id, const typename DataType::Request& request,
|
||||
uavcan::MonotonicDuration timeout)
|
||||
{
|
||||
@@ -86,8 +97,15 @@ public:
|
||||
return blockingCall(server_node_id, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the last blocking call was successful.
|
||||
*/
|
||||
bool wasSuccessful() const { return call_was_successful_; }
|
||||
|
||||
/**
|
||||
* Use this to retrieve the response on the last blocking service call.
|
||||
* This method returns default constructed response object if the last service call was unsuccessful.
|
||||
*/
|
||||
const typename DataType::Response& getResponse() const { return response_; }
|
||||
};
|
||||
|
||||
@@ -109,10 +127,11 @@ typedef std::shared_ptr<DriverPack> DriverPackPtr;
|
||||
|
||||
typedef std::shared_ptr<uavcan::Timer> TimerPtr;
|
||||
|
||||
static constexpr std::size_t NodeMemPoolSize = 1024 * 512; // One size fits all
|
||||
static constexpr std::size_t NodeMemPoolSize = 1024 * 512; ///< This shall be enough for any possible use case
|
||||
|
||||
/**
|
||||
* Wrapper for uavcan::Node with some additional convenience functions.
|
||||
* Note that this wrapper adds stderr log sink to @ref uavcan::Logger, which can be removed if needed.
|
||||
*/
|
||||
class Node : public uavcan::Node<NodeMemPoolSize>
|
||||
{
|
||||
@@ -137,7 +156,7 @@ class Node : public uavcan::Node<NodeMemPoolSize>
|
||||
|
||||
public:
|
||||
/**
|
||||
* Simple forwarding constructor, compatible with uavcan::Node
|
||||
* Simple forwarding constructor, compatible with uavcan::Node.
|
||||
*/
|
||||
Node(uavcan::ICanDriver& can_driver, uavcan::ISystemClock& clock)
|
||||
: uavcan::Node<NodeMemPoolSize>(can_driver, clock)
|
||||
@@ -146,7 +165,7 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes ownership of the driver container.
|
||||
* Takes ownership of the driver container via the shared pointer.
|
||||
*/
|
||||
explicit Node(DriverPackPtr driver_pack)
|
||||
: uavcan::Node<NodeMemPoolSize>(driver_pack->can, driver_pack->clock)
|
||||
@@ -155,6 +174,11 @@ public:
|
||||
getLogger().setExternalSink(&log_sink_);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates @ref uavcan::Subscriber in the heap using shared pointer.
|
||||
* The subscriber will be started immediately.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
template <typename DataType>
|
||||
std::shared_ptr<uavcan::Subscriber<DataType>>
|
||||
makeSubscriber(const typename uavcan::Subscriber<DataType>::Callback& cb)
|
||||
@@ -164,6 +188,11 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates @ref uavcan::Publisher in the heap using shared pointer.
|
||||
* The publisher will be initialized immediately.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
template <typename DataType>
|
||||
std::shared_ptr<uavcan::Publisher<DataType>>
|
||||
makePublisher(uavcan::MonotonicDuration tx_timeout = uavcan::Publisher<DataType>::getDefaultTxTimeout())
|
||||
@@ -174,6 +203,11 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates @ref uavcan::ServiceServer in the heap using shared pointer.
|
||||
* The server will be started immediately.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
template <typename DataType>
|
||||
std::shared_ptr<uavcan::ServiceServer<DataType>>
|
||||
makeServiceServer(const typename uavcan::ServiceServer<DataType>::Callback& cb)
|
||||
@@ -183,6 +217,11 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates @ref uavcan::ServiceClient in the heap using shared pointer.
|
||||
* The service client will be initialized immediately.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
template <typename DataType>
|
||||
std::shared_ptr<uavcan::ServiceClient<DataType>>
|
||||
makeServiceClient(const typename uavcan::ServiceClient<DataType>::Callback& cb)
|
||||
@@ -193,6 +232,11 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates @ref uavcan_linux::BlockingServiceClient in the heap using shared pointer.
|
||||
* The service client will be initialized immediately.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
template <typename DataType>
|
||||
std::shared_ptr<BlockingServiceClient<DataType>>
|
||||
makeBlockingServiceClient()
|
||||
@@ -202,6 +246,10 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates @ref uavcan::Timer in the heap using shared pointer.
|
||||
* The timer will be started immediately in one-shot mode.
|
||||
*/
|
||||
TimerPtr makeTimer(uavcan::MonotonicTime deadline, const typename uavcan::Timer::Callback& cb)
|
||||
{
|
||||
TimerPtr p(new uavcan::Timer(*this));
|
||||
@@ -210,6 +258,10 @@ public:
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates @ref uavcan::Timer in the heap using shared pointer.
|
||||
* The timer will be started immediately in periodic mode.
|
||||
*/
|
||||
TimerPtr makeTimer(uavcan::MonotonicDuration period, const typename uavcan::Timer::Callback& cb)
|
||||
{
|
||||
TimerPtr p(new uavcan::Timer(*this));
|
||||
@@ -226,6 +278,8 @@ typedef std::shared_ptr<Node> NodePtr;
|
||||
|
||||
/**
|
||||
* Constructs Node with explicitly specified ClockAdjustmentMode.
|
||||
* Please consider using the overload with fewer parameters instead.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
static inline NodePtr makeNode(const std::vector<std::string>& iface_names, ClockAdjustmentMode clock_adjustment_mode)
|
||||
{
|
||||
@@ -241,7 +295,10 @@ static inline NodePtr makeNode(const std::vector<std::string>& iface_names, Cloc
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the preferred way to make Node.
|
||||
* Use this function to create a node instance.
|
||||
* It accepts the list of interface names to use for the new node, e.g. "can1", "vcan2", "slcan0".
|
||||
* Clock adjustment mode will be detected automatically.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
static inline NodePtr makeNode(const std::vector<std::string>& iface_names)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
namespace uavcan_linux
|
||||
{
|
||||
|
||||
/**
|
||||
* SocketCan driver class keeps number of each kind of errors occurred since the object was created.
|
||||
*/
|
||||
enum class SocketCanError
|
||||
{
|
||||
SocketReadFailure,
|
||||
@@ -35,6 +37,8 @@ enum class SocketCanError
|
||||
};
|
||||
|
||||
/**
|
||||
* Single SocketCAN socket interface.
|
||||
*
|
||||
* SocketCAN socket adapter maintains TX and RX queues in user space. At any moment socket's buffer contains
|
||||
* no more than 'max_frames_in_socket_tx_queue_' TX frames, rest is waiting in the user space TX queue; when the
|
||||
* socket produces loopback for the previously sent TX frame the next frame from the user space TX queue will
|
||||
@@ -308,6 +312,9 @@ public:
|
||||
assert(fd_ >= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Socket file descriptor will be closed.
|
||||
*/
|
||||
virtual ~SocketCanIface()
|
||||
{
|
||||
(void)::close(fd_);
|
||||
@@ -406,8 +413,15 @@ public:
|
||||
return (ret < 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* SocketCAN emulates the CAN filters in software, so the number of filters is virtually unlimited.
|
||||
* This method returns a constant value.
|
||||
*/
|
||||
virtual std::uint16_t getNumFilters() const { return 255; }
|
||||
|
||||
/**
|
||||
* Returns total number of errors of each kind detected since the object was created.
|
||||
*/
|
||||
virtual std::uint64_t getErrorCount() const
|
||||
{
|
||||
std::uint64_t ec = 0;
|
||||
@@ -415,6 +429,9 @@ public:
|
||||
return ec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns number of errors of each kind in a map.
|
||||
*/
|
||||
const decltype(errors_)& getErrors() const { return errors_; }
|
||||
|
||||
int getFileDescriptor() const { return fd_; }
|
||||
@@ -479,9 +496,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Multiplexing container for multiple SocketCAN sockets
|
||||
* Multiplexing container for multiple SocketCAN sockets.
|
||||
* Uses ppoll() for multiplexing.
|
||||
*/
|
||||
class SocketCanDriver : public uavcan::ICanDriver
|
||||
{
|
||||
@@ -495,6 +512,9 @@ private:
|
||||
std::uint8_t num_ifaces_;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Reference to the clock object shall remain valid.
|
||||
*/
|
||||
explicit SocketCanDriver(const SystemClock& clock)
|
||||
: clock_(clock)
|
||||
, num_ifaces_(0)
|
||||
@@ -588,6 +608,7 @@ public:
|
||||
* Adds one iface by name. Will fail if there are @ref MaxIfaces ifaces registered already.
|
||||
* @param iface_name E.g. "can0", "vcan1"
|
||||
* @return Negative on error, zero on success.
|
||||
* @throws uavcan_linux::Exception.
|
||||
*/
|
||||
int addIface(const std::string& iface_name)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user