mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-10 04:28:54 +08:00
Merge branch 'dsdl_review'
This commit is contained in:
@@ -5,9 +5,12 @@
|
||||
|
||||
uint8 actuator_id
|
||||
|
||||
float16 position # Position feedback; same units as command
|
||||
float16 power # Watt
|
||||
float16 force # Newton (sign depends on the direction of the force)
|
||||
#
|
||||
# Whether the units are linear or angular depends on the actuator type (refer to the Command data type).
|
||||
#
|
||||
float16 position # meter or radian
|
||||
float16 force # Newton or Newton metre
|
||||
float16 speed # meter per second or radian per second
|
||||
|
||||
uint7 POWER_RATING_PCT_UNKNOWN = 127
|
||||
uint7 power_rating_pct # 0 - unloaded, 100 - full load/overload
|
||||
uint7 power_rating_pct # 0 - unloaded, 100 - full load
|
||||
|
||||
@@ -6,10 +6,15 @@
|
||||
uint8 actuator_id
|
||||
|
||||
#
|
||||
# Recommended units are, either:
|
||||
# - Unitless [-1; 1]
|
||||
# - Angular position in radians
|
||||
# - Linear position in meters
|
||||
# Status report should normally use the same units.
|
||||
# Whether the units are linear or angular depends on the actuator type.
|
||||
#
|
||||
float16 command
|
||||
uint4 COMMAND_TYPE_UNITLESS = 0 # [-1, 1]
|
||||
uint4 COMMAND_TYPE_POSITION = 1 # meter or radian
|
||||
uint4 COMMAND_TYPE_FORCE = 2 # Newton or Newton metre
|
||||
uint4 COMMAND_TYPE_SPEED = 3 # meter per second or radian per second
|
||||
uint4 command_type
|
||||
|
||||
#
|
||||
# Value of the above type
|
||||
#
|
||||
float16 command_value
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
#
|
||||
# True airspeed in meters per second.
|
||||
#
|
||||
|
||||
float16 true_airspeed
|
||||
float16 true_airspeed_variance
|
||||
@@ -1,12 +0,0 @@
|
||||
#
|
||||
# Pressure altitude in meters and barometric climb rate in meters per second.
|
||||
#
|
||||
|
||||
uavcan.Timestamp timestamp
|
||||
|
||||
float32 pressure_altitude # m
|
||||
float16 pressure_altitude_variance # m^2
|
||||
|
||||
# Positive if climbing up
|
||||
float16 climb_rate # m/s
|
||||
float16 climb_rate_variance # m^2/s^2
|
||||
@@ -1,9 +0,0 @@
|
||||
#
|
||||
# Static air data for barometric altitude and altitude rate measurements.
|
||||
#
|
||||
|
||||
float32 static_pressure # Pascal
|
||||
float16 static_pressure_variance # Pascal^2
|
||||
|
||||
float16 static_temperature # Kelvin
|
||||
float16 static_temperature_variance # Kelvin^2
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# TAS.
|
||||
#
|
||||
|
||||
float16 true_airspeed # m/s
|
||||
float16 true_airspeed_variance # (m/s)^2
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# IAS.
|
||||
#
|
||||
|
||||
float16 indicated_airspeed # m/s
|
||||
float16 indicated_airspeed_variance # (m/s)^2
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Angle of attack in radians.
|
||||
# Angle of attack.
|
||||
#
|
||||
|
||||
uint8 SENSOR_ID_LEFT = 254
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Static pressure.
|
||||
#
|
||||
|
||||
float32 static_pressure # Pascal
|
||||
float16 static_pressure_variance # Pascal^2
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# Static temperature.
|
||||
#
|
||||
|
||||
float16 static_temperature # Kelvin
|
||||
float16 static_temperature_variance # Kelvin^2
|
||||
+6
-17
@@ -1,31 +1,20 @@
|
||||
#
|
||||
# Generic camera gimbal control.
|
||||
#
|
||||
# This message can only be used in the following modes:
|
||||
# - COMMAND_MODE_ANGULAR_VELOCITY
|
||||
# - COMMAND_MODE_ORIENTATION_FIXED_FRAME
|
||||
# - COMMAND_MODE_ORIENTATION_BODY_FRAME
|
||||
#
|
||||
|
||||
#
|
||||
# Target operation mode - how to handle this message.
|
||||
# See the list of acceptable modes above.
|
||||
#
|
||||
Mode mode
|
||||
|
||||
#
|
||||
# This field is only used in the following modes:
|
||||
# - COMMAND_MODE_ANGULAR_VELOCITY
|
||||
# - COMMAND_MODE_ORIENTATION_FIXED_FRAME
|
||||
# - COMMAND_MODE_ORIENTATION_BODY_FRAME
|
||||
#
|
||||
# In the angular velocity mode, this field contains a rate quaternion.
|
||||
# In the orientation mode, this field contains orientation either in fixed frame or in body frame.
|
||||
#
|
||||
float16[4] quaternion_xyzw
|
||||
|
||||
#
|
||||
# These fields are only used in the following modes:
|
||||
# - COMMAND_MODE_GEO_POI
|
||||
#
|
||||
int32 longitude_deg_1e7 # 1 LSB = 1e-7 deg
|
||||
int32 latitude_deg_1e7
|
||||
int22 height_cm # 1 LSB = 10 mm
|
||||
|
||||
uint2 HEIGHT_REFERENCE_ELLIPSOID = 0
|
||||
uint2 HEIGHT_REFERENCE_MEAN_SEA_LEVEL = 1
|
||||
uint2 height_reference
|
||||
@@ -0,0 +1,23 @@
|
||||
#
|
||||
# Generic camera gimbal control.
|
||||
#
|
||||
# This message can only be used in the following modes:
|
||||
# - COMMAND_MODE_GEO_POI
|
||||
#
|
||||
|
||||
#
|
||||
# Target operation mode - how to handle this message.
|
||||
# See the list of acceptable modes above.
|
||||
#
|
||||
Mode mode
|
||||
|
||||
#
|
||||
# Coordinates of the POI (point of interest).
|
||||
#
|
||||
int32 longitude_deg_1e7 # 1 LSB = 1e-7 deg
|
||||
int32 latitude_deg_1e7
|
||||
int22 height_cm # 1 LSB = 10 mm
|
||||
|
||||
uint2 HEIGHT_REFERENCE_ELLIPSOID = 0
|
||||
uint2 HEIGHT_REFERENCE_MEAN_SEA_LEVEL = 1
|
||||
uint2 height_reference
|
||||
@@ -2,8 +2,8 @@
|
||||
# Gimbal operating mode
|
||||
#
|
||||
|
||||
uint4 COMMAND_MODE_ANGULAR_VELOCITY = 0
|
||||
uint4 COMMAND_MODE_ORIENTATION_FIXED_FRAME = 1
|
||||
uint4 COMMAND_MODE_ORIENTATION_BODY_FRAME = 2
|
||||
uint4 COMMAND_MODE_GEO_POI = 3
|
||||
uint4 command_mode
|
||||
uint8 COMMAND_MODE_ANGULAR_VELOCITY = 0
|
||||
uint8 COMMAND_MODE_ORIENTATION_FIXED_FRAME = 1
|
||||
uint8 COMMAND_MODE_ORIENTATION_BODY_FRAME = 2
|
||||
uint8 COMMAND_MODE_GEO_POI = 3
|
||||
uint8 command_mode
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
#
|
||||
# GNSS navigation solution with uncertainty.
|
||||
#
|
||||
|
||||
uavcan.Timestamp timestamp # Global network-synchronized time, if available, otherwise zero
|
||||
|
||||
uavcan.Timestamp gnss_timestamp # GNSS timestamp (UTC is preferred), if available, otherwise zero
|
||||
|
||||
int37 longitude_deg_1e8 # Longitude degrees multiplied by 1e8 (approx. 1 mm per LSB)
|
||||
int37 latitude_deg_1e8 # Latitude degrees multiplied by 1e8 (approx. 1 mm per LSB on equator)
|
||||
int27 height_ellipsoid_mm # Height above ellipsoid in millimeters
|
||||
int27 height_msl_mm # Height above mean sea level in millimeters
|
||||
|
||||
float16[3] ned_velocity # NED frame (north-east-down) in meters per second
|
||||
|
||||
uint6 sats_used
|
||||
|
||||
uint2 STATUS_NO_FIX = 0
|
||||
uint2 STATUS_TIME_ONLY = 1
|
||||
uint2 STATUS_2D_FIX = 2
|
||||
uint2 STATUS_3D_FIX = 3
|
||||
uint2 status
|
||||
|
||||
float16 pdop
|
||||
|
||||
float16[<=9] position_covariance # m^2
|
||||
float16[<=9] velocity_covariance # (m/s)^2
|
||||
@@ -0,0 +1,52 @@
|
||||
#
|
||||
# GNSS navigation solution with uncertainty.
|
||||
#
|
||||
|
||||
uavcan.Timestamp timestamp # Global network-synchronized time, if available, otherwise zero
|
||||
|
||||
#
|
||||
# Time solution
|
||||
#
|
||||
# The following rules apply:
|
||||
# - if num_leap_seconds = 0, it is assumed that its value is unknown, and that gnss_timestamp contains UTC time.
|
||||
# - if num_leap_seconds = 1, it is assumed that its value is unknown, and that gnss_timestamp contains GPS time.
|
||||
# - if num_leap_seconds = 2, it is assumed that its value is unknown, and that gnss_timestamp contains TAI time.
|
||||
# - if num_leap_seconds > 2, it is assumed that its value is KNOWN, and that gnss_timestamp contains UTC time.
|
||||
#
|
||||
# At the time of February 2015, the number of leap seconds is 26.
|
||||
#
|
||||
uavcan.Timestamp gnss_timestamp # GNSS timestamp, if available, otherwise zero
|
||||
|
||||
uint8 NUM_LEAP_SECONDS_UNKNOWN_GNSS_TIME_UTC = 0 # num_leap_seconds is unknown, gnss_timestamp contains UTC time
|
||||
uint8 NUM_LEAP_SECONDS_UNKNOWN_GNSS_TIME_GPS = 1 # num_leap_seconds is unknown, gnss_timestamp contains GPS time
|
||||
uint8 NUM_LEAP_SECONDS_UNKNOWN_GNSS_TIME_TAI = 2 # num_leap_seconds is unknown, gnss_timestamp contains TAI time
|
||||
uint8 num_leap_seconds
|
||||
|
||||
#
|
||||
# Position and velocity solution
|
||||
#
|
||||
int37 longitude_deg_1e8 # Longitude degrees multiplied by 1e8 (approx. 1 mm per LSB)
|
||||
int37 latitude_deg_1e8 # Latitude degrees multiplied by 1e8 (approx. 1 mm per LSB on equator)
|
||||
int27 height_ellipsoid_mm # Height above ellipsoid in millimeters
|
||||
int27 height_msl_mm # Height above mean sea level in millimeters
|
||||
|
||||
float16[3] ned_velocity # NED frame (north-east-down) in meters per second
|
||||
|
||||
#
|
||||
# Fix status
|
||||
#
|
||||
uint6 sats_used
|
||||
|
||||
uint2 STATUS_NO_FIX = 0
|
||||
uint2 STATUS_TIME_ONLY = 1
|
||||
uint2 STATUS_2D_FIX = 2
|
||||
uint2 STATUS_3D_FIX = 3
|
||||
uint2 status
|
||||
|
||||
#
|
||||
# Precision
|
||||
#
|
||||
float16 pdop
|
||||
|
||||
float16[<=9] position_covariance # m^2
|
||||
float16[<=9] velocity_covariance # (m/s)^2
|
||||
-2
@@ -13,5 +13,3 @@ float16 edop
|
||||
|
||||
uint7 sats_visible # All visible sats of all available GNSS (e.g. GPS, GLONASS, etc)
|
||||
uint6 sats_used # All used sats of all available GNSS
|
||||
|
||||
bool differential_corrections_applied
|
||||
@@ -1,9 +0,0 @@
|
||||
#
|
||||
# X/Y velocities estimated by a simple downward looking optical flow sensor.
|
||||
#
|
||||
|
||||
uavcan.Timestamp timestamp
|
||||
|
||||
float16 linear_velocity_x
|
||||
float16 linear_velocity_y
|
||||
float16 linear_velocity_variance
|
||||
+5
-6
@@ -33,8 +33,8 @@ uint11 STATUS_MASK_OVERLOAD = 32 # Safe operating area violation
|
||||
uint11 STATUS_MASK_BAD_BATTERY = 64 # This battery should not be used anymore (e.g. low SOH)
|
||||
uint11 STATUS_MASK_NEED_SERVICE = 128 # This battery requires maintenance (e.g. balancing, full recharge)
|
||||
uint11 STATUS_MASK_BMS_ERROR = 256 # Battery management system/controller error, smart battery interface error
|
||||
uint11 STATUS_MASK_VENDOR_A = 512 # Vendor-specific flag
|
||||
uint11 STATUS_MASK_VENDOR_B = 1024 # Vendor-specific flag
|
||||
uint11 STATUS_MASK_RESERVED_A = 512 # Keep zero
|
||||
uint11 STATUS_MASK_RESERVED_B = 1024 # Keep zero
|
||||
uint11 status_mask
|
||||
|
||||
#
|
||||
@@ -53,11 +53,10 @@ uint7 state_of_charge_pct_stdev # SOC error standard deviation; use best
|
||||
|
||||
#
|
||||
# Battery identification.
|
||||
# Instance ID must be unique within the same battery model name.
|
||||
# Model instance ID must be unique within the same battery model name.
|
||||
# Model name is a human-readable string that normally should include the vendor name, model name, and chemistry
|
||||
# type of this battery. This field should be assumed case-insensitive. Example: "Zubax Smart Battery v1.1 LiPo".
|
||||
#
|
||||
uint32 instance_id # Set to zero if not applicable
|
||||
uint6 battery_index # Identifies the battery within this vehicle, e.g. 0 - primary battery
|
||||
uint2 group_id # Not used, set zero
|
||||
uint8 battery_id # Identifies the battery within this vehicle, e.g. 0 - primary battery
|
||||
uint32 model_instance_id # Set to zero if not applicable
|
||||
uint8[<32] model_name # Battery model name
|
||||
@@ -1,19 +0,0 @@
|
||||
#
|
||||
# Altitude above ground level.
|
||||
# A single node can publish measurements from different sensors concurrently.
|
||||
#
|
||||
|
||||
uavcan.Timestamp timestamp
|
||||
|
||||
float16 altitude_agl # +inf - too far, -inf - too close
|
||||
float16 altitude_agl_variance # +inf if too close or too far
|
||||
|
||||
float16 sensor_max_range
|
||||
float16 sensor_min_range
|
||||
|
||||
uint8 SENSOR_UNKNOWN = 0
|
||||
uint8 SENSOR_SONAR = 1
|
||||
uint8 SENSOR_LASER = 2
|
||||
uint8 SENSOR_RADAR = 3
|
||||
uint8 SENSOR_CV = 4
|
||||
uint8 sensor_type
|
||||
@@ -1,25 +0,0 @@
|
||||
#
|
||||
# Generic narrow-beam range sensor data.
|
||||
#
|
||||
|
||||
uavcan.Timestamp timestamp
|
||||
|
||||
uint8 sensor_id
|
||||
|
||||
uavcan.equipment.CoarseOrientation beam_orientation # In body frame
|
||||
|
||||
float16 field_of_view # Radians
|
||||
|
||||
uint4 SENSOR_TYPE_UNDEFINED = 0
|
||||
uint4 SENSOR_TYPE_SONAR = 1
|
||||
uint4 SENSOR_TYPE_LIDAR = 2
|
||||
uint4 SENSOR_TYPE_RADAR = 3
|
||||
uint4 sensor_type
|
||||
|
||||
uint4 READING_TYPE_UNDEFINED = 0 # Range is unknown
|
||||
uint4 READING_TYPE_VALID_RANGE = 1 # Range field contains valid distance
|
||||
uint4 READING_TYPE_TOO_CLOSE = 2 # Range field contains min range for the sensor
|
||||
uint4 READING_TYPE_TOO_FAR = 3 # Range field contains max range for the sensor
|
||||
uint4 reading_type
|
||||
|
||||
float16 range # Meters
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Generic narrow-beam range sensor data.
|
||||
#
|
||||
|
||||
uavcan.Timestamp timestamp
|
||||
|
||||
uint8 sensor_id
|
||||
|
||||
uavcan.equipment.CoarseOrientation beam_orientation # In body frame
|
||||
|
||||
float16 field_of_view # Radians
|
||||
|
||||
uint5 SENSOR_TYPE_UNDEFINED = 0
|
||||
uint5 SENSOR_TYPE_SONAR = 1
|
||||
uint5 SENSOR_TYPE_LIDAR = 2
|
||||
uint5 SENSOR_TYPE_RADAR = 3
|
||||
uint5 sensor_type
|
||||
|
||||
uint3 READING_TYPE_UNDEFINED = 0 # Range is unknown
|
||||
uint3 READING_TYPE_VALID_RANGE = 1 # Range field contains valid distance
|
||||
uint3 READING_TYPE_TOO_CLOSE = 2 # Range field contains min range for the sensor
|
||||
uint3 READING_TYPE_TOO_FAR = 3 # Range field contains max range for the sensor
|
||||
uint3 reading_type
|
||||
|
||||
float16 range # Meters
|
||||
@@ -1,6 +0,0 @@
|
||||
#
|
||||
# Orientation and thrust setpoint for VTOL crafts.
|
||||
#
|
||||
|
||||
float16[4] orientation_xyzw
|
||||
float16 thrust # Normal range [0, 1]; or [-1, 1] if thrust can be reversed
|
||||
@@ -1,15 +1,17 @@
|
||||
#
|
||||
# Global time synchronization.
|
||||
# Should be UTC time, not GPS time nor local time.
|
||||
# Preferred time is UTC.
|
||||
# Any node that publishes timestamped data must use this time reference.
|
||||
# This message is not intended for unicast transfers.
|
||||
#
|
||||
# Please refer to the specification to learn about time synchronization algorithm.
|
||||
#
|
||||
|
||||
uint16 MAX_PUBLICATION_PERIOD_MS = 1100
|
||||
uint16 MIN_PUBLICATION_PERIOD_MS = 350
|
||||
uint16 MAX_PUBLICATION_PERIOD_MS = 1100 # Milliseconds
|
||||
uint16 MIN_PUBLICATION_PERIOD_MS = 350 # Milliseconds
|
||||
|
||||
uint16 PUBLISHER_TIMEOUT_MS = 10000
|
||||
uint16 PUBLISHER_TIMEOUT_MS = 10000 # Milliseconds
|
||||
|
||||
# UTC time in microseconds when the PREVIOUS GlobalTimeSync message was transmitted.
|
||||
# Time in microseconds when the PREVIOUS GlobalTimeSync message was transmitted.
|
||||
# If this message is the first one, this field must be zero.
|
||||
uint64 prev_utc_usec
|
||||
uint64 previous_transmission_timestamp_usec # Microseconds
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
#
|
||||
# Abstract node status information.
|
||||
# Any UAVCAN node is required to publish this message periodically.
|
||||
# It is NOT recommended to change its publication rate at run time.
|
||||
#
|
||||
# See http://uavcan.org/Standard_data_types_and_application_level_functions
|
||||
#
|
||||
|
||||
uint16 MAX_PUBLICATION_PERIOD_MS = 1000
|
||||
uint16 MIN_PUBLICATION_PERIOD_MS = 20
|
||||
uint16 MIN_PUBLICATION_PERIOD_MS = 2
|
||||
|
||||
# If a node fails to publish this message in this amount of time, it should be considered offline.
|
||||
uint16 OFFLINE_TIMEOUT_MS = 3000
|
||||
@@ -13,9 +16,6 @@ uint16 OFFLINE_TIMEOUT_MS = 3000
|
||||
uint28 uptime_sec
|
||||
|
||||
# Status code should be used to reflect the node status in the most abstract way.
|
||||
# Use cases: top-level onboard computer should not allow the UAV to begin normal operation
|
||||
# unless all nodes report OK. If a mission critical node reports CRITICAL status, current
|
||||
# mission should be immediately yet safely aborted (e.g. RTL).
|
||||
# OFFLINE status can be actually reported by the node to explicitly inform other network
|
||||
# participants that the sending node is about to shutdown. In this case other nodes will not
|
||||
# have to wait OFFLINE_TIMEOUT_MS before they detect that the node is no longer available.
|
||||
@@ -25,3 +25,6 @@ uint4 STATUS_WARNING = 2
|
||||
uint4 STATUS_CRITICAL = 3
|
||||
uint4 STATUS_OFFLINE = 15
|
||||
uint4 status_code
|
||||
|
||||
# Optional, vendor-specific node status code, e.g. a fault code or a status bitmask.
|
||||
uint16 vendor_specific_status_code
|
||||
|
||||
@@ -16,4 +16,4 @@ HardwareVersion hardware_version
|
||||
# Empty string is not a valid node name.
|
||||
# Node name shall not be changed while the node is running.
|
||||
# The naming convention is like of Java packages (reversed internet domain names), e.g. "com.example.project.product".
|
||||
uint8[<64] name
|
||||
uint8[<=80] name
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#
|
||||
# Restart the node.
|
||||
# Some nodes may require restart before the new configuration will be applied.
|
||||
# The request should be rejected if magic_number does not equal MAGIC_NUMBER.
|
||||
#
|
||||
|
||||
uint40 MAGIC_NUMBER = 0xACCE551B1E
|
||||
|
||||
@@ -2,14 +2,6 @@
|
||||
# Generic named parameter (key/value pair).
|
||||
#
|
||||
|
||||
uint3 TYPE_UNDEF = 0
|
||||
uint3 TYPE_INTEGER = 1
|
||||
uint3 TYPE_FLOAT = 2
|
||||
uint3 TYPE_STRING = 3
|
||||
uint3 TYPE_BYTES = 4
|
||||
uint3 type
|
||||
uint8[<=92] key
|
||||
|
||||
uint8[<64] key
|
||||
|
||||
float64[<=1] numeric_value # For type = INTEGER, FLOAT
|
||||
uint8[<256] binary_value # For type = STRING, BYTES
|
||||
uavcan.protocol.param.Value value
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#
|
||||
# Start HIL simulation for the specified components.
|
||||
# The request should be rejected if magic_number does not equal MAGIC_NUMBER.
|
||||
#
|
||||
|
||||
uint40 MAGIC_NUMBER = 0xACCE551B1E
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Nested type.
|
||||
# File system path in ASCII or UTF8.
|
||||
# The only valid separator is forward flash.
|
||||
# File system path in UTF8.
|
||||
# The only valid separator is forward slash.
|
||||
#
|
||||
|
||||
uint8 SEPARATOR = '/'
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#
|
||||
# Service to control the node configuration.
|
||||
#
|
||||
# SAVE operation instructs the remote node to save the current configuration parameters to the non-volatile
|
||||
# storage. The node may require a restart in order for some changes to take effect.
|
||||
#
|
||||
# ERASE operation instructs the remote node to clear its configuration storage and reinitialize the parameters
|
||||
# with their default values. The node may require a restart in order for some changes to take effect.
|
||||
#
|
||||
# Other opcodes may be added in the future (for example, an opcode for switching between multiple configurations).
|
||||
#
|
||||
|
||||
uint8 OPCODE_SAVE = 0 # Save all parameters to non-volatile storage.
|
||||
uint8 OPCODE_ERASE = 1 # Clear the non-volatile storage; some changes may take effect only after reboot.
|
||||
uint8 opcode
|
||||
|
||||
#
|
||||
# Reserved, keep zero.
|
||||
#
|
||||
int48 argument
|
||||
|
||||
---
|
||||
|
||||
#
|
||||
# Reserved, keep zero.
|
||||
#
|
||||
int48 argument
|
||||
|
||||
bool ok
|
||||
@@ -1,11 +0,0 @@
|
||||
#
|
||||
# Service to control non-volatile parameter storage.
|
||||
#
|
||||
|
||||
uint2 OPCODE_SAVE = 0 # Save all parameters to non-volatile storage
|
||||
uint2 OPCODE_ERASE = 1 # Clear the non-volatile storage; actual parameter values may or may not be affected
|
||||
uint2 opcode
|
||||
|
||||
---
|
||||
|
||||
bool ok
|
||||
@@ -1,26 +1,34 @@
|
||||
#
|
||||
# Get or set a parameter by name or by index.
|
||||
# Note that access by index should only be used to retreive the list of parameters; it is higly
|
||||
# discouraged to use it for anything else, because persistent ordering is not guaranteed.
|
||||
#
|
||||
|
||||
# If set - parameter will be assigned this value, then the new value will be returned
|
||||
# If not set - current parameter value will be returned
|
||||
# If set - parameter will be assigned this value, then the new value will be returned.
|
||||
# If not set - current parameter value will be returned.
|
||||
# Refer to the definition of Value for details.
|
||||
Value value
|
||||
|
||||
# Index of the parameter starting from 0; ignored if name is nonempty
|
||||
# Index of the parameter starting from 0; ignored if name is nonempty.
|
||||
# Use index only to retrieve the list of parameters.
|
||||
uint8 index
|
||||
|
||||
# Name of the parameter; always preferred over index if nonempty
|
||||
uint8[<=40] name
|
||||
# Name of the parameter; always preferred over index if nonempty.
|
||||
uint8[<=92] name
|
||||
|
||||
---
|
||||
|
||||
# Actual parameter value. For write requests it must contain the newly assigned parameter value.
|
||||
# Actual parameter value.
|
||||
# For set requests, it should contain the actual parameter value after the set request was
|
||||
# executed. The objective is to let the client know if the value could not be updated, e.g.
|
||||
# due to its range violation, etc.
|
||||
# Empty value indicates that there is no such parameter.
|
||||
Value value
|
||||
|
||||
Value default_value # Optional
|
||||
Value max_value # Optional
|
||||
Value min_value # Optional
|
||||
Value default_value # Optional
|
||||
|
||||
NumericValue max_value # Optional, not applicable for bool/string
|
||||
NumericValue min_value # Optional, not applicable for bool/string
|
||||
|
||||
# Empty name in response indicates that there is no such parameter
|
||||
uint8[<=40] name
|
||||
uint8[<=92] name
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#
|
||||
# Numeric-only value.
|
||||
# The actual type should be inferred from the available values, as described below.
|
||||
# If none of the values below are present, the value is considered empty.
|
||||
#
|
||||
|
||||
int64[<=1] value_int # Preferred over float if ambiguous
|
||||
float32[<=1] value_float # Only if int is empty
|
||||
@@ -0,0 +1,5 @@
|
||||
#
|
||||
# This type is nested in Value.
|
||||
#
|
||||
|
||||
uint8[<=127] value
|
||||
@@ -1,8 +1,10 @@
|
||||
#
|
||||
# Single parameter value.
|
||||
# The actual type should be detected from the available values, as described below.
|
||||
# The actual type should be inferred from the available values, as described below.
|
||||
# If none of the values below are present, the value is considered empty.
|
||||
#
|
||||
|
||||
bool[<=1] value_bool # Preferred over int and float if ambiguous
|
||||
int64[<=1] value_int # Preferred over float if ambiguous
|
||||
float32[<=1] value_float
|
||||
bool[<=1] value_bool # Preferred over int, float and string if ambiguous
|
||||
int64[<=1] value_int # Preferred over float and string if ambiguous
|
||||
float32[<=1] value_float # Preferred over string if ambiguous
|
||||
String[<=1] value_string # This one will be used only if all above are empty
|
||||
|
||||
+2
-5
@@ -1,12 +1,9 @@
|
||||
All the unallocated space can be claimed later.
|
||||
|
||||
256..399 - high priority equipment
|
||||
|
||||
540..549 - high priority nav
|
||||
256..449 - high priority equipment
|
||||
|
||||
550..599 - protocol
|
||||
|
||||
600..749 - low priority eqipment
|
||||
|
||||
760..766 - low priority nav
|
||||
|
||||
767 - MAVLink
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
/*
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -84,6 +84,7 @@ static void runForever(const uavcan_linux::NodePtr& node)
|
||||
auto do_nothing_once_a_minute = [&node](const uavcan::TimerEvent&)
|
||||
{
|
||||
node->logInfo("timer", "Another minute passed...");
|
||||
node->setVendorSpecificStatusCode(static_cast<std::uint16_t>(std::rand())); // Setting to an arbitrary value
|
||||
};
|
||||
auto timer = node->makeTimer(uavcan::MonotonicDuration::fromMSec(60000), do_nothing_once_a_minute);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <uavcan/protocol/param/GetSet.hpp>
|
||||
#include <uavcan/protocol/param/SaveErase.hpp>
|
||||
#include <uavcan/protocol/param/ExecuteOpcode.hpp>
|
||||
#include <uavcan/protocol/EnumerationRequest.hpp>
|
||||
#include <uavcan/equipment/hardpoint/Command.hpp>
|
||||
|
||||
@@ -88,9 +88,29 @@ std::string paramValueToString(const uavcan::protocol::param::Value& value)
|
||||
{
|
||||
return std::to_string(value.value_float[0]);
|
||||
}
|
||||
else if (!value.value_string.empty())
|
||||
{
|
||||
return std::string(value.value_string[0].value.c_str()) + " ";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "?";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string paramValueToString(const uavcan::protocol::param::NumericValue& value)
|
||||
{
|
||||
if (!value.value_int.empty())
|
||||
{
|
||||
return std::to_string(value.value_int[0]);
|
||||
}
|
||||
else if (!value.value_float.empty())
|
||||
{
|
||||
return std::to_string(value.value_float[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +196,7 @@ const std::map<std::string,
|
||||
else
|
||||
{
|
||||
request.name = args.at(0).c_str();
|
||||
// TODO: add support for string parameters
|
||||
request.value.value_float.push_back(std::stof(args.at(1)));
|
||||
printGetSetResponse(call(*client, node_id, request));
|
||||
}
|
||||
@@ -185,11 +206,11 @@ const std::map<std::string,
|
||||
{
|
||||
"param_save",
|
||||
{
|
||||
"Calls uavcan.protocol.param.SaveErase on a remote node with OPCODE_SAVE",
|
||||
"Calls uavcan.protocol.param.ExecuteOpcode on a remote node with OPCODE_SAVE",
|
||||
[](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>&)
|
||||
{
|
||||
auto client = node->makeBlockingServiceClient<uavcan::protocol::param::SaveErase>();
|
||||
uavcan::protocol::param::SaveErase::Request request;
|
||||
auto client = node->makeBlockingServiceClient<uavcan::protocol::param::ExecuteOpcode>();
|
||||
uavcan::protocol::param::ExecuteOpcode::Request request;
|
||||
request.opcode = request.OPCODE_SAVE;
|
||||
std::cout << call(*client, node_id, request) << std::endl;
|
||||
}
|
||||
@@ -198,11 +219,11 @@ const std::map<std::string,
|
||||
{
|
||||
"param_erase",
|
||||
{
|
||||
"Calls uavcan.protocol.param.SaveErase on a remote node with OPCODE_ERASE",
|
||||
"Calls uavcan.protocol.param.ExecuteOpcode on a remote node with OPCODE_ERASE",
|
||||
[](const uavcan_linux::NodePtr& node, const uavcan::NodeID node_id, const std::vector<std::string>&)
|
||||
{
|
||||
auto client = node->makeBlockingServiceClient<uavcan::protocol::param::SaveErase>();
|
||||
uavcan::protocol::param::SaveErase::Request request;
|
||||
auto client = node->makeBlockingServiceClient<uavcan::protocol::param::ExecuteOpcode>();
|
||||
uavcan::protocol::param::ExecuteOpcode::Request request;
|
||||
request.opcode = request.OPCODE_ERASE;
|
||||
std::cout << call(*client, node_id, request) << std::endl;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <bitset>
|
||||
#include <unordered_map>
|
||||
#include <uavcan_linux/uavcan_linux.hpp>
|
||||
#include <uavcan/protocol/node_status_monitor.hpp>
|
||||
@@ -18,6 +19,7 @@ struct OstreamColorizer
|
||||
Yellow = 33,
|
||||
Blue = 34,
|
||||
Magenta = 35,
|
||||
Cyan = 36,
|
||||
Default = 39
|
||||
};
|
||||
explicit OstreamColorizer(Color color = Default) : color_(color) { }
|
||||
@@ -33,11 +35,11 @@ private:
|
||||
class Monitor : public uavcan::NodeStatusMonitor
|
||||
{
|
||||
uavcan_linux::TimerPtr timer_;
|
||||
std::unordered_map<int, std::uint64_t> uptimes_;
|
||||
std::unordered_map<int, uavcan::protocol::NodeStatus> status_registry_;
|
||||
|
||||
virtual void handleNodeStatusMessage(const uavcan::ReceivedDataStructure<uavcan::protocol::NodeStatus>& msg)
|
||||
{
|
||||
uptimes_[msg.getSrcNodeID().get()] = msg.uptime_sec;
|
||||
status_registry_[msg.getSrcNodeID().get()] = msg;
|
||||
}
|
||||
|
||||
static std::pair<OstreamColorizer, std::string>
|
||||
@@ -49,7 +51,7 @@ class Monitor : public uavcan::NodeStatusMonitor
|
||||
}
|
||||
if (status_code == uavcan::protocol::NodeStatus::STATUS_INITIALIZING)
|
||||
{
|
||||
return { OstreamColorizer(OstreamColorizer::Blue), "INITIALIZING" };
|
||||
return { OstreamColorizer(OstreamColorizer::Cyan), "INITIALIZING" };
|
||||
}
|
||||
if (status_code == uavcan::protocol::NodeStatus::STATUS_WARNING)
|
||||
{
|
||||
@@ -68,20 +70,33 @@ class Monitor : public uavcan::NodeStatusMonitor
|
||||
|
||||
void printStatusLine(uavcan::NodeID nid, const uavcan::NodeStatusMonitor::NodeStatus& status)
|
||||
{
|
||||
const auto original_flags = std::cout.flags();
|
||||
|
||||
const auto color_and_string = statusCodeToColoredString(status.status_code);
|
||||
const int nid_int = nid.get();
|
||||
const auto uptime = status_registry_[nid_int].uptime_sec;
|
||||
const int vendor_code = status_registry_[nid_int].vendor_specific_status_code;
|
||||
|
||||
std::cout << color_and_string.first;
|
||||
std::cout << " " << std::setw(3) << std::left << nid_int << " | "
|
||||
<< std::setw(13) << std::left << color_and_string.second << " | "
|
||||
<< uptimes_[nid_int];
|
||||
std::cout << OstreamColorizer() << "\n";
|
||||
|
||||
std::cout << " " << std::setw(3) << std::left << nid_int << " | " // Node ID
|
||||
<< std::setw(13) << std::left << color_and_string.second << " | " // Status name
|
||||
<< std::setw(12) << uptime << " | " // Uptime
|
||||
<< "0x" << std::hex << std::setw(4) << std::setfill('0') << vendor_code // Vendor, hex
|
||||
<< " 0b" << std::dec << std::bitset<8>((vendor_code >> 8) & 0xFF) // Vendor, bin, high
|
||||
<< "'" << std::bitset<8>(vendor_code & 0xFF) // Vendor, bin, low
|
||||
<< " " << vendor_code; // Vendor, dec
|
||||
|
||||
std::cout << OstreamColorizer() << std::setfill(' ') << "\n";
|
||||
std::cout.width(0);
|
||||
std::cout.flags(original_flags);
|
||||
}
|
||||
|
||||
void redraw(const uavcan::TimerEvent&)
|
||||
{
|
||||
std::cout << "\x1b\x5b\x48" << "\x1b\x5b\x32\x4a"
|
||||
<< " NID | Status | Uptime\n"
|
||||
<< "-----+---------------+--------\n";
|
||||
<< " NID | Status | Uptime (sec) | Vendor-specific status (hex/bin/dec)\n"
|
||||
<< "-----+---------------+--------------+--------------------------------------\n";
|
||||
for (unsigned i = 1; i <= uavcan::NodeID::Max; i++)
|
||||
{
|
||||
const auto s = getNodeStatus(i);
|
||||
|
||||
@@ -183,16 +183,12 @@ class CompoundType(Type):
|
||||
txt = StringIO()
|
||||
txt.write(self.full_name + '\n')
|
||||
adjoin = lambda attrs: txt.write('\n'.join(x.get_normalized_definition() for x in attrs) + '\n')
|
||||
const_sort_key = lambda x: x.get_normalized_definition()
|
||||
if self.kind == CompoundType.KIND_SERVICE:
|
||||
adjoin(self.request_fields)
|
||||
adjoin(sorted(self.request_constants, key=const_sort_key))
|
||||
txt.write('\n---\n')
|
||||
adjoin(self.response_fields)
|
||||
adjoin(sorted(self.response_constants, key=const_sort_key))
|
||||
elif self.kind == CompoundType.KIND_MESSAGE:
|
||||
adjoin(self.fields)
|
||||
adjoin(sorted(self.constants, key=const_sort_key))
|
||||
else:
|
||||
error('Compound type of unknown kind [%s]', self.kind)
|
||||
return txt.getvalue().strip().replace('\n\n\n', '\n').replace('\n\n', '\n')
|
||||
|
||||
Reference in New Issue
Block a user