6.6 KiB
See also: device
Streaming
A stream is a single topic. Its data flows from the server (publisher) to the client (subscriber).
Quality of Service
- Reliability:
BEST_EFFORT - Durability:
VOLATILE
Start / Stop
To receive data, a client need give no command.
The act of subscribing is enough to start streaming.
I.e.: the server must track the number of subscribers and start or stop streaming from the sensor accordingly (if there is a sensor).
Multiple Clients
Note that streaming is a read-only operation and therefore can be shared: once streaming, any subscriber can see what's being streamed. See open-streams for information about changing what is being streamed.
Multicast
Network bandwidth is at a premium and multiple clients accessing the same server entails sending datagrams to each separately (by default). To save on bandwidth and efficiently read from a server, a multicast IP address is used.
The address is broadcast as part of device discovery.
With multicast-enabled clients, the server has to send datagrams to one address, saving network bandwidth and processing time. The clients need to know to listen on this address.
Multiple Streams
To start multiple streams, a client must simply subscribe to multiple topics.
Incompatible profiles
If, when streaming is attempted (a subscriber is detected), no compatible profile can be found to the currently-streaming profile, an error will result.
E.g.:
- Default
Depthprofile is 1280x800 - Streaming starts on
Depth - Streaming is then attempted on
Infrared Infraredhas no profile for 1280x800; only for 1280x720
It is therefore very important for default profiles to agree with one-another and with the intended client (ROS2, specifically).
Format
The type of stream matters and dictates the stream format.
For video streams, the format is the ROS2 Image format; for motion, the ROS2 Imu format.
Video
For video streams, the format is the ROS2 Image format. This is a simplified IDL for reference:
struct Time {
long sec;
unsigned long nanosec;
};
struct Header {
Time stamp;
string frame_id;
};
struct Image {
Header header;
unsigned long height;
unsigned long width;
string encoding;
octet is_bigendian; // false
unsigned long step;
sequence< octet > data;
};
The encoding is the same as the currently set profile format, and shouldn't change between frames. Neither should the width, height, step, or frame_id.
Motion
See the ROS2 Imu format. This is a simplified IDL for reference:
struct Vector3 {
double x;
double y;
double z;
};
struct Quaternion {
double x;
double y;
double z;
double w;
};
struct Imu {
Header header;
Quaternion orientation;
double[9] orientation_covariance;
Vector3 angular_velocity;
double[9] angular_velocity_covariance;
Vector3 linear_acceleration;
double[9] linear_acceleration_covariance;
};
Metadata
There are no frame numbers in the ROS2 formats.
It is therefore impossible to communicate a frame number unless additional data is used. This is what metadata is for. Without metadata (which is optional), frames will not be numbered, or will be up to the client to number (as happens in librealsense).
The same is true for any frame information that the server generates.
Controls
open-streams
This control tries to configure the profile(s) used for streaming.
Note that it does not start streaming. It is a request. It may fail.
Notably, if a sensor is already streaming, this command will likely fail though the behavior is up to the server.
{
"id": "open-streams",
"stream-profiles": {
"Color": [30,"rgb8",1280,720]
}
}
The stream-profiles is a mapping from stream-name to a profile. The profile is an array of [frequency, format, width, height], similar to those used in initialization.
If the stream-name or profile are not found, this should result in an error.
If a field called reset is set to true (the default -- the above JSON therefore has it at true), any previous open-streams are forgotten and the server resets all sensors to default profiles before processing the stream-profiles (which can be empty).
Multiple streams can be configured by a single open-streams. If these streams share a sensor-name (see initialization), they must be compatible or an error will result.
If the stream profile cannot be changed (sensor is already open, for example), an error will be the result. This usually means that, once the stream is streaming, its profile cannot be modified by anyone. The only way is to stop all subscriptions first.
If commit is set to true (again the default), the state of the streams is locked in after open-streams and until the next reset is received. If false, additional open-streams requests can be cumulative (with reset also false). A commit is implicit when streaming actually starts.
Implicit vs. Explicit profiles
Many times profiles are dependent on one-another.
A good example is the Stereo Module sensor, with two streams: Depth and Infrared. When you set the Depth profile, the Infrared profile must change implicitly if not explicitly specified by open-streams, else streaming won't work (because the sensor cannot work at two different FPS or resolutions, for example).
When streaming starts (on first subscription), the server must align the profiles for the sensor. They are then "committed" and cannot be changed.
Assume the default for both streams is 1280x720. An open-streams is received for only Depth, to 640x480. Infrared should be implicitly set to the same resolution (if possible). Depth is then subscribed to. Then, to stop streaming, the subscription is removed. A second client then subscribes to either stream. Which resolution should it stream? An explicit resolution control was made, and so the same resolution should stay locked in until reset.
Without an open-streams control, all profiles are implicit, meaning streams revert back to their defaults when streaming stops.