diff --git a/dsdl/uavcan/equipment/actuator/600.Status.uavcan b/dsdl/uavcan/equipment/actuator/600.Status.uavcan index 16a4125447..ef15e5e395 100644 --- a/dsdl/uavcan/equipment/actuator/600.Status.uavcan +++ b/dsdl/uavcan/equipment/actuator/600.Status.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/actuator/Command.uavcan b/dsdl/uavcan/equipment/actuator/Command.uavcan index 2728d682c3..e4d3d74084 100644 --- a/dsdl/uavcan/equipment/actuator/Command.uavcan +++ b/dsdl/uavcan/equipment/actuator/Command.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/air_data/280.Airspeed.uavcan b/dsdl/uavcan/equipment/air_data/280.Airspeed.uavcan deleted file mode 100644 index ee366fcb55..0000000000 --- a/dsdl/uavcan/equipment/air_data/280.Airspeed.uavcan +++ /dev/null @@ -1,6 +0,0 @@ -# -# True airspeed in meters per second. -# - -float16 true_airspeed -float16 true_airspeed_variance diff --git a/dsdl/uavcan/equipment/air_data/281.AltitudeAndClimbRate.uavcan b/dsdl/uavcan/equipment/air_data/281.AltitudeAndClimbRate.uavcan deleted file mode 100644 index dc43c54aed..0000000000 --- a/dsdl/uavcan/equipment/air_data/281.AltitudeAndClimbRate.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/equipment/air_data/284.StaticAirData.uavcan b/dsdl/uavcan/equipment/air_data/284.StaticAirData.uavcan deleted file mode 100644 index 245218669a..0000000000 --- a/dsdl/uavcan/equipment/air_data/284.StaticAirData.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/equipment/air_data/290.TrueAirspeed.uavcan b/dsdl/uavcan/equipment/air_data/290.TrueAirspeed.uavcan new file mode 100644 index 0000000000..ace10e61cb --- /dev/null +++ b/dsdl/uavcan/equipment/air_data/290.TrueAirspeed.uavcan @@ -0,0 +1,6 @@ +# +# TAS. +# + +float16 true_airspeed # m/s +float16 true_airspeed_variance # (m/s)^2 diff --git a/dsdl/uavcan/equipment/air_data/291.IndicatedAirspeed.uavcan b/dsdl/uavcan/equipment/air_data/291.IndicatedAirspeed.uavcan new file mode 100644 index 0000000000..c11ea903a6 --- /dev/null +++ b/dsdl/uavcan/equipment/air_data/291.IndicatedAirspeed.uavcan @@ -0,0 +1,6 @@ +# +# IAS. +# + +float16 indicated_airspeed # m/s +float16 indicated_airspeed_variance # (m/s)^2 diff --git a/dsdl/uavcan/equipment/air_data/282.AngleOfAttack.uavcan b/dsdl/uavcan/equipment/air_data/295.AngleOfAttack.uavcan similarity index 83% rename from dsdl/uavcan/equipment/air_data/282.AngleOfAttack.uavcan rename to dsdl/uavcan/equipment/air_data/295.AngleOfAttack.uavcan index 89aef90848..c14d7fdcbc 100644 --- a/dsdl/uavcan/equipment/air_data/282.AngleOfAttack.uavcan +++ b/dsdl/uavcan/equipment/air_data/295.AngleOfAttack.uavcan @@ -1,5 +1,5 @@ # -# Angle of attack in radians. +# Angle of attack. # uint8 SENSOR_ID_LEFT = 254 diff --git a/dsdl/uavcan/equipment/air_data/283.Sideslip.uavcan b/dsdl/uavcan/equipment/air_data/296.Sideslip.uavcan similarity index 100% rename from dsdl/uavcan/equipment/air_data/283.Sideslip.uavcan rename to dsdl/uavcan/equipment/air_data/296.Sideslip.uavcan diff --git a/dsdl/uavcan/equipment/air_data/298.StaticPressure.uavcan b/dsdl/uavcan/equipment/air_data/298.StaticPressure.uavcan new file mode 100644 index 0000000000..75d3cc7e06 --- /dev/null +++ b/dsdl/uavcan/equipment/air_data/298.StaticPressure.uavcan @@ -0,0 +1,6 @@ +# +# Static pressure. +# + +float32 static_pressure # Pascal +float16 static_pressure_variance # Pascal^2 diff --git a/dsdl/uavcan/equipment/air_data/410.StaticTemperature.uavcan b/dsdl/uavcan/equipment/air_data/410.StaticTemperature.uavcan new file mode 100644 index 0000000000..7e8d570fe5 --- /dev/null +++ b/dsdl/uavcan/equipment/air_data/410.StaticTemperature.uavcan @@ -0,0 +1,6 @@ +# +# Static temperature. +# + +float16 static_temperature # Kelvin +float16 static_temperature_variance # Kelvin^2 diff --git a/dsdl/uavcan/equipment/camera_gimbal/390.Command.uavcan b/dsdl/uavcan/equipment/camera_gimbal/400.AngularCommand.uavcan similarity index 55% rename from dsdl/uavcan/equipment/camera_gimbal/390.Command.uavcan rename to dsdl/uavcan/equipment/camera_gimbal/400.AngularCommand.uavcan index 36205851ec..98b696947f 100644 --- a/dsdl/uavcan/equipment/camera_gimbal/390.Command.uavcan +++ b/dsdl/uavcan/equipment/camera_gimbal/400.AngularCommand.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/camera_gimbal/401.GEOPOICommand.uavcan b/dsdl/uavcan/equipment/camera_gimbal/401.GEOPOICommand.uavcan new file mode 100644 index 0000000000..83236d52b0 --- /dev/null +++ b/dsdl/uavcan/equipment/camera_gimbal/401.GEOPOICommand.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/camera_gimbal/391.Status.uavcan b/dsdl/uavcan/equipment/camera_gimbal/402.Status.uavcan similarity index 100% rename from dsdl/uavcan/equipment/camera_gimbal/391.Status.uavcan rename to dsdl/uavcan/equipment/camera_gimbal/402.Status.uavcan diff --git a/dsdl/uavcan/equipment/camera_gimbal/Mode.uavcan b/dsdl/uavcan/equipment/camera_gimbal/Mode.uavcan index 383194cb16..2def06dcad 100644 --- a/dsdl/uavcan/equipment/camera_gimbal/Mode.uavcan +++ b/dsdl/uavcan/equipment/camera_gimbal/Mode.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/gnss/300.Fix.uavcan b/dsdl/uavcan/equipment/gnss/300.Fix.uavcan deleted file mode 100644 index 8e3997307e..0000000000 --- a/dsdl/uavcan/equipment/gnss/300.Fix.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/equipment/gnss/420.Fix.uavcan b/dsdl/uavcan/equipment/gnss/420.Fix.uavcan new file mode 100644 index 0000000000..273daaa799 --- /dev/null +++ b/dsdl/uavcan/equipment/gnss/420.Fix.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/gnss/302.Auxiliary.uavcan b/dsdl/uavcan/equipment/gnss/421.Auxiliary.uavcan similarity index 90% rename from dsdl/uavcan/equipment/gnss/302.Auxiliary.uavcan rename to dsdl/uavcan/equipment/gnss/421.Auxiliary.uavcan index 6321bca887..43bb3c56be 100644 --- a/dsdl/uavcan/equipment/gnss/302.Auxiliary.uavcan +++ b/dsdl/uavcan/equipment/gnss/421.Auxiliary.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/hardpoint/700.Command.uavcan b/dsdl/uavcan/equipment/hardpoint/660.Command.uavcan similarity index 100% rename from dsdl/uavcan/equipment/hardpoint/700.Command.uavcan rename to dsdl/uavcan/equipment/hardpoint/660.Command.uavcan diff --git a/dsdl/uavcan/equipment/hardpoint/701.Status.uavcan b/dsdl/uavcan/equipment/hardpoint/661.Status.uavcan similarity index 100% rename from dsdl/uavcan/equipment/hardpoint/701.Status.uavcan rename to dsdl/uavcan/equipment/hardpoint/661.Status.uavcan diff --git a/dsdl/uavcan/equipment/indication/742.BeepCommand.uavcan b/dsdl/uavcan/equipment/indication/747.BeepCommand.uavcan similarity index 100% rename from dsdl/uavcan/equipment/indication/742.BeepCommand.uavcan rename to dsdl/uavcan/equipment/indication/747.BeepCommand.uavcan diff --git a/dsdl/uavcan/equipment/indication/743.LightsCommand.uavcan b/dsdl/uavcan/equipment/indication/748.LightsCommand.uavcan similarity index 100% rename from dsdl/uavcan/equipment/indication/743.LightsCommand.uavcan rename to dsdl/uavcan/equipment/indication/748.LightsCommand.uavcan diff --git a/dsdl/uavcan/equipment/optical_flow/291.OpticalFlow.uavcan b/dsdl/uavcan/equipment/optical_flow/291.OpticalFlow.uavcan deleted file mode 100644 index c6089fe696..0000000000 --- a/dsdl/uavcan/equipment/optical_flow/291.OpticalFlow.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/equipment/power/710.PrimaryPowerSupplyStatus.uavcan b/dsdl/uavcan/equipment/power/720.PrimaryPowerSupplyStatus.uavcan similarity index 100% rename from dsdl/uavcan/equipment/power/710.PrimaryPowerSupplyStatus.uavcan rename to dsdl/uavcan/equipment/power/720.PrimaryPowerSupplyStatus.uavcan diff --git a/dsdl/uavcan/equipment/power/711.CircuitStatus.uavcan b/dsdl/uavcan/equipment/power/721.CircuitStatus.uavcan similarity index 100% rename from dsdl/uavcan/equipment/power/711.CircuitStatus.uavcan rename to dsdl/uavcan/equipment/power/721.CircuitStatus.uavcan diff --git a/dsdl/uavcan/equipment/power/712.BatteryInfo.uavcan b/dsdl/uavcan/equipment/power/722.BatteryInfo.uavcan similarity index 88% rename from dsdl/uavcan/equipment/power/712.BatteryInfo.uavcan rename to dsdl/uavcan/equipment/power/722.BatteryInfo.uavcan index 0da83846e1..64d1a4da87 100644 --- a/dsdl/uavcan/equipment/power/712.BatteryInfo.uavcan +++ b/dsdl/uavcan/equipment/power/722.BatteryInfo.uavcan @@ -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 diff --git a/dsdl/uavcan/equipment/range_sensor/290.AltitudeAGL.uavcan b/dsdl/uavcan/equipment/range_sensor/290.AltitudeAGL.uavcan deleted file mode 100644 index 7ff1af2766..0000000000 --- a/dsdl/uavcan/equipment/range_sensor/290.AltitudeAGL.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/equipment/range_sensor/292.RangeMeasurement.uavcan b/dsdl/uavcan/equipment/range_sensor/292.RangeMeasurement.uavcan deleted file mode 100644 index ab5d6b240d..0000000000 --- a/dsdl/uavcan/equipment/range_sensor/292.RangeMeasurement.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/equipment/range_sensor/380.RangeMeasurement.uavcan b/dsdl/uavcan/equipment/range_sensor/380.RangeMeasurement.uavcan new file mode 100644 index 0000000000..b90d1a984a --- /dev/null +++ b/dsdl/uavcan/equipment/range_sensor/380.RangeMeasurement.uavcan @@ -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 diff --git a/dsdl/uavcan/nav/540.AttitudeThrustCommand.uavcan b/dsdl/uavcan/nav/540.AttitudeThrustCommand.uavcan deleted file mode 100644 index cd4ce9ab50..0000000000 --- a/dsdl/uavcan/nav/540.AttitudeThrustCommand.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/protocol/0.GlobalTimeSync.uavcan b/dsdl/uavcan/protocol/0.GlobalTimeSync.uavcan index d85fd3232b..40e3dd472b 100644 --- a/dsdl/uavcan/protocol/0.GlobalTimeSync.uavcan +++ b/dsdl/uavcan/protocol/0.GlobalTimeSync.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/550.NodeStatus.uavcan b/dsdl/uavcan/protocol/550.NodeStatus.uavcan index 0d777fc759..f3c42c6cbc 100644 --- a/dsdl/uavcan/protocol/550.NodeStatus.uavcan +++ b/dsdl/uavcan/protocol/550.NodeStatus.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/551.GetNodeInfo.uavcan b/dsdl/uavcan/protocol/551.GetNodeInfo.uavcan index 9360d59561..110cc2f4c9 100644 --- a/dsdl/uavcan/protocol/551.GetNodeInfo.uavcan +++ b/dsdl/uavcan/protocol/551.GetNodeInfo.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/560.RestartNode.uavcan b/dsdl/uavcan/protocol/560.RestartNode.uavcan index b4f4672da0..fea950ab23 100644 --- a/dsdl/uavcan/protocol/560.RestartNode.uavcan +++ b/dsdl/uavcan/protocol/560.RestartNode.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/debug/1022.KeyValue.uavcan b/dsdl/uavcan/protocol/debug/1022.KeyValue.uavcan index be9668cfaf..cd4668e7f7 100644 --- a/dsdl/uavcan/protocol/debug/1022.KeyValue.uavcan +++ b/dsdl/uavcan/protocol/debug/1022.KeyValue.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/debug/1022.StartHILSimulation.uavcan b/dsdl/uavcan/protocol/debug/1022.StartHILSimulation.uavcan index c132bcab29..c76ac61593 100644 --- a/dsdl/uavcan/protocol/debug/1022.StartHILSimulation.uavcan +++ b/dsdl/uavcan/protocol/debug/1022.StartHILSimulation.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/file/Path.uavcan b/dsdl/uavcan/protocol/file/Path.uavcan index 8a30feb0be..c89b77b1e5 100644 --- a/dsdl/uavcan/protocol/file/Path.uavcan +++ b/dsdl/uavcan/protocol/file/Path.uavcan @@ -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 = '/' diff --git a/dsdl/uavcan/protocol/param/598.ExecuteOpcode.uavcan b/dsdl/uavcan/protocol/param/598.ExecuteOpcode.uavcan new file mode 100644 index 0000000000..626fb79c65 --- /dev/null +++ b/dsdl/uavcan/protocol/param/598.ExecuteOpcode.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/param/598.SaveErase.uavcan b/dsdl/uavcan/protocol/param/598.SaveErase.uavcan deleted file mode 100644 index 4d4d933fd4..0000000000 --- a/dsdl/uavcan/protocol/param/598.SaveErase.uavcan +++ /dev/null @@ -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 diff --git a/dsdl/uavcan/protocol/param/599.GetSet.uavcan b/dsdl/uavcan/protocol/param/599.GetSet.uavcan index 73f5d74dab..296b91266d 100644 --- a/dsdl/uavcan/protocol/param/599.GetSet.uavcan +++ b/dsdl/uavcan/protocol/param/599.GetSet.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/param/NumericValue.uavcan b/dsdl/uavcan/protocol/param/NumericValue.uavcan new file mode 100644 index 0000000000..76d782f9a0 --- /dev/null +++ b/dsdl/uavcan/protocol/param/NumericValue.uavcan @@ -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 diff --git a/dsdl/uavcan/protocol/param/String.uavcan b/dsdl/uavcan/protocol/param/String.uavcan new file mode 100644 index 0000000000..e5e42bfb5c --- /dev/null +++ b/dsdl/uavcan/protocol/param/String.uavcan @@ -0,0 +1,5 @@ +# +# This type is nested in Value. +# + +uint8[<=127] value diff --git a/dsdl/uavcan/protocol/param/Value.uavcan b/dsdl/uavcan/protocol/param/Value.uavcan index 083db54bdf..5a47150eff 100644 --- a/dsdl/uavcan/protocol/param/Value.uavcan +++ b/dsdl/uavcan/protocol/param/Value.uavcan @@ -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 diff --git a/dsdl/uavcan/ranges b/dsdl/uavcan/ranges index b44ae3f110..5af05b409f 100644 --- a/dsdl/uavcan/ranges +++ b/dsdl/uavcan/ranges @@ -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 diff --git a/libuavcan/include/uavcan/build_config.hpp b/libuavcan/include/uavcan/build_config.hpp index fac52be812..13a6725f4d 100644 --- a/libuavcan/include/uavcan/build_config.hpp +++ b/libuavcan/include/uavcan/build_config.hpp @@ -123,7 +123,6 @@ #if UAVCAN_TOSTRING # include -# include #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. diff --git a/libuavcan/include/uavcan/data_type.hpp b/libuavcan/include/uavcan/data_type.hpp index 8e47751647..323b6f8a18 100644 --- a/libuavcan/include/uavcan/data_type.hpp +++ b/libuavcan/include/uavcan/data_type.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include diff --git a/libuavcan/include/uavcan/driver/can.hpp b/libuavcan/include/uavcan/driver/can.hpp index ad77abfcf7..3fca51c9ed 100644 --- a/libuavcan/include/uavcan/driver/can.hpp +++ b/libuavcan/include/uavcan/driver/can.hpp @@ -7,7 +7,7 @@ #define UAVCAN_DRIVER_CAN_HPP_INCLUDED #include -#include +#include #include #include diff --git a/libuavcan/include/uavcan/driver/system_clock.hpp b/libuavcan/include/uavcan/driver/system_clock.hpp index 22055b457e..1939e5d553 100644 --- a/libuavcan/include/uavcan/driver/system_clock.hpp +++ b/libuavcan/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 +#include #include #include diff --git a/libuavcan/include/uavcan/dynamic_memory.hpp b/libuavcan/include/uavcan/dynamic_memory.hpp index 7c0ffb2038..813d5480be 100644 --- a/libuavcan/include/uavcan/dynamic_memory.hpp +++ b/libuavcan/include/uavcan/dynamic_memory.hpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -157,7 +157,6 @@ bool PoolManager::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; } diff --git a/libuavcan/include/uavcan/error.hpp b/libuavcan/include/uavcan/error.hpp index 1cbeafcc22..bce8b4ed00 100644 --- a/libuavcan/include/uavcan/error.hpp +++ b/libuavcan/include/uavcan/error.hpp @@ -6,7 +6,7 @@ #define UAVCAN_ERROR_HPP_INCLUDED #include -#include +#include namespace uavcan { diff --git a/libuavcan/include/uavcan/helpers/component_status_manager.hpp b/libuavcan/include/uavcan/helpers/component_status_manager.hpp index 78d700b758..f33da0a583 100644 --- a/libuavcan/include/uavcan/helpers/component_status_manager.hpp +++ b/libuavcan/include/uavcan/helpers/component_status_manager.hpp @@ -6,7 +6,7 @@ #define UAVCAN_HELPERS_COMPONENT_STATUS_MANAGER_HPP_INCLUDED #include -#include +#include #include namespace uavcan diff --git a/libuavcan/include/uavcan/marshal/array.hpp b/libuavcan/include/uavcan/marshal/array.hpp index 70f1c27d97..67d5ee41d0 100644 --- a/libuavcan/include/uavcan/marshal/array.hpp +++ b/libuavcan/include/uavcan/marshal/array.hpp @@ -15,6 +15,7 @@ #include #include #include +#include #ifndef UAVCAN_CPP_VERSION # error UAVCAN_CPP_VERSION @@ -714,7 +715,8 @@ public: StaticAssert::check(); StaticAssert= A(0))>::check(); // This check allows to weed out most compound types - StaticAssert::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(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::check(); + + for (SizeType i = 0; i < size(); i++) + { + const int x = Base::at(i); + if ((x <= 'z') && (x >= 'a')) + { + Base::at(i) = static_cast(x + ('Z' - 'z')); + } + } + } + + void convertToLowerCaseASCII() + { + StaticAssert::check(); + + for (SizeType i = 0; i < size(); i++) + { + const int x = Base::at(i); + if ((x <= 'Z') && (x >= 'A')) + { + Base::at(i) = static_cast(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. diff --git a/libuavcan/include/uavcan/marshal/bit_stream.hpp b/libuavcan/include/uavcan/marshal/bit_stream.hpp index b7504112ec..1ac9fe400c 100644 --- a/libuavcan/include/uavcan/marshal/bit_stream.hpp +++ b/libuavcan/include/uavcan/marshal/bit_stream.hpp @@ -6,7 +6,7 @@ #define UAVCAN_MARSHAL_BIT_STREAM_HPP_INCLUDED #include -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/marshal/float_spec.hpp b/libuavcan/include/uavcan/marshal/float_spec.hpp index ab0063056a..b77328f44a 100644 --- a/libuavcan/include/uavcan/marshal/float_spec.hpp +++ b/libuavcan/include/uavcan/marshal/float_spec.hpp @@ -6,7 +6,7 @@ #define UAVCAN_MARSHAL_FLOAT_SPEC_HPP_INCLUDED #include -#include +#include #include #include #include @@ -16,9 +16,7 @@ #ifndef UAVCAN_CPP_VERSION # error UAVCAN_CPP_VERSION #endif -#if UAVCAN_CPP_VERSION < UAVCAN_CPP11 -# include // Needed for isfinite() -#else +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 # include // 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()) { diff --git a/libuavcan/include/uavcan/marshal/integer_spec.hpp b/libuavcan/include/uavcan/marshal/integer_spec.hpp index 2a74218581..b7424310db 100644 --- a/libuavcan/include/uavcan/marshal/integer_spec.hpp +++ b/libuavcan/include/uavcan/marshal/integer_spec.hpp @@ -5,7 +5,7 @@ #ifndef UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED #define UAVCAN_MARSHAL_INTEGER_SPEC_HPP_INCLUDED -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/marshal/scalar_codec.hpp b/libuavcan/include/uavcan/marshal/scalar_codec.hpp index b46c1b16bb..2690f6e1d6 100644 --- a/libuavcan/include/uavcan/marshal/scalar_codec.hpp +++ b/libuavcan/include/uavcan/marshal/scalar_codec.hpp @@ -6,7 +6,7 @@ #define UAVCAN_MARSHAL_SCALAR_CODEC_HPP_INCLUDED #include -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/node/global_data_type_registry.hpp b/libuavcan/include/uavcan/node/global_data_type_registry.hpp index 7e27d92886..d7f837c199 100644 --- a/libuavcan/include/uavcan/node/global_data_type_registry.hpp +++ b/libuavcan/include/uavcan/node/global_data_type_registry.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/node/node.hpp b/libuavcan/include/uavcan/node/node.hpp index c04bf1103b..a3e88ff829 100644 --- a/libuavcan/include/uavcan/node/node.hpp +++ b/libuavcan/include/uavcan/node/node.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. */ diff --git a/libuavcan/include/uavcan/node/timer.hpp b/libuavcan/include/uavcan/node/timer.hpp index 1521489f99..13fc4f5ed9 100644 --- a/libuavcan/include/uavcan/node/timer.hpp +++ b/libuavcan/include/uavcan/node/timer.hpp @@ -5,7 +5,7 @@ #ifndef UAVCAN_NODE_TIMER_HPP_INCLUDED #define UAVCAN_NODE_TIMER_HPP_INCLUDED -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/protocol/node_status_monitor.hpp b/libuavcan/include/uavcan/protocol/node_status_monitor.hpp index 0cf829a63a..e9028e37b9 100644 --- a/libuavcan/include/uavcan/protocol/node_status_monitor.hpp +++ b/libuavcan/include/uavcan/protocol/node_status_monitor.hpp @@ -46,7 +46,12 @@ private: void (NodeStatusMonitor::*)(const ReceivedDataStructure&)> NodeStatusCallback; - Subscriber sub_; + /* + * We'll be able to handle this many nodes in the network without any dynamic memory. + */ + enum { NumStaticReceivers = 64 }; + + Subscriber sub_; struct Entry { diff --git a/libuavcan/include/uavcan/protocol/node_status_provider.hpp b/libuavcan/include/uavcan/protocol/node_status_provider.hpp index 524dd43c35..6b06fa76dd 100644 --- a/libuavcan/include/uavcan/protocol/node_status_provider.hpp +++ b/libuavcan/include/uavcan/protocol/node_status_provider.hpp @@ -49,6 +49,9 @@ class UAVCAN_EXPORT NodeStatusProvider : private TimerBase void handleGetNodeInfoRequest(const protocol::GetNodeInfo::Request&, protocol::GetNodeInfo::Response& rsp); public: + typedef typename StorageType::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. diff --git a/libuavcan/include/uavcan/protocol/param_server.hpp b/libuavcan/include/uavcan/protocol/param_server.hpp index f0292198a2..8f7bdef5e0 100644 --- a/libuavcan/include/uavcan/protocol/param_server.hpp +++ b/libuavcan/include/uavcan/protocol/param_server.hpp @@ -6,7 +6,7 @@ #define UAVCAN_PROTOCOL_PARAM_SERVER_HPP_INCLUDED #include -#include +#include #include #include @@ -19,33 +19,35 @@ namespace uavcan class UAVCAN_EXPORT IParamManager { public: - typedef typename StorageType::Type ParamName; - typedef typename StorageType::Type ParamIndex; - typedef protocol::param::Value ParamValue; + typedef typename StorageType::Type Name; + typedef typename StorageType::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 GetSetCallback; - typedef MethodBinder SaveEraseCallback; + typedef MethodBinder ExecuteOpcodeCallback; ServiceServer get_set_srv_; - ServiceServer save_erase_srv_; + ServiceServer 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) diff --git a/libuavcan/include/uavcan/std.hpp b/libuavcan/include/uavcan/std.hpp new file mode 100644 index 0000000000..c04ced0c89 --- /dev/null +++ b/libuavcan/include/uavcan/std.hpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#ifndef UAVCAN_STD_HPP_INCLUDED +#define UAVCAN_STD_HPP_INCLUDED + +#include +#include + +#if !defined(UAVCAN_CPP_VERSION) || !defined(UAVCAN_CPP11) +# error UAVCAN_CPP_VERSION +#endif + +#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 + +# include +# include + +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 // Standard integer types from C library +# include // 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 diff --git a/libuavcan/include/uavcan/stdint.hpp b/libuavcan/include/uavcan/stdint.hpp deleted file mode 100644 index 4fc668a2a7..0000000000 --- a/libuavcan/include/uavcan/stdint.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2014 Pavel Kirienko - */ - -#ifndef UAVCAN_STDINT_HPP_INCLUDED -#define UAVCAN_STDINT_HPP_INCLUDED - -#include - -#if !defined(UAVCAN_CPP_VERSION) || !defined(UAVCAN_CPP11) -# error UAVCAN_CPP_VERSION -#endif - -#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 - -# include - -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 - -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 diff --git a/libuavcan/include/uavcan/time.hpp b/libuavcan/include/uavcan/time.hpp index 094016fb35..39528b045b 100644 --- a/libuavcan/include/uavcan/time.hpp +++ b/libuavcan/include/uavcan/time.hpp @@ -6,7 +6,7 @@ #define UAVCAN_TIME_HPP_INCLUDED #include -#include +#include #include #include #include @@ -223,7 +223,6 @@ const unsigned TimeBase::StringBufSize; template void DurationBase::toString(char buf[StringBufSize]) const { - using namespace std; // For snprintf() char* ptr = buf; if (isNegative()) { @@ -238,7 +237,6 @@ void DurationBase::toString(char buf[StringBufSize]) const template void TimeBase::toString(char buf[StringBufSize]) const { - using namespace std; // For snprintf() (void)snprintf(buf, StringBufSize, "%llu.%06lu", static_cast(toUSec() / 1000000UL), static_cast(toUSec() % 1000000UL)); diff --git a/libuavcan/include/uavcan/transport/abstract_transfer_buffer.hpp b/libuavcan/include/uavcan/transport/abstract_transfer_buffer.hpp index 7cc703c4c2..e4a276d1ce 100644 --- a/libuavcan/include/uavcan/transport/abstract_transfer_buffer.hpp +++ b/libuavcan/include/uavcan/transport/abstract_transfer_buffer.hpp @@ -6,7 +6,7 @@ #define UAVCAN_TRANSPORT_ABSTRACT_TRANSFER_BUFFER_HPP_INCLUDED #include -#include +#include namespace uavcan { diff --git a/libuavcan/include/uavcan/transport/can_io.hpp b/libuavcan/include/uavcan/transport/can_io.hpp index cee418569d..867407d056 100644 --- a/libuavcan/include/uavcan/transport/can_io.hpp +++ b/libuavcan/include/uavcan/transport/can_io.hpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/transport/crc.hpp b/libuavcan/include/uavcan/transport/crc.hpp index abee099522..aae2c4d964 100644 --- a/libuavcan/include/uavcan/transport/crc.hpp +++ b/libuavcan/include/uavcan/transport/crc.hpp @@ -6,7 +6,7 @@ #define UAVCAN_TRANSPORT_CRC_HPP_INCLUDED #include -#include +#include #include namespace uavcan diff --git a/libuavcan/include/uavcan/transport/dispatcher.hpp b/libuavcan/include/uavcan/transport/dispatcher.hpp index a34789bf36..ac12bbd2b7 100644 --- a/libuavcan/include/uavcan/transport/dispatcher.hpp +++ b/libuavcan/include/uavcan/transport/dispatcher.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/transport/outgoing_transfer_registry.hpp b/libuavcan/include/uavcan/transport/outgoing_transfer_registry.hpp index 9d91ac1955..114cecee22 100644 --- a/libuavcan/include/uavcan/transport/outgoing_transfer_registry.hpp +++ b/libuavcan/include/uavcan/transport/outgoing_transfer_registry.hpp @@ -6,7 +6,7 @@ #define UAVCAN_TRANSPORT_OUTGOING_TRANSFER_REGISTRY_HPP_INCLUDED #include -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/transport/perf_counter.hpp b/libuavcan/include/uavcan/transport/perf_counter.hpp index 009dfeec81..58861897bd 100644 --- a/libuavcan/include/uavcan/transport/perf_counter.hpp +++ b/libuavcan/include/uavcan/transport/perf_counter.hpp @@ -5,7 +5,7 @@ #ifndef UAVCAN_TRANSPORT_PERF_COUNTER_HPP_INCLUDED #define UAVCAN_TRANSPORT_PERF_COUNTER_HPP_INCLUDED -#include +#include #include namespace uavcan diff --git a/libuavcan/include/uavcan/transport/transfer.hpp b/libuavcan/include/uavcan/transport/transfer.hpp index d5c3f8268f..50255fe37c 100644 --- a/libuavcan/include/uavcan/transport/transfer.hpp +++ b/libuavcan/include/uavcan/transport/transfer.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include namespace uavcan { diff --git a/libuavcan/include/uavcan/transport/transfer_buffer.hpp b/libuavcan/include/uavcan/transport/transfer_buffer.hpp index d29bcce9ed..0911f106e4 100644 --- a/libuavcan/include/uavcan/transport/transfer_buffer.hpp +++ b/libuavcan/include/uavcan/transport/transfer_buffer.hpp @@ -5,7 +5,7 @@ #ifndef UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED #define UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/transport/transfer_listener.hpp b/libuavcan/include/uavcan/transport/transfer_listener.hpp index a8210821ce..e71d50f1e3 100644 --- a/libuavcan/include/uavcan/transport/transfer_listener.hpp +++ b/libuavcan/include/uavcan/transport/transfer_listener.hpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include diff --git a/libuavcan/include/uavcan/util/templates.hpp b/libuavcan/include/uavcan/util/templates.hpp index e25102790d..e2572ff3d3 100644 --- a/libuavcan/include/uavcan/util/templates.hpp +++ b/libuavcan/include/uavcan/util/templates.hpp @@ -470,6 +470,20 @@ inline bool isInfinity(T arg) #endif } +/** + * Replacement for std::isfinite(). + * Note that direct float comparison (==, !=) is intentionally avoided. + */ +template +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. diff --git a/libuavcan/src/driver/uc_can.cpp b/libuavcan/src/driver/uc_can.cpp index ed5723eecd..739740343b 100644 --- a/libuavcan/src/driver/uc_can.cpp +++ b/libuavcan/src/driver/uc_can.cpp @@ -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; diff --git a/libuavcan/src/protocol/uc_global_time_sync_master.cpp b/libuavcan/src/protocol/uc_global_time_sync_master.cpp index 8f45c43c1a..8825c1ba85 100644 --- a/libuavcan/src/protocol/uc_global_time_sync_master.cpp +++ b/libuavcan/src/protocol/uc_global_time_sync_master.cpp @@ -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(msg.prev_utc_usec), int(iface_index_), int(tid.get())); + static_cast(msg.previous_transmission_timestamp_usec), + int(iface_index_), int(tid.get())); return pub_.broadcast(msg, tid); } diff --git a/libuavcan/src/protocol/uc_global_time_sync_slave.cpp b/libuavcan/src/protocol/uc_global_time_sync_slave.cpp index 67fe307efe..5a52ee29ae 100644 --- a/libuavcan/src/protocol/uc_global_time_sync_slave.cpp +++ b/libuavcan/src/protocol/uc_global_time_sync_slave.cpp @@ -11,8 +11,8 @@ namespace uavcan void GlobalTimeSyncSlave::adjustFromMsg(const ReceivedDataStructure& 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(adjustment.toUSec()), @@ -58,7 +58,7 @@ void GlobalTimeSyncSlave::processMsg(const ReceivedDataStructure protocol::GlobalTimeSync::MAX_PUBLICATION_PERIOD_MS; if (msg_invalid || wrong_tid || wrong_timing) diff --git a/libuavcan/src/protocol/uc_node_status_provider.cpp b/libuavcan/src/protocol/uc_node_status_provider.cpp index 7a6425684e..d83b48f191 100644 --- a/libuavcan/src/protocol/uc_node_status_provider.cpp +++ b/libuavcan/src/protocol/uc_node_status_provider.cpp @@ -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())) diff --git a/libuavcan/src/protocol/uc_param_server.cpp b/libuavcan/src/protocol/uc_param_server.cpp index 0096239fa0..908400af91 100644 --- a/libuavcan/src/protocol/uc_param_server.cpp +++ b/libuavcan/src/protocol/uc_param_server.cpp @@ -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(); diff --git a/libuavcan/src/transport/uc_frame.cpp b/libuavcan/src/transport/uc_frame.cpp index 510b60e6e3..3a3938a01b 100644 --- a/libuavcan/src/transport/uc_frame.cpp +++ b/libuavcan/src/transport/uc_frame.cpp @@ -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 diff --git a/libuavcan/src/transport/uc_outgoing_transfer_registry.cpp b/libuavcan/src/transport/uc_outgoing_transfer_registry.cpp index 8054b7f9e0..66cb4a5ad8 100644 --- a/libuavcan/src/transport/uc_outgoing_transfer_registry.cpp +++ b/libuavcan/src/transport/uc_outgoing_transfer_registry.cpp @@ -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())); diff --git a/libuavcan/src/transport/uc_transfer_buffer.cpp b/libuavcan/src/transport/uc_transfer_buffer.cpp index 4a56b75632..fb3774c7d9 100644 --- a/libuavcan/src/transport/uc_transfer_buffer.cpp +++ b/libuavcan/src/transport/uc_transfer_buffer.cpp @@ -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); diff --git a/libuavcan/src/uc_data_type.cpp b/libuavcan/src/uc_data_type.cpp index 1e0453eb15..184d6dc610 100644 --- a/libuavcan/src/uc_data_type.cpp +++ b/libuavcan/src/uc_data_type.cpp @@ -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(id_.get()), kindch, static_cast(signature_.get())); diff --git a/libuavcan/test/data_type.cpp b/libuavcan/test/data_type.cpp index e3c6508b53..4d849076eb 100644 --- a/libuavcan/test/data_type.cpp +++ b/libuavcan/test/data_type.cpp @@ -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()); } diff --git a/libuavcan/test/dsdl_test/dsdl_test.cpp b/libuavcan/test/dsdl_test/dsdl_test.cpp index ee582e18ed..96c99d2f2d 100644 --- a/libuavcan/test/dsdl_test/dsdl_test.cpp +++ b/libuavcan/test/dsdl_test/dsdl_test.cpp @@ -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); } diff --git a/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp b/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp index d1671c4ef5..852f79a208 100644 --- a/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp +++ b/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp @@ -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" diff --git a/libuavcan/test/marshal/array.cpp b/libuavcan/test/marshal/array.cpp index e0402ec0cc..f3dfebb3ad 100644 --- a/libuavcan/test/marshal/array.cpp +++ b/libuavcan/test/marshal/array.cpp @@ -1278,3 +1278,21 @@ TEST(Array, FuzzyComparison) uavcan::YamlStreamer::stream(std::cout, array_d64, 0); std::cout << std::endl; } + +TEST(Array, CaseConversion) +{ + Array, 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()); +} diff --git a/libuavcan/test/protocol/global_time_sync_slave.cpp b/libuavcan/test/protocol/global_time_sync_slave.cpp index dbfde47502..5bb2e91c0d 100644 --- a/libuavcan/test/protocol/global_time_sync_slave.cpp +++ b/libuavcan/test/protocol/global_time_sync_slave.cpp @@ -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()); diff --git a/libuavcan/test/protocol/node_status_monitor.cpp b/libuavcan/test/protocol/node_status_monitor.cpp index 3a2db1394b..bfb97b0053 100644 --- a/libuavcan/test/protocol/node_status_monitor.cpp +++ b/libuavcan/test/protocol/node_status_monitor.cpp @@ -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 diff --git a/libuavcan/test/protocol/node_status_provider.cpp b/libuavcan/test/protocol/node_status_provider.cpp index eaa160b6e1..31c4e5cc20 100644 --- a/libuavcan/test/protocol/node_status_provider.cpp +++ b/libuavcan/test/protocol/node_status_provider.cpp @@ -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); /* diff --git a/libuavcan/test/protocol/param_server.cpp b/libuavcan/test/protocol/param_server.cpp index dd65bb5c9e..245864a83f 100644 --- a/libuavcan/test/protocol/param_server.cpp +++ b/libuavcan/test/protocol/param_server.cpp @@ -12,9 +12,9 @@ struct ParamServerTestManager : public uavcan::IParamManager typedef std::map 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 _reg1; - uavcan::DefaultDataTypeRegistrator _reg2; + uavcan::DefaultDataTypeRegistrator _reg2; ASSERT_LE(0, server.start(&mgr)); ServiceClientWithCollector get_set_cln(nodes.b); - ServiceClientWithCollector save_erase_cln(nodes.b); + ServiceClientWithCollector 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]); diff --git a/libuavcan_drivers/linux/apps/test_node.cpp b/libuavcan_drivers/linux/apps/test_node.cpp index 2241f246ca..4bd4eb872f 100644 --- a/libuavcan_drivers/linux/apps/test_node.cpp +++ b/libuavcan_drivers/linux/apps/test_node.cpp @@ -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::rand())); // Setting to an arbitrary value }; auto timer = node->makeTimer(uavcan::MonotonicDuration::fromMSec(60000), do_nothing_once_a_minute); diff --git a/libuavcan_drivers/linux/apps/uavcan_nodetool.cpp b/libuavcan_drivers/linux/apps/uavcan_nodetool.cpp index 822144701b..2c2d60ae42 100644 --- a/libuavcan_drivers/linux/apps/uavcan_nodetool.cpp +++ b/libuavcan_drivers/linux/apps/uavcan_nodetool.cpp @@ -14,7 +14,7 @@ #include "debug.hpp" #include -#include +#include #include #include @@ -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&) { - auto client = node->makeBlockingServiceClient(); - uavcan::protocol::param::SaveErase::Request request; + auto client = node->makeBlockingServiceClient(); + 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&) { - auto client = node->makeBlockingServiceClient(); - uavcan::protocol::param::SaveErase::Request request; + auto client = node->makeBlockingServiceClient(); + uavcan::protocol::param::ExecuteOpcode::Request request; request.opcode = request.OPCODE_ERASE; std::cout << call(*client, node_id, request) << std::endl; } diff --git a/libuavcan_drivers/linux/apps/uavcan_status_monitor.cpp b/libuavcan_drivers/linux/apps/uavcan_status_monitor.cpp index c8374ded0d..540c68dce6 100644 --- a/libuavcan_drivers/linux/apps/uavcan_status_monitor.cpp +++ b/libuavcan_drivers/linux/apps/uavcan_status_monitor.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -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 uptimes_; + std::unordered_map status_registry_; virtual void handleNodeStatusMessage(const uavcan::ReceivedDataStructure& msg) { - uptimes_[msg.getSrcNodeID().get()] = msg.uptime_sec; + status_registry_[msg.getSrcNodeID().get()] = msg; } static std::pair @@ -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); diff --git a/pyuavcan/pyuavcan/dsdl/parser.py b/pyuavcan/pyuavcan/dsdl/parser.py index e27da2eafd..7a10c822ff 100644 --- a/pyuavcan/pyuavcan/dsdl/parser.py +++ b/pyuavcan/pyuavcan/dsdl/parser.py @@ -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')