Merge branch 'dsdl_review'

This commit is contained in:
Pavel Kirienko
2015-03-27 00:05:46 +03:00
96 changed files with 636 additions and 392 deletions
+8 -1
View File
@@ -123,7 +123,6 @@
#if UAVCAN_TOSTRING
# include <string>
# include <cstdio>
#endif
/**
@@ -135,6 +134,14 @@
# define UAVCAN_IMPLEMENT_PLACEMENT_NEW 0
#endif
/**
* Allows the user's application to provide custom implementation of uavcan::snprintf(),
* which is often useful on deeply embedded systems.
*/
#ifndef UAVCAN_USE_EXTERNAL_SNPRINTF
# define UAVCAN_USE_EXTERNAL_SNPRINTF 0
#endif
/**
* Run time checks.
* Resolves to the standard assert() by default.
+1 -1
View File
@@ -7,7 +7,7 @@
#include <cassert>
#include <cstring>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/transport/transfer.hpp>
+1 -1
View File
@@ -7,7 +7,7 @@
#define UAVCAN_DRIVER_CAN_HPP_INCLUDED
#include <cassert>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/driver/system_clock.hpp>
@@ -6,7 +6,7 @@
#ifndef UAVCAN_DRIVER_SYSTEM_CLOCK_HPP_INCLUDED
#define UAVCAN_DRIVER_SYSTEM_CLOCK_HPP_INCLUDED
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/time.hpp>
+1 -2
View File
@@ -8,7 +8,7 @@
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/util/templates.hpp>
#include <uavcan/util/placement_new.hpp>
#include <uavcan/build_config.hpp>
@@ -157,7 +157,6 @@ bool PoolManager<MaxPools>::addPool(IPoolAllocator* pool)
}
}
// We need to keep the pools in order, so that smallest blocks go first
using namespace std; // for qsort()
qsort(pools_, MaxPools, sizeof(IPoolAllocator*), &PoolManager::qsortComparePoolAllocators);
return retval;
}
+1 -1
View File
@@ -6,7 +6,7 @@
#define UAVCAN_ERROR_HPP_INCLUDED
#include <uavcan/build_config.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
namespace uavcan
{
@@ -6,7 +6,7 @@
#define UAVCAN_HELPERS_COMPONENT_STATUS_MANAGER_HPP_INCLUDED
#include <uavcan/build_config.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/protocol/NodeStatus.hpp>
namespace uavcan
+35 -2
View File
@@ -15,6 +15,7 @@
#include <uavcan/build_config.hpp>
#include <uavcan/marshal/type_util.hpp>
#include <uavcan/marshal/integer_spec.hpp>
#include <uavcan/std.hpp>
#ifndef UAVCAN_CPP_VERSION
# error UAVCAN_CPP_VERSION
@@ -714,7 +715,8 @@ public:
StaticAssert<IsDynamic>::check();
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
StaticAssert<(sizeof(A) <= sizeof(long double)) ||
(sizeof(A) <= sizeof(long long))>::check(); // Another stupid check to catch non-primitive types
if (!format)
{
@@ -728,7 +730,6 @@ public:
const SizeType max_size = SizeType(capacity() - size());
// We have one extra byte for the null terminator, hence +1
using namespace std; // For snprintf()
const int ret = snprintf(reinterpret_cast<char*>(ptr), SizeType(max_size + 1U), format, value);
for (int i = 0; i < min(ret, int(max_size)); i++)
@@ -742,6 +743,38 @@ public:
}
}
/**
* Converts the string to upper/lower case in place, assuming that encoding is ASCII.
* These methods can only be used with string-like arrays; otherwise compilation will fail.
*/
void convertToUpperCaseASCII()
{
StaticAssert<Base::IsStringLike>::check();
for (SizeType i = 0; i < size(); i++)
{
const int x = Base::at(i);
if ((x <= 'z') && (x >= 'a'))
{
Base::at(i) = static_cast<ValueType>(x + ('Z' - 'z'));
}
}
}
void convertToLowerCaseASCII()
{
StaticAssert<Base::IsStringLike>::check();
for (SizeType i = 0; i < size(); i++)
{
const int x = Base::at(i);
if ((x <= 'Z') && (x >= 'A'))
{
Base::at(i) = static_cast<ValueType>(x - ('Z' - 'z'));
}
}
}
/**
* Fills this array as a packed square matrix from a static array.
* Please refer to the specification to learn more about matrix packing.
@@ -6,7 +6,7 @@
#define UAVCAN_MARSHAL_BIT_STREAM_HPP_INCLUDED
#include <cassert>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/util/templates.hpp>
#include <uavcan/transport/abstract_transfer_buffer.hpp>
#include <uavcan/build_config.hpp>
@@ -6,7 +6,7 @@
#define UAVCAN_MARSHAL_FLOAT_SPEC_HPP_INCLUDED
#include <cmath>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/util/templates.hpp>
#include <uavcan/build_config.hpp>
@@ -16,9 +16,7 @@
#ifndef UAVCAN_CPP_VERSION
# error UAVCAN_CPP_VERSION
#endif
#if UAVCAN_CPP_VERSION < UAVCAN_CPP11
# include <math.h> // Needed for isfinite()
#else
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
# include <limits> // Assuming that in C++11 mode all standard headers are available
#endif
@@ -169,8 +167,7 @@ public:
private:
static inline void saturate(StorageType& value)
{
using namespace std;
if ((IsExactRepresentation == 0) && isfinite(value))
if ((IsExactRepresentation == 0) && isFinite(value))
{
if (value > max())
{
@@ -189,8 +186,7 @@ private:
static inline void truncate(StorageType& value)
{
using namespace std;
if ((IsExactRepresentation == 0) && isfinite(value))
if ((IsExactRepresentation == 0) && isFinite(value))
{
if (value > max())
{
@@ -5,7 +5,7 @@
#ifndef UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED
#define UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/util/templates.hpp>
#include <uavcan/marshal/scalar_codec.hpp>
@@ -6,7 +6,7 @@
#define UAVCAN_MARSHAL_SCALAR_CODEC_HPP_INCLUDED
#include <cassert>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/util/templates.hpp>
#include <uavcan/marshal/bit_stream.hpp>
@@ -7,7 +7,7 @@
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/data_type.hpp>
#include <uavcan/util/bitset.hpp>
#include <uavcan/util/templates.hpp>
+8
View File
@@ -180,6 +180,14 @@ public:
(void)proto_nsp_.forcePublish();
}
/**
* Updates the vendor-specific status code.
*/
void setVendorSpecificStatusCode(NodeStatusProvider::VendorSpecificStatusCode code)
{
proto_nsp_.setVendorSpecificStatusCode(code);
}
/**
* Sets the node version information.
*/
+1 -1
View File
@@ -5,7 +5,7 @@
#ifndef UAVCAN_NODE_TIMER_HPP_INCLUDED
#define UAVCAN_NODE_TIMER_HPP_INCLUDED
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/error.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/util/linked_list.hpp>
@@ -46,7 +46,12 @@ private:
void (NodeStatusMonitor::*)(const ReceivedDataStructure<protocol::NodeStatus>&)>
NodeStatusCallback;
Subscriber<protocol::NodeStatus, NodeStatusCallback> sub_;
/*
* We'll be able to handle this many nodes in the network without any dynamic memory.
*/
enum { NumStaticReceivers = 64 };
Subscriber<protocol::NodeStatus, NodeStatusCallback, NumStaticReceivers, 0> sub_;
struct Entry
{
@@ -49,6 +49,9 @@ class UAVCAN_EXPORT NodeStatusProvider : private TimerBase
void handleGetNodeInfoRequest(const protocol::GetNodeInfo::Request&, protocol::GetNodeInfo::Response& rsp);
public:
typedef typename StorageType<typename protocol::NodeStatus::FieldTypes::vendor_specific_status_code>::Type
VendorSpecificStatusCode;
explicit NodeStatusProvider(INode& node)
: TimerBase(node)
, creation_timestamp_(node.getMonotonicTime())
@@ -78,8 +81,8 @@ public:
* Refer to the DSDL definition of uavcan.protocol.NodeStatus to see what is the default rate.
* Doesn't fail; if the value is outside of acceptable range, a closest valid value will be used instead.
*/
void setStatusPublishingPeriod(uavcan::MonotonicDuration period);
uavcan::MonotonicDuration getStatusPublishingPeriod() const;
void setStatusPublicationPeriod(uavcan::MonotonicDuration period);
uavcan::MonotonicDuration getStatusPublicationPeriod() const;
/**
* Local node status code control.
@@ -92,6 +95,15 @@ public:
void setStatusCritical() { setStatusCode(protocol::NodeStatus::STATUS_CRITICAL); }
void setStatusOffline() { setStatusCode(protocol::NodeStatus::STATUS_OFFLINE); }
/**
* Local node vendor-specific status code control.
*/
void setVendorSpecificStatusCode(VendorSpecificStatusCode code);
VendorSpecificStatusCode getVendorSpecificStatusCode() const
{
return node_info_.status.vendor_specific_status_code;
}
/**
* Local node name control.
* Can be set only once before the provider is started.
@@ -6,7 +6,7 @@
#define UAVCAN_PROTOCOL_PARAM_SERVER_HPP_INCLUDED
#include <uavcan/protocol/param/GetSet.hpp>
#include <uavcan/protocol/param/SaveErase.hpp>
#include <uavcan/protocol/param/ExecuteOpcode.hpp>
#include <uavcan/node/service_server.hpp>
#include <uavcan/util/method_binder.hpp>
@@ -19,33 +19,35 @@ namespace uavcan
class UAVCAN_EXPORT IParamManager
{
public:
typedef typename StorageType<typename protocol::param::GetSet::Response::FieldTypes::name>::Type ParamName;
typedef typename StorageType<typename protocol::param::GetSet::Request::FieldTypes::index>::Type ParamIndex;
typedef protocol::param::Value ParamValue;
typedef typename StorageType<typename protocol::param::GetSet::Response::FieldTypes::name>::Type Name;
typedef typename StorageType<typename protocol::param::GetSet::Request::FieldTypes::index>::Type Index;
typedef protocol::param::Value Value;
typedef protocol::param::NumericValue NumericValue;
virtual ~IParamManager() { }
/**
* Copy the parameter name to @ref out_name if it exists, otherwise do nothing.
*/
virtual void getParamNameByIndex(ParamIndex index, ParamName& out_name) const = 0;
virtual void getParamNameByIndex(Index index, Name& out_name) const = 0;
/**
* Assign by name if exists.
*/
virtual void assignParamValue(const ParamName& name, const ParamValue& value) = 0;
virtual void assignParamValue(const Name& name, const Value& value) = 0;
/**
* Read by name if exists, otherwise do nothing.
*/
virtual void readParamValue(const ParamName& name, ParamValue& out_value) const = 0;
virtual void readParamValue(const Name& name, Value& out_value) const = 0;
/**
* Read param's default/max/min if available.
* Note that min/max are only applicable to numeric params.
* Implementation is optional.
*/
virtual void readParamDefaultMaxMin(const ParamName& name, ParamValue& out_default,
ParamValue& out_max, ParamValue& out_min) const
virtual void readParamDefaultMaxMin(const Name& name, Value& out_default,
NumericValue& out_max, NumericValue& out_min) const
{
(void)name;
(void)out_default;
@@ -64,6 +66,22 @@ public:
* @return Negative if failed.
*/
virtual int eraseAllParams() = 0;
/**
* Convenience methods that can be used to check if a param value is empty.
*/
static bool isValueEmpty(const Value& val)
{
return val.value_bool.empty() &&
val.value_int.empty() &&
val.value_float.empty() &&
val.value_string.empty();
}
static bool isValueEmpty(const NumericValue& val)
{
return val.value_int.empty() &&
val.value_float.empty();
}
};
/**
@@ -75,19 +93,18 @@ class UAVCAN_EXPORT ParamServer
typedef MethodBinder<ParamServer*, void (ParamServer::*)(const protocol::param::GetSet::Request&,
protocol::param::GetSet::Response&)> GetSetCallback;
typedef MethodBinder<ParamServer*, void (ParamServer::*)(const protocol::param::SaveErase::Request&,
protocol::param::SaveErase::Response&)> SaveEraseCallback;
typedef MethodBinder<ParamServer*,
void (ParamServer::*)(const protocol::param::ExecuteOpcode::Request&,
protocol::param::ExecuteOpcode::Response&)> ExecuteOpcodeCallback;
ServiceServer<protocol::param::GetSet, GetSetCallback> get_set_srv_;
ServiceServer<protocol::param::SaveErase, SaveEraseCallback> save_erase_srv_;
ServiceServer<protocol::param::ExecuteOpcode, ExecuteOpcodeCallback> save_erase_srv_;
IParamManager* manager_;
static bool isValueNonEmpty(const protocol::param::Value& value);
void handleGetSet(const protocol::param::GetSet::Request& request, protocol::param::GetSet::Response& response);
void handleSaveErase(const protocol::param::SaveErase::Request& request,
protocol::param::SaveErase::Response& response);
void handleExecuteOpcode(const protocol::param::ExecuteOpcode::Request& request,
protocol::param::ExecuteOpcode::Response& response);
public:
explicit ParamServer(INode& node)
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
*/
#ifndef UAVCAN_STD_HPP_INCLUDED
#define UAVCAN_STD_HPP_INCLUDED
#include <uavcan/build_config.hpp>
#include <cstdarg>
#if !defined(UAVCAN_CPP_VERSION) || !defined(UAVCAN_CPP11)
# error UAVCAN_CPP_VERSION
#endif
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
# include <cstdint>
# include <cstdio>
namespace uavcan
{
typedef std::uint8_t uint8_t;
typedef std::uint16_t uint16_t;
typedef std::uint32_t uint32_t;
typedef std::uint64_t uint64_t;
typedef std::int8_t int8_t;
typedef std::int16_t int16_t;
typedef std::int32_t int32_t;
typedef std::int64_t int64_t;
}
#else
# include <stdint.h> // Standard integer types from C library
# include <stdio.h> // vsnprintf() from the C library
namespace uavcan
{
typedef ::uint8_t uint8_t;
typedef ::uint16_t uint16_t;
typedef ::uint32_t uint32_t;
typedef ::uint64_t uint64_t;
typedef ::int8_t int8_t;
typedef ::int16_t int16_t;
typedef ::int32_t int32_t;
typedef ::int64_t int64_t;
}
#endif
namespace uavcan
{
/**
* Wrapper over the standard snprintf(). This wrapper is needed because different standards and different
* implementations of C++ do not agree whether snprintf() should be defined in std:: or in ::. The solution
* is to use 'using namespace std' hack inside the wrapper, so the compiler will be able to pick whatever
* definition is available in the standard library. Alternatively, the user's application can provide a
* custom implementation of uavcan::snprintf().
*/
#if __GNUC__
__attribute__ ((format(printf, 3, 4)))
#endif
extern int snprintf(char* out, std::size_t maxlen, const char* format, ...);
#if !UAVCAN_USE_EXTERNAL_SNPRINTF
inline int snprintf(char* out, std::size_t maxlen, const char* format, ...)
{
using namespace std; // This way we can pull vsnprintf() either from std:: or from ::.
va_list args;
va_start(args, format);
const int return_value = vsnprintf(out, maxlen, format, args);
va_end(args);
return return_value;
}
#endif
}
#endif // UAVCAN_STD_HPP_INCLUDED
-57
View File
@@ -1,57 +0,0 @@
/*
* Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
*/
#ifndef UAVCAN_STDINT_HPP_INCLUDED
#define UAVCAN_STDINT_HPP_INCLUDED
#include <uavcan/build_config.hpp>
#if !defined(UAVCAN_CPP_VERSION) || !defined(UAVCAN_CPP11)
# error UAVCAN_CPP_VERSION
#endif
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
# include <cstdint>
namespace uavcan
{
typedef std::uint8_t uint8_t;
typedef std::uint16_t uint16_t;
typedef std::uint32_t uint32_t;
typedef std::uint64_t uint64_t;
typedef std::int8_t int8_t;
typedef std::int16_t int16_t;
typedef std::int32_t int32_t;
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
{
typedef ::uint8_t uint8_t;
typedef ::uint16_t uint16_t;
typedef ::uint32_t uint32_t;
typedef ::uint64_t uint64_t;
typedef ::int8_t int8_t;
typedef ::int16_t int16_t;
typedef ::int32_t int32_t;
typedef ::int64_t int64_t;
}
#endif
#endif // UAVCAN_STDINT_HPP_INCLUDED
+1 -3
View File
@@ -6,7 +6,7 @@
#define UAVCAN_TIME_HPP_INCLUDED
#include <cstdio>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/util/templates.hpp>
#include <uavcan/Timestamp.hpp>
@@ -223,7 +223,6 @@ const unsigned TimeBase<T, D>::StringBufSize;
template <typename D>
void DurationBase<D>::toString(char buf[StringBufSize]) const
{
using namespace std; // For snprintf()
char* ptr = buf;
if (isNegative())
{
@@ -238,7 +237,6 @@ void DurationBase<D>::toString(char buf[StringBufSize]) const
template <typename T, typename D>
void TimeBase<T, D>::toString(char buf[StringBufSize]) const
{
using namespace std; // For snprintf()
(void)snprintf(buf, StringBufSize, "%llu.%06lu",
static_cast<unsigned long long>(toUSec() / 1000000UL),
static_cast<unsigned long>(toUSec() % 1000000UL));
@@ -6,7 +6,7 @@
#define UAVCAN_TRANSPORT_ABSTRACT_TRANSFER_BUFFER_HPP_INCLUDED
#include <uavcan/build_config.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
namespace uavcan
{
@@ -8,7 +8,7 @@
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/util/linked_list.hpp>
#include <uavcan/dynamic_memory.hpp>
#include <uavcan/build_config.hpp>
+1 -1
View File
@@ -6,7 +6,7 @@
#define UAVCAN_TRANSPORT_CRC_HPP_INCLUDED
#include <cassert>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
namespace uavcan
@@ -7,7 +7,7 @@
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/transport/perf_counter.hpp>
#include <uavcan/transport/transfer_listener.hpp>
@@ -6,7 +6,7 @@
#define UAVCAN_TRANSPORT_OUTGOING_TRANSFER_REGISTRY_HPP_INCLUDED
#include <cassert>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
#include <uavcan/util/map.hpp>
#include <uavcan/debug.hpp>
@@ -5,7 +5,7 @@
#ifndef UAVCAN_TRANSPORT_PERF_COUNTER_HPP_INCLUDED
#define UAVCAN_TRANSPORT_PERF_COUNTER_HPP_INCLUDED
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/build_config.hpp>
namespace uavcan
@@ -7,7 +7,7 @@
#include <cassert>
#include <uavcan/build_config.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
namespace uavcan
{
@@ -5,7 +5,7 @@
#ifndef UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED
#define UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/error.hpp>
#include <uavcan/transport/frame.hpp>
#include <uavcan/transport/abstract_transfer_buffer.hpp>
@@ -7,7 +7,7 @@
#include <cassert>
#include <uavcan/error.hpp>
#include <uavcan/stdint.hpp>
#include <uavcan/std.hpp>
#include <uavcan/transport/transfer_receiver.hpp>
#include <uavcan/transport/perf_counter.hpp>
#include <uavcan/util/linked_list.hpp>
@@ -470,6 +470,20 @@ inline bool isInfinity(T arg)
#endif
}
/**
* Replacement for std::isfinite().
* Note that direct float comparison (==, !=) is intentionally avoided.
*/
template <typename T>
inline bool isFinite(T arg)
{
#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11
return std::isfinite(arg);
#else
return !isNaN(arg) && !isInfinity(arg);
#endif
}
/**
* Replacement for std::signbit().
* Note that direct float comparison (==, !=) is intentionally avoided.
-2
View File
@@ -59,8 +59,6 @@ bool CanFrame::priorityHigherThan(const CanFrame& rhs) const
#if UAVCAN_TOSTRING
std::string CanFrame::toString(StringRepresentation mode) const
{
using namespace std; // For snprintf()
UAVCAN_ASSERT(mode == StrTight || mode == StrAligned);
static const unsigned AsciiColumnOffset = 36U;
@@ -56,11 +56,12 @@ int GlobalTimeSyncMaster::IfaceMaster::publish(TransferID tid, MonotonicTime cur
const bool long_period = since_prev_pub.toMSec() >= protocol::GlobalTimeSync::MAX_PUBLICATION_PERIOD_MS;
protocol::GlobalTimeSync msg;
msg.prev_utc_usec = long_period ? 0 : prev_tx_utc_.toUSec();
msg.previous_transmission_timestamp_usec = long_period ? 0 : prev_tx_utc_.toUSec();
prev_tx_utc_ = UtcTime();
UAVCAN_TRACE("GlobalTimeSyncMaster", "Publishing %llu iface=%i tid=%i",
static_cast<unsigned long long>(msg.prev_utc_usec), int(iface_index_), int(tid.get()));
static_cast<unsigned long long>(msg.previous_transmission_timestamp_usec),
int(iface_index_), int(tid.get()));
return pub_.broadcast(msg, tid);
}
@@ -11,8 +11,8 @@ namespace uavcan
void GlobalTimeSyncSlave::adjustFromMsg(const ReceivedDataStructure<protocol::GlobalTimeSync>& msg)
{
UAVCAN_ASSERT(msg.prev_utc_usec > 0);
const UtcDuration adjustment = UtcTime::fromUSec(msg.prev_utc_usec) - prev_ts_utc_;
UAVCAN_ASSERT(msg.previous_transmission_timestamp_usec > 0);
const UtcDuration adjustment = UtcTime::fromUSec(msg.previous_transmission_timestamp_usec) - prev_ts_utc_;
UAVCAN_TRACE("GlobalTimeSyncSlave", "Adjustment: usec=%lli snid=%i iface=%i suppress=%i",
static_cast<long long>(adjustment.toUSec()),
@@ -58,7 +58,7 @@ void GlobalTimeSyncSlave::processMsg(const ReceivedDataStructure<protocol::Globa
{
if (state_ == Adjust)
{
const bool msg_invalid = msg.prev_utc_usec == 0;
const bool msg_invalid = msg.previous_transmission_timestamp_usec == 0;
const bool wrong_tid = prev_tid_.computeForwardDistance(msg.getTransferID()) != 1;
const bool wrong_timing = since_prev_msg.toMSec() > protocol::GlobalTimeSync::MAX_PUBLICATION_PERIOD_MS;
if (msg_invalid || wrong_tid || wrong_timing)
@@ -92,7 +92,7 @@ int NodeStatusProvider::startAndPublish()
goto fail;
}
setStatusPublishingPeriod(MonotonicDuration::fromMSec(protocol::NodeStatus::MAX_PUBLICATION_PERIOD_MS));
setStatusPublicationPeriod(MonotonicDuration::fromMSec(protocol::NodeStatus::MAX_PUBLICATION_PERIOD_MS));
return res;
@@ -104,7 +104,7 @@ fail:
return res;
}
void NodeStatusProvider::setStatusPublishingPeriod(uavcan::MonotonicDuration period)
void NodeStatusProvider::setStatusPublicationPeriod(uavcan::MonotonicDuration period)
{
const MonotonicDuration maximum = MonotonicDuration::fromMSec(protocol::NodeStatus::MAX_PUBLICATION_PERIOD_MS);
const MonotonicDuration minimum = MonotonicDuration::fromMSec(protocol::NodeStatus::MIN_PUBLICATION_PERIOD_MS);
@@ -120,7 +120,7 @@ void NodeStatusProvider::setStatusPublishingPeriod(uavcan::MonotonicDuration per
period.toString().c_str(), node_status_pub_.getTxTimeout().toString().c_str());
}
uavcan::MonotonicDuration NodeStatusProvider::getStatusPublishingPeriod() const
uavcan::MonotonicDuration NodeStatusProvider::getStatusPublicationPeriod() const
{
return TimerBase::getPeriod();
}
@@ -130,6 +130,11 @@ void NodeStatusProvider::setStatusCode(uint8_t code)
node_info_.status.status_code = code;
}
void NodeStatusProvider::setVendorSpecificStatusCode(VendorSpecificStatusCode code)
{
node_info_.status.vendor_specific_status_code = code;
}
void NodeStatusProvider::setName(const char* name)
{
if ((name != NULL) && (*name != '\0') && (node_info_.name.empty()))
+14 -13
View File
@@ -10,11 +10,6 @@
namespace uavcan
{
bool ParamServer::isValueNonEmpty(const protocol::param::Value& value)
{
return !value.value_bool.empty() || !value.value_int.empty() || !value.value_float.empty();
}
void ParamServer::handleGetSet(const protocol::param::GetSet::Request& in, protocol::param::GetSet::Response& out)
{
UAVCAN_ASSERT(manager_ != NULL);
@@ -30,15 +25,21 @@ void ParamServer::handleGetSet(const protocol::param::GetSet::Request& in, proto
out.name = in.name;
}
if (out.name.empty())
{
UAVCAN_TRACE("ParamServer", "GetSet: Can't resolve parameter name, index=%i", int(in.index));
return;
}
// Assign if needed, read back
if (isValueNonEmpty(in.value))
if (!IParamManager::isValueEmpty(in.value))
{
manager_->assignParamValue(out.name, in.value);
}
manager_->readParamValue(out.name, out.value);
// Check if the value is OK, otherwise reset the name to indicate that we have no idea what is it all about
if (isValueNonEmpty(out.value))
if (!IParamManager::isValueEmpty(out.value))
{
manager_->readParamDefaultMaxMin(out.name, out.default_value, out.max_value, out.min_value);
}
@@ -49,22 +50,22 @@ void ParamServer::handleGetSet(const protocol::param::GetSet::Request& in, proto
}
}
void ParamServer::handleSaveErase(const protocol::param::SaveErase::Request& in,
protocol::param::SaveErase::Response& out)
void ParamServer::handleExecuteOpcode(const protocol::param::ExecuteOpcode::Request& in,
protocol::param::ExecuteOpcode::Response& out)
{
UAVCAN_ASSERT(manager_ != NULL);
if (in.opcode == protocol::param::SaveErase::Request::OPCODE_SAVE)
if (in.opcode == protocol::param::ExecuteOpcode::Request::OPCODE_SAVE)
{
out.ok = manager_->saveAllParams() >= 0;
}
else if (in.opcode == protocol::param::SaveErase::Request::OPCODE_ERASE)
else if (in.opcode == protocol::param::ExecuteOpcode::Request::OPCODE_ERASE)
{
out.ok = manager_->eraseAllParams() >= 0;
}
else
{
UAVCAN_TRACE("ParamServer", "SaveErase: invalid opcode %i", int(in.opcode));
UAVCAN_TRACE("ParamServer", "ExecuteOpcode: invalid opcode %i", int(in.opcode));
out.ok = false;
}
}
@@ -83,7 +84,7 @@ int ParamServer::start(IParamManager* manager)
return res;
}
res = save_erase_srv_.start(SaveEraseCallback(this, &ParamServer::handleSaveErase));
res = save_erase_srv_.start(ExecuteOpcodeCallback(this, &ParamServer::handleExecuteOpcode));
if (res < 0)
{
get_set_srv_.stop();
-1
View File
@@ -198,7 +198,6 @@ bool Frame::operator==(const Frame& rhs) const
#if UAVCAN_TOSTRING
std::string Frame::toString() const
{
using namespace std; // For snprintf()
/*
* Frame ID fields, according to UAVCAN specs:
* - Data Type ID
@@ -12,7 +12,6 @@ namespace uavcan
#if UAVCAN_TOSTRING
std::string OutgoingTransferRegistryKey::toString() const
{
using namespace std;
char buf[40];
(void)snprintf(buf, sizeof(buf), "dtid=%u tt=%u dnid=%u",
int(data_type_id_.get()), int(transfer_type_), int(destination_node_id_.get()));
@@ -14,7 +14,6 @@ namespace uavcan
#if UAVCAN_TOSTRING
std::string TransferBufferManagerKey::toString() const
{
using namespace std; // For snprintf()
char buf[24];
(void)snprintf(buf, sizeof(buf), "nid=%i tt=%i", int(node_id_.get()), int(transfer_type_));
return std::string(buf);
+1 -2
View File
@@ -111,8 +111,7 @@ std::string DataTypeDescriptor::toString() const
}
}
using namespace std; // For snprintf()
char buf[80];
char buf[128];
(void)snprintf(buf, sizeof(buf), "%s:%u%c:%016llx",
full_name_, static_cast<unsigned>(id_.get()), kindch,
static_cast<unsigned long long>(signature_.get()));
+6
View File
@@ -105,6 +105,12 @@ TEST(DataTypeDescriptor, ToString)
desc = uavcan::DataTypeDescriptor(uavcan::DataTypeKindMessage, 123,
uavcan::DataTypeSignature(0xdeadbeef1234), "Bar");
ASSERT_EQ("Bar:123m:0000deadbeef1234", desc.toString());
// Max length - 80 chars
desc = uavcan::DataTypeDescriptor(uavcan::DataTypeKindMessage, 1023, uavcan::DataTypeSignature(0xdeadbeef12345678),
"sirius_cybernetics_corporation.marvin.model_a.LongDataTypeName123456789abcdefghi");
ASSERT_EQ("sirius_cybernetics_corporation.marvin.model_a.LongDataTypeName123456789abcdefghi:1023m:deadbeef12345678",
desc.toString());
}
+1 -1
View File
@@ -57,7 +57,7 @@ TEST(Dsdl, Signature)
ASSERT_EQ("root_ns_a.EmptyService", root_ns_a::EmptyService::getDataTypeFullName());
ASSERT_EQ(uavcan::DataTypeKindService, root_ns_a::EmptyService::DataTypeKind);
ASSERT_EQ(0x41a2582ee72be419, root_ns_a::NestedMessage::getDataTypeSignature().get()); // Computed manually
ASSERT_EQ(0x99604d7066e0d713, root_ns_a::NestedMessage::getDataTypeSignature().get()); // Computed manually
ASSERT_EQ("root_ns_a.NestedMessage", root_ns_a::NestedMessage::getDataTypeFullName());
ASSERT_EQ(uavcan::DataTypeKindMessage, root_ns_a::NestedMessage::DataTypeKind);
}
@@ -60,6 +60,7 @@ TEST(Dsdl, Streaming)
"status: \n"
" uptime_sec: 0\n"
" status_code: 0\n"
" vendor_specific_status_code: 0\n"
"software_version: \n"
" major: 0\n"
" minor: 0\n"
+18
View File
@@ -1278,3 +1278,21 @@ TEST(Array, FuzzyComparison)
uavcan::YamlStreamer<ArrayDynamic64>::stream(std::cout, array_d64, 0);
std::cout << std::endl;
}
TEST(Array, CaseConversion)
{
Array<IntegerSpec<8, SignednessUnsigned, CastModeTruncate>, ArrayModeDynamic, 30> str;
str.convertToLowerCaseASCII();
str.convertToUpperCaseASCII();
ASSERT_STREQ("", str.c_str());
str = "Hello World!";
ASSERT_STREQ("Hello World!", str.c_str());
str.convertToLowerCaseASCII();
ASSERT_STREQ("hello world!", str.c_str());
str.convertToUpperCaseASCII();
ASSERT_STREQ("HELLO WORLD!", str.c_str());
}
@@ -37,9 +37,9 @@ TEST(GlobalTimeSyncSlave, Basic)
* The slave must only register the timestamp and adjust nothing
*/
uavcan::protocol::GlobalTimeSync gts;
gts.prev_utc_usec = 0;
gts.previous_transmission_timestamp_usec = 0;
gts_pub.broadcast(gts);
gts.prev_utc_usec = master_clock.utc;
gts.previous_transmission_timestamp_usec = master_clock.utc;
nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(10));
ASSERT_EQ(0, slave_clock.utc);
ASSERT_EQ(1000000, master_clock.utc);
@@ -54,7 +54,7 @@ TEST(GlobalTimeSyncSlave, Basic)
* Slave must adjust now
*/
gts_pub.broadcast(gts);
gts.prev_utc_usec = master_clock.utc;
gts.previous_transmission_timestamp_usec = master_clock.utc;
nodes.spinBoth(uavcan::MonotonicDuration());
ASSERT_EQ(1000000, slave_clock.utc);
ASSERT_EQ(1000000, master_clock.utc);
@@ -72,7 +72,7 @@ TEST(GlobalTimeSyncSlave, Basic)
* Will update
*/
gts_pub.broadcast(gts);
gts.prev_utc_usec = master_clock.utc;
gts.previous_transmission_timestamp_usec = master_clock.utc;
nodes.spinBoth(uavcan::MonotonicDuration());
ASSERT_EQ(2000000, slave_clock.utc);
ASSERT_EQ(2000000, master_clock.utc);
@@ -88,7 +88,7 @@ TEST(GlobalTimeSyncSlave, Basic)
* Will adjust
*/
gts_pub.broadcast(gts);
gts.prev_utc_usec = master_clock.utc;
gts.previous_transmission_timestamp_usec = master_clock.utc;
nodes.spinBoth(uavcan::MonotonicDuration());
ASSERT_EQ(3000000, slave_clock.utc);
ASSERT_EQ(3000000, master_clock.utc);
@@ -117,9 +117,9 @@ TEST(GlobalTimeSyncSlave, Basic)
/*
* Update step, no adjustment yet
*/
gts.prev_utc_usec = 0;
gts.previous_transmission_timestamp_usec = 0;
gts_pub2.broadcast(gts);
gts.prev_utc_usec = master2_clock.utc;
gts.previous_transmission_timestamp_usec = master2_clock.utc;
nodes.spinBoth(uavcan::MonotonicDuration());
ASSERT_EQ(4000000, slave_clock.utc);
ASSERT_EQ(100, master2_clock.utc);
@@ -142,7 +142,7 @@ TEST(GlobalTimeSyncSlave, Basic)
/*
* Another master will be ignored now
*/
gts.prev_utc_usec = 99999999;
gts.previous_transmission_timestamp_usec = 99999999;
// Update
gts_pub.broadcast(gts);
nodes.spinBoth(uavcan::MonotonicDuration());
@@ -20,7 +20,7 @@ static void publishNodeStatus(CanDriverMock& can, uavcan::NodeID node_id, uavcan
// Manual message publication
ASSERT_LT(0, uavcan::protocol::NodeStatus::encode(msg, codec));
ASSERT_GE(7, buffer.getMaxWritePos());
ASSERT_GE(8, buffer.getMaxWritePos());
// DataTypeID data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id,
// uint_fast8_t frame_index, TransferID transfer_id, bool last_frame
@@ -48,15 +48,15 @@ TEST(NodeStatusProvider, Basic)
// Checking the publishing rate settings
ASSERT_EQ(uavcan::MonotonicDuration::fromMSec(uavcan::protocol::NodeStatus::MAX_PUBLICATION_PERIOD_MS),
nsp.getStatusPublishingPeriod());
nsp.getStatusPublicationPeriod());
nsp.setStatusPublishingPeriod(uavcan::MonotonicDuration());
nsp.setStatusPublicationPeriod(uavcan::MonotonicDuration());
ASSERT_EQ(uavcan::MonotonicDuration::fromMSec(uavcan::protocol::NodeStatus::MIN_PUBLICATION_PERIOD_MS),
nsp.getStatusPublishingPeriod());
nsp.getStatusPublicationPeriod());
nsp.setStatusPublishingPeriod(uavcan::MonotonicDuration::fromMSec(3600 * 1000 * 24));
nsp.setStatusPublicationPeriod(uavcan::MonotonicDuration::fromMSec(3600 * 1000 * 24));
ASSERT_EQ(uavcan::MonotonicDuration::fromMSec(uavcan::protocol::NodeStatus::MAX_PUBLICATION_PERIOD_MS),
nsp.getStatusPublishingPeriod());
nsp.getStatusPublicationPeriod());
/*
* Initial status publication
@@ -70,6 +70,22 @@ TEST(NodeStatusProvider, Basic)
ASSERT_TRUE(status_sub.collector.msg.get()); // Was published at startup
ASSERT_EQ(uavcan::protocol::NodeStatus::STATUS_OK, status_sub.collector.msg->status_code);
ASSERT_EQ(0, status_sub.collector.msg->vendor_specific_status_code);
ASSERT_GE(1, status_sub.collector.msg->uptime_sec);
/*
* Altering the vendor-specific status code, forcePublish()-ing it and checking the result
*/
ASSERT_EQ(0, nsp.getVendorSpecificStatusCode());
nsp.setVendorSpecificStatusCode(1234);
ASSERT_EQ(1234, nsp.getVendorSpecificStatusCode());
ASSERT_LE(0, nsp.forcePublish());
nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(10));
ASSERT_EQ(uavcan::protocol::NodeStatus::STATUS_OK, status_sub.collector.msg->status_code);
ASSERT_EQ(1234, status_sub.collector.msg->vendor_specific_status_code);
ASSERT_GE(1, status_sub.collector.msg->uptime_sec);
/*
+20 -10
View File
@@ -12,9 +12,9 @@ struct ParamServerTestManager : public uavcan::IParamManager
typedef std::map<std::string, double> KeyValue;
KeyValue kv;
virtual void getParamNameByIndex(ParamIndex index, ParamName& out_name) const
virtual void getParamNameByIndex(Index index, Name& out_name) const
{
ParamIndex current_idx = 0;
Index current_idx = 0;
for (KeyValue::const_iterator it = kv.begin(); it != kv.end(); ++it, ++current_idx)
{
if (current_idx == index)
@@ -25,8 +25,9 @@ struct ParamServerTestManager : public uavcan::IParamManager
}
}
virtual void assignParamValue(const ParamName& name, const ParamValue& value)
virtual void assignParamValue(const Name& name, const Value& value)
{
assert(!name.empty());
std::cout << "ASSIGN [" << name.c_str() << "]\n" << value << "\n---" << std::endl;
KeyValue::iterator it = kv.find(name.c_str());
if (it != kv.end())
@@ -43,6 +44,10 @@ struct ParamServerTestManager : public uavcan::IParamManager
{
it->second = double(value.value_float[0]);
}
else if (!value.value_string.empty())
{
it->second = std::atof(value.value_string[0].value.c_str());
}
else
{
assert(0);
@@ -50,8 +55,9 @@ struct ParamServerTestManager : public uavcan::IParamManager
}
}
virtual void readParamValue(const ParamName& name, ParamValue& out_value) const
virtual void readParamValue(const Name& name, Value& out_value) const
{
assert(!name.empty());
KeyValue::const_iterator it = kv.find(name.c_str());
if (it != kv.end())
{
@@ -93,23 +99,23 @@ TEST(ParamServer, Basic)
uavcan::GlobalDataTypeRegistry::instance().reset();
uavcan::DefaultDataTypeRegistrator<uavcan::protocol::param::GetSet> _reg1;
uavcan::DefaultDataTypeRegistrator<uavcan::protocol::param::SaveErase> _reg2;
uavcan::DefaultDataTypeRegistrator<uavcan::protocol::param::ExecuteOpcode> _reg2;
ASSERT_LE(0, server.start(&mgr));
ServiceClientWithCollector<uavcan::protocol::param::GetSet> get_set_cln(nodes.b);
ServiceClientWithCollector<uavcan::protocol::param::SaveErase> save_erase_cln(nodes.b);
ServiceClientWithCollector<uavcan::protocol::param::ExecuteOpcode> save_erase_cln(nodes.b);
/*
* Save/erase
*/
uavcan::protocol::param::SaveErase::Request save_erase_rq;
save_erase_rq.opcode = uavcan::protocol::param::SaveErase::Request::OPCODE_SAVE;
uavcan::protocol::param::ExecuteOpcode::Request save_erase_rq;
save_erase_rq.opcode = uavcan::protocol::param::ExecuteOpcode::Request::OPCODE_SAVE;
doCall(save_erase_cln, save_erase_rq, nodes);
ASSERT_TRUE(save_erase_cln.collector.result.get());
ASSERT_TRUE(save_erase_cln.collector.result->response.ok);
save_erase_rq.opcode = uavcan::protocol::param::SaveErase::Request::OPCODE_ERASE;
save_erase_rq.opcode = uavcan::protocol::param::ExecuteOpcode::Request::OPCODE_ERASE;
doCall(save_erase_cln, save_erase_rq, nodes);
ASSERT_TRUE(save_erase_cln.collector.result->response.ok);
@@ -151,7 +157,11 @@ TEST(ParamServer, Basic)
// Set by index
get_set_rq = uavcan::protocol::param::GetSet::Request();
get_set_rq.index = 0;
get_set_rq.value.value_int.push_back(424242);
{
uavcan::protocol::param::String str;
str.value = "424242";
get_set_rq.value.value_string.push_back(str);
}
doCall(get_set_cln, get_set_rq, nodes);
ASSERT_STREQ("foobar", get_set_cln.collector.result->response.name.c_str());
ASSERT_FLOAT_EQ(424242, get_set_cln.collector.result->response.value.value_float[0]);