---json
{"name": "Standard messages and mappings"}
---
====== Standard messages, scalar fallbacks and descriptor mappings ======
The host driver turns decoded Axiom measurements into ROS messages. Use a semantic message such as ''sensor_msgs/msg/Illuminance'' when the quantity is known, or a scalar topic when no supported semantic adapter applies. The generic ''sample'' and ''data'' outputs remain available for full decoded values and validity.
Complete [[:axiom:ros2:getting_started|Install and connect]] and leave the host driver acquiring. These instructions apply to USB and Wi-Fi host-driver connections. Sensors must have a supported firmware profile; ROS output mappings do not install a sensor driver or introduce a custom binary decoder.
===== Availability =====
Illuminance and scalar fallbacks are included in the published ''main'' source from [[https://github.com/robotical/axiom-ros2/commit/2e0c1f6adab4f68263629cbe70eac0684d8e6494|commit 2e0c1f6]] onward. After updating source, rebuild, source the workspace and restart affected ROS processes as described in [[:axiom:ros2:getting_started#install_and_build|Install and build]]. An old installed driver does not gain new outputs merely by importing a viewer layout.
**Optional descriptor mappings are a development preview as of 16 October 2026.** The ''ros.version: 1'' implementation described below is not yet committed or pushed to the published ''main'' branch. It requires a driver checkout containing that implementation; an ordinary pull of ''main'' currently supplies Illuminance/scalar fallbacks but does not interpret the optional block. The normal sensor outputs work without it. This page separates the available defaults from that preview so the schema can be reviewed without implying it is already released.
===== Find the actual outputs =====
In a terminal with the same ROS environment, domain and middleware as the driver:
ros2 topic list -t --no-daemon
BOARD_NS='PASTE_DISCOVERED_BOARD_NAMESPACE_HERE'
ros2 topic echo "$BOARD_NS/devices" std_msgs/msg/String \
--qos-reliability reliable --qos-durability transient_local \
--qos-depth 1 --full-length --once
Replace ''BOARD_NS'' with the complete namespace from ''/axiom_discovery/boards'', including its leading slash. Variables are local to the terminal where you set them. The board inventory's ''topic'' is a relative sensor root. ''public_topics[group][suffix]'' gives its actually published relative outputs; prepend the board namespace to use them as full ROS paths. Unresolved rows have ''topic: null''.
The parallel ''output_info[group][suffix]'' map records each published canonical output's ''message_type'' and ''unit''. For example, this is an excerpt from a resolved LTR-390 row, using an illustrative bus/address:
{
"topic": "ltr_2d390_b1_53",
"public_topics": {
"x": {
"ambient": "ltr_2d390_b1_53/ambient",
"UVI": "ltr_2d390_b1_53/UVI"
}
},
"output_info": {
"x": {
"ambient": {"message_type": "sensor_msgs/msg/Illuminance", "unit": "lux"},
"UVI": {"message_type": "std_msgs/msg/Float64", "unit": "index"}
}
}
}
The full row also includes generic outputs and device identity/state fields. Group ''x'' is the ordinary payload group; other groups have separate paths. A ''null'' unit means unspecified/unitless or no single measurement unit, for example an IMU with several physical quantities. Outputs appear after their first published sample and retire with their publishers. Alias paths are listed separately; an alias that reserves a canonical path can suppress that canonical output. See [[:axiom:ros2:sensors_and_boards|sensor names, lifetime and aliases]].
===== Illuminance and LTR-390 =====
With the existing LTR-390 descriptor, ''ambient'' publishes ''sensor_msgs/msg/Illuminance'' in lux and ''UVI'' publishes ''std_msgs/msg/Float64'' in the descriptor's ''index'' unit. No optional ROS block is needed. Attribute case is retained: ''UVI'' and ''uvi'' are different suffixes.
For example, a board named ''/axiom'' might publish ''/axiom/ltr_2d390_b1_53/ambient'' and ''/axiom/ltr_2d390_b1_53/UVI''. These are examples; copy your actual complete topic paths:
LIGHT_TOPIC='PASTE_FULL_ILLUMINANCE_TOPIC_HERE'
UV_TOPIC='PASTE_FULL_UVI_TOPIC_HERE'
ros2 topic type "$LIGHT_TOPIC"
ros2 topic echo "$LIGHT_TOPIC" sensor_msgs/msg/Illuminance \
--once --qos-reliability best_effort
ros2 topic type "$UV_TOPIC"
ros2 topic echo "$UV_TOPIC" std_msgs/msg/Float64 \
--once --qos-reliability best_effort
Read ''illuminance'' for lux and ''data'' for UVI. Illuminance carries the sample's timestamp and configured sensor frame; ''variance: 0'' means the variance is unknown. Negative or unavailable illuminance is NaN, not a measured zero. UVI has no header or unit field; use inventory for its unit and ''sample'' for measurement timing and validity.
Automatic Illuminance mapping recognises scalar attributes named ''ambient'', ''als'', ''white'', ''visible'', ''illuminance'' or ''light'' (case insensitive), with a known lux conversion. The rule applies across compatible profiles rather than only one sensor model. A channel such as ''ir'' stays a numeric fallback even if its descriptor labels it lux; that label alone does not identify a photometric light quantity.
===== Scalar fallbacks =====
^ Decoded attribute ^ ROS output ^ Value and invalid-reading behavior ^
| Numeric scalar | ''std_msgs/msg/Float64'' | Decoded SI value when available; otherwise decoded engineering value and original unit. Invalid or nonfinite readings are NaN. |
| Boolean | ''std_msgs/msg/Bool'' | Descriptor ''o: bool'' or a ''?'' wire field. Invalid readings are omitted. |
| Text | ''std_msgs/msg/String'' | Decoded scalar text. Invalid readings are omitted. |
| Array or structured value | No generic scalar topic | Remains in ''sample''/''data'', or uses an existing dedicated image/grid adapter. |
The decoder already applies masks, divisors, offsets and other descriptor transforms. The ROS adapter does not apply them twice or replace an unavailable reading with a raw counter. Unknown units stay unknown. A unit such as ''index'', ''ppm'' or ''ticks'' is not silently relabelled as another physical quantity. Numeric scalars use Float64 even when the wire field is an integer, because the engineering result may be fractional. Integer values above 2^53 can lose Float64 precision; ''sample'' retains the raw value.
By default, existing semantic/compound adapters consume the attributes they represent. IMU axes, range values, temperature/humidity, servo position, battery voltage and image pixels/dimensions are not also published as automatic scalar copies. Other fields, such as status, counters and auxiliary readings, may get scalar topics. Generic ''sample'' and ''data'' still contain the full decoded row.
Float64, Bool and String carry only ''data'', with no measurement timestamp, frame or unit field. A headerless fallback is useful for plotting a value, but use ''sample'' when timing, validity or raw/decoded values matter. ''sample.values_json'' contains raw, engineering and SI values, their units and validity; ''data'' is a JSON convenience view. Retain ''device_metadata'' with a recording when you need the complete decoder profile.
===== Aliases and repeated sensor types =====
Automatic paths retain model, bus and address, so multiple sensors of the same type stay distinct. Fallback suffixes retain attribute case and escape unsafe characters. A name that would be hidden, start with a digit or collide with reserved adapter output names gains an ''attribute_'' prefix; for example, a numeric attribute named ''data'' publishes as ''attribute_data''. Read the actual suffix from inventory.
Aliases choose an existing output; they do not change its message type or install a profile. Merge this fragment into the intended board's existing settings, retaining its connection/identity configuration:
topic_aliases:
light: {type: LTR-390, source: ambient}
uv: {type: LTR-390, source: UVI}
For an illustrative ''/axiom'' board, these add ''/axiom/light'' and ''/axiom/uv''. An alias binds only when exactly one matching sensor is online, resolved and fresh. If several LTR-390 sensors match, add string ''bus'' and ''address'' selectors copied from inventory, or use their distinct canonical paths. Header-bearing aliases retain the same timestamp/frame; headerless aliases remain headerless. Canonical and alias QoS overrides match exact topic paths. Restart affected processes after changing read-only board configuration.
===== Optional descriptor mappings: development preview =====
**This section requires the optional-mapping development driver described under Availability. It is not required for the LTR-390 defaults above.**
Add a ''ros'' block inside a sensor descriptor's ''devInfoJson'', alongside its existing ''type'', ''resp'' and ''actions''. This JSON is a fragment to merge into that metadata object, not a complete Device Library file:
{
"ros": {
"version": 1,
"attributes": {
"photodiode": {"message_type": "sensor_msgs/msg/Illuminance"},
"UVI": {"message_type": "std_msgs/msg/Float64"}
}
}
}
Every key must exactly match an attribute's ''n'' in the existing ''resp.a'' array. Replace ''photodiode'' with the actual name in your profile; an existing LTR-390 uses ''ambient''. An unfamiliar scalar name can explicitly request Illuminance, but its descriptor must already supply meaningful lux values. The mapping is received by the host as ''devinfo.ros''; it is not a new library-envelope field, a ''boards.yaml'' option or a native firmware ROS configuration.
Version 1 accepts exactly ''version'' and ''attributes''. Each attribute declaration contains exactly ''message_type'', chosen from this list:
^ Message type ^ Required decoded input ^ Published numeric/text field ^
| ''sensor_msgs/msg/Illuminance'' | Numeric scalar with normalised unit ''lux'' | ''illuminance''; lux |
| ''sensor_msgs/msg/Temperature'' | Numeric scalar with normalised unit ''degC'' | ''temperature''; °C |
| ''sensor_msgs/msg/RelativeHumidity'' | Numeric scalar with normalised unit ''fraction'', e.g. converted from ''%RH'' | ''relative_humidity''; fraction |
| ''std_msgs/msg/Float64'' | Numeric scalar | ''data''; SI when known, otherwise engineering value |
| ''std_msgs/msg/Bool'' | Descriptor boolean | ''data''; boolean |
| ''std_msgs/msg/String'' | Decoded scalar text | ''data''; text |
Mapping declarations select types; they do not supply a unit conversion, scale, topic rename, script or arbitrary message-field assignment. The ordinary descriptor and decoder still determine values, units and validity. The output suffix remains the escaped attribute name. Semantic scalar messages use the sample timestamp, configured frame and unknown variance ''0''. Invalid number/bool/text handling follows the rules above.
==== Precedence and fallback ====
* A valid declaration selects that attribute's scalar output type. Mapping ''temperature'' to Float64, for example, replaces its automatic Temperature output at the same suffix.
* Existing compound IMU, range, image, joint and battery outputs remain available. An explicit component mapping, such as ''gx'' to Float64, additionally exposes that scalar; unmapped components remain consumed by their adapters.
* Unmapped attributes use the existing automatic semantic mapping or scalar fallback. A profile without ''ros'' behaves as before.
* An unsupported version or malformed block is ignored with a warning. Unknown attributes, unsupported message types, extra declaration fields, arrays, incompatible scalar types or incompatible units retain the previous automatic handling for that attribute. Valid peer declarations still apply.
* Warnings appear once per issue per device revision. A field absent from one payload group is skipped there rather than fabricated.
* Metadata changes retire old publishers before replacement types appear, including aliases. The ''output_info'' inventory reports the resulting type and unit.
Use the [[:axiom:device_library:start|Device Library workflow]] to edit and install a profile, preserving other entries in the library. A saved library file becomes effective after an Axiom restart; editing JSON alone does not change the active descriptor. After applying it with a driver that includes the preview, inspect ''device_metadata'' for the returned ''ros'' block, inspect ''devices.output_info'' and check the topic's actual type. The existing metadata path carries the declaration; firmware and Raft do not interpret it as a native ROS instruction.
The implementation has automated ROS Jazzy coverage with simulated firmware peers. Physical Device Library upload/restart/readback and Pi/Kilted acceptance of the mapping block remain pending; this is not a claim of a completed hardware test.
===== Plot the values in Foxglove =====
Start the bridge and connect the viewer using the [[:axiom:ros2:foxglove#illuminance_and_scalar_plots|Foxglove scalar plotting instructions]]. Choose numeric fields directly: Illuminance uses ''.illuminance'', Temperature uses ''.temperature'', RelativeHumidity uses ''.relative_humidity'' and Float64 uses ''.data''. These outputs do not require extracting numbers from JSON strings. Use separate plots for different units and label their axes accordingly.
===== Troubleshooting =====
^ Symptom ^ Check ^
| Only ''sample'' and ''data'' on an older driver | Update, rebuild, source and restart the host driver that includes Illuminance/scalar outputs. Confirm the installed executable comes from the intended workspace. |
| Numeric fallback instead of an expected semantic type | Check the attribute name and normalised units. Explicit selection requires the optional-mapping driver; ''main'' currently ignores that preview block. |
| Mapping warning | Read the named attribute/error, correct the declaration or units, or remove the optional declaration to retain default behavior. Other usable outputs should continue. |
| Bool/text field stops updating | Inspect validity in ''sample''; invalid bool/text readings are omitted rather than publishing an invented value. A viewer may still show its last received value. |
| Alias absent but canonical topic exists | Check exact source case and suffix, board namespace and whether multiple sensors make the match ambiguous. |
| Viewer has a topic but no fresh values | Check publisher count, driver acquisition, sensor state, validity and the shared ROS environment. A subscriber can keep a topic name visible after its publisher retires. |
Continue with [[:axiom:ros2:sensors_and_boards|Sensors and multiple boards]] or [[:axiom:ros2:foxglove|Foxglove dashboards]].