10 KiB
See also: device, notifications
Initialization
In order to stream, a client must know the stream names, available formats, etc.
The only way for a client to get these is by subscribing to the notification
topic. When the server detects a subscriber on this topic, it will broadcast a set of initialization messages in the following order:
device-header
device-options
- optional- For each stream:
stream-header
stream-options
These initialization messages should only have effect on devices that are not already initialized. They are expected in the above order.
Once all streams have been received, the device is initialized and ready to use. See Streaming.
"Atomic" Initialization
Initialization may happen interspersed with regular notifications: for example, a server that's already serving data and notifications to an existing client may see another client and broadcast initialization messages.
Only one set of initialization messages can be sent at a time. I.e., if a new client is detected while initialization messages for a previous client are still outgoing, a new set of messages must go out but only once the previous set is finished.
While a set of initialization messages are outgoing, all other notifications must take a back seat and wait until the set is written out.
Messages
device-header
This is the very first message, for example:
{
"id": "device-header",
"n-streams": 5,
"extrinsics": [
["Depth","Gyro",[1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0,-0.005520000122487545,0.005100000184029341,0.011739999987185001]]
["Depth","Infrared 2",[1.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,1.0,-0.04986396059393883,0.0,0.0]]
],
"presets": ["Default", "Max Range", "Max Quality"]
}
n-streams
is the number of streams to expect The device will wait for this many stream headers to arrive to finish initializationextrinsics
describe world coordinate transformations between any two streams in the device, required for proper translation of pixel coordinates between sensors, such as when a point-cloud is neededpresets
is an optional array of preset names The presets may then be applied usingchange-preset
Extrinsics
In order to translate from one stream viewpoint to another, a graph needs to be available with nodes for each stream and a directional edge between them (one from A to B; another from B to A).
So extrinsics
is an array of such edges: [<edge1>,<edge2>,...]
,
Each edge
is also an array: [<from>,<to>,[<r00>,<r01>,...,<r22>,<tx>,<ty>,<tz>]]
.
Where <from>
and <to>
are stream names, and the array inside contains the 9 rotation values (column-major) followed by 3 translation vector values.
The complete graph can be transmitted like this but this is overkill: given at least one edge from each stream to another, the rest can be computed. This is what librealsense does:
- Depth to IR = identity
- Depth to IR2 = {...}
- RGB to Depth = {...}
With those 3, one can compute IR2 to RGB, for example.
device-options
This is optional: not all devices have options. See device.
{
"id": "device-options",
"options": [
["Domain",0,0,232,1,0,"The DDS domain (0-232) in which this device will be discovered"],
["IP Address","1.2.3.4",null,"Which IP address to assign to the device; if empty, DHCP will be used", ["optional","IPv4"]]
]
}
"options"
is an array of options- Each option is an array of
[name, value, range..., default-value, description, [properties...]]
:- The
name
is what will be displayed to the user - The current
value
- An optional
range
of valid values- Numeric options (
float
,int
), defined by aminimum
,maximum
, andstepping
- I.e., is-valid = one-of(
minimum
,minimum+1*stepping
,minimum+2*stepping
, ...,maximum
)
- I.e., is-valid = one-of(
- Booleans can remove the range, e.g.
["Enabled", true, true, "Description"]
- Booleans can be expressed as a range with
minimum=0
,maximum=1
,stepping=1
- Booleans can be expressed as a range with
- Free string options would likewise have no range, e.g.
["Name", "Bob", "", "The customer's name"]
"IPv4"
is a string option that conforms toW.X.Y.Z
(IP address) format
- Enum options are strings with an array of choices, e.g.
["Preset", "Maximum Quality", ["Maximum Range", "Maximum Quality", "Maximum Speed"], "Maximum Speed", "Standard preset combination of options"]
- Numeric options (
- A
default-value
which also adheres to the range- If this and the range are missing, the option is read-only
- A user-friendly description that describes the option, to be shown in any tooltip
- Additional
properties
describing behavior or nature, as an array of (case-sensitive) strings"optional"
to note that it's possible for it to not have a value; lack of a value is denoted asnull
in the JSON- If optional, a type must be deducible or present in the properties
- E.g.,
["name", null, "description", ["optional", "string"]]
is an optional read-only string value that's currently unset - Enums cannot be optional
"string"
,"int"
,"boolean"
,"float"
,"IPv4"
,"enum"
can (and sometime must) indicate the value type- If missing, the type will be deduced, if possible, from the values
"read-only"
options are not settableset-option
will fail for these, though their value may change on the server side
- The
- The device server has final say whether an option value is valid or not, and return an error if
set-option
specifies an unsupported or invalid value based on context
- Each option is an array of
Device options will not be shown in the Viewer.
stream-header
Information about a specific stream:
name
is the stream name, e.g.Color
- This will be shown in the Viewer
- This is also the name of the topic containing the stream data
- E.g.,
rt/<topic-root>_Color
- If it contains a space, the space will be replaced by
_
- e.g.,rt/<topic-root>_Infrared_1
- E.g.,
profiles
array- Each profile is itself an array of
[frequency, format, width, height]
- Format is a string representation, similar to the image encoding in ROS
- Each profile is itself an array of
default-profile-index
is the index into theprofiles
for the default profilesensor-name
is the name of the sensor- Sometimes, a single sensor may produce multiple streams, e.g.
Stereo Module
produces aDepth
stream and alsoInfrared
- Streaming one stream requires starting the sensor, and so may have effect on the other streams, depending on the server implementation
- This allows streams to be grouped by the client and may affect its logic
- Sometimes, a single sensor may produce multiple streams, e.g.
type
is one ofir
,depth
,color
,confidence
,motion
- similar to the librealsensers2_stream
enummetadata-enabled
istrue
if ametadata
topic for the device will be written to
{
"default-profile-index": 29,
"id": "stream-header",
"metadata-enabled": true,
"name": "Color",
"profiles": [
[30,"rgb8",1280,800],
[30,"BYR2",1280,800],
[30,"Y16",1280,800],
...
],
"sensor-name": "RGB Camera",
"type": "color"
}
stream-options
stream-name
is the name of the stream, same as instream-header
intrinsics
is:- For video streams, see below
- For motion streams, a mapping from either
accel
orgyro
to an array of float values conforming to:struct rs2_motion_device_intrinsic { // Scale X cross axis cross axis Bias X // cross axis Scale Y cross axis Bias Y // cross axis cross axis Scale Z Bias Z float data[3][4]; // Variance of noise for X, Y, and Z axis float noise_variances[3]; // Variance of bias for X, Y, and Z axis float bias_variances[3]; }
JSON "intrinsics": { "accel": [1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0], "gyro": [1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] }
options
is an array of option objects, same asdevice-options
above
Stream options are shown in the Viewer.
Video Stream Intrinsics
{
"id": "stream-options",
"intrinsics": {
"width": 1280,
"height": 720,
"principal-point": [640.2379150390625,357.3431396484375],
"focal-length": [631.3428955078125,631.3428955078125]
},
"options": [
["Backlight Compensation",0.0,0.0,1.0,1.0,0.0,"Enable / disable backlight compensation"],
["Brightness",0.0,-64.0,64.0,1.0,0.0,"UVC image brightness"],
],
"stream-name": "Infrared 1"
}
Like extrinsics are used to communicate translation between different stream viewpoints, the intrinsics serve to transform 2D pixel values to 3D world coordinates. I.e., an RGB pixel has to be converted to a 3D point in space, then mapped to a 3D point from the viewpoint of the Depth stream, then transformed back into a 2D Depth pixel.
The intrinsics are communicated in an object, as shown above:
- A
width
andheight
are for the native stream resolution, as 16-bit integer values - A
principal-point
defined as[<x>,<y>]
floating point values - A
focal-length
, also as[<x>,<y>]
floats
A distortion model may be applied:
- The
model
would specify which model is to be used, with the default ofbrown
- The
coefficients
is an array of floating point values, the number and meaning which depend on themodel
- For
brown
, 5 points [k1, k2, p1, p2, k3] are needed
- For
The coefficients are assumed 0 if not there, applying no un/distortion.
An additional force-symmetry
boolean can be applied, and defaults to false
.
The intrinsics are communicated for the native resolution the device chooses. Librealsense, or any client, will need to scale these to a target resolution.