-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open streams working for all stream types + some bug fixes #11045
Conversation
@@ -83,18 +83,20 @@ class dds_stream_profile | |||
{ | |||
dds_stream_uid _uid; | |||
dds_stream_format _format; | |||
int16_t _frequency; // "Frames" per second | |||
int16_t _frequency; // "Frames" per second | |||
int8_t _inner_type; // User defined type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite understand the need here.
If really necessary, the "type" is the "stream type" and not the profile type. All profiles of the same stream will have the same type, no? I.e., it should be communicated with the stream and not the profile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RS applications like rs-enumerate-devices
and rs-sensor-control
use rs2_profile type field to print a "stream name" for each profile, and we need to pass this information to them.
I agree that this is a duplication that can be avoided by sending a stream type. Currently in notificaiton-msg it is sent in the profile struct, and I didn't want to change that so we won't have a difficult merge.
I will take the information to the stream from the first profile in the message assuming all profiles have the same type (true for libRS, not sure that true in the general case)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So approve my PR and sending a type as part of the stream-header
will be simple :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way -- I don't think the type should be an argument to the stream, but a subtype of the stream: i.e., a dds_gyro_stream_server
derives from dds_motion_stream_server
, etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we will have to add types to realdds if LibRS adds a type. realdds doesn't really care about the type, it just need to relay it to the user
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the type does change things, and can change functionality.
Right now it's divided into "video" and "motion" but if we need more, then more types are needed.
Doing this thru polymorphism is the right way to do it -- if it's important. I'm still unsure that it is (what depends on the stream type?) -- let's talk about it.
@@ -176,6 +179,11 @@ void dds_device_server::init( std::vector< std::shared_ptr< dds_stream_server > | |||
else | |||
DDS_THROW( runtime_error, "unexpected stream '" + stream->name() + "' type" ); | |||
} | |||
|
|||
// Create a control server and set callback | |||
_control_server = std::make_shared< dds_control_server >( _subscriber, _topic_root + "/control" ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems weird: why is the device server creating a control server? It's a control client -- the server is on the client side... i.e., the "server" is the "publisher", not the subscriber...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "Server" term refers to the camera side, as opposed to the "client" or "host".
"Server" does imply publisher. Many server only handles incoming requests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, let's stick to one terminology: a server "serves" data (i.e., sends), a client receives. Otherwise it's confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that your terminology is confusing. A server just have services that handle client requests.
And what is the difference than between "broadcaster" and "server"? They both send data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't make the terminology. A server serves data, whether it's web pages or anything else.
The "broadcaster" needed distinguishing in its name somehow, and we decided on broadcaster which you're right, also serves data. But it's understood from the name.
But here you have something that consumes data and serves nothing. Why call it a server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree with you here.
All the -server
classes are on the "server" side (as in rs-dds-server
tool) to distinguish from the "host" side.
dds-device-server
vs dds-device
, dds-stream-server
vs dds-stream
.
Keeping this notation helps to orient in the code and distinguish the class purpose.
@Nir-Az - what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This argument might be redundant, as mentioned in another conversation this class might later be refactored out...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that server
should not be confused and places at the client side.
server
is the node
that sends frames, it a camera server.
It will add more confusion to call the client server.
We are creating here a client for controlling the camera server and getting frames..
It does help distinguish between sides IMO.
|
||
// A control is a command sent from a client (camera user) and the server (this class) receives and interprets. | ||
// | ||
class dds_control_server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my understanding of the usage, this is not really a server but a client -- a listener for control messages.
If so -- then how is this different than a topic-reader? Do you envision more logic being placed here? I don't see much logic belonging in realdds other than high-level commands (stream start/stop, control get/set) that would still need customization by the end implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we will need more logic to handle stuff like query-reply pairs and msg-id matching.
If it will all be in the application than you are right and we can refactor this out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it'll be where the control messages are handled.
Most controls will be handled in the app and only a few will be done entirely in realdds and even then it'll likely be in the device-server. If there's a lot of code we can certainly push to another class but at this time I don't see much justification.
…into dds # Conflicts: # third-party/realdds/src/dds-stream-server.cpp
@@ -41,17 +44,34 @@ dds_device_server::~dds_device_server() | |||
} | |||
|
|||
|
|||
void dds_device_server::start_streaming( const std::string & stream_name, | |||
const image_header & header ) | |||
void dds_device_server::start_streaming( const std::vector< std::pair < std::string, image_header > > & streams_to_open ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said in our discussion:
I think this should not be a command (to the server or the stream) but rather the direct result of someone subscribing to the stream. The application needs to be notified when this happens (because it does the streaming).
Not for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's speak about it later on.
I think it's better to stick to USB style use case.
Open --> start stream
Start --> connect a callback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's better to stick to USB style use case.
Not sure I agree.
There's no meaning to providing a callback in DDS, therefore start
is meaningless. And open
is just too generic.
As I said elsewhere:
I don't think there should be an open
or start_streaming
at all: this is DDS. When someone subscribes to a stream, the server should automatically start given the set profile. Same with stopping.
if ( !data.is_valid() ) | ||
continue; | ||
|
||
_control_dispatcher.invoke( [&]( dispatcher::cancellable_timer ) { handle_control_message( data ); } ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to be really careful here:
data
is local and will likely go out of scope by the time the dispatcher handles things. A crash is very likely eventually. The &
will pass it to the lambda by ref which is no good -- we need to move it to the lambda.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
invoke
is moving when enqueuing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It moves the lambda, with all its contexts. But if the lambda contains a reference, the moved-to lambda will still contain the same reference to the original object, which sits on the stack.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently, moving captures is not supported by C++11
Will copy the data, it is bound at 4K.
|
||
void dds_device_server::handle_control_message( topics::flexible_msg control_message ) | ||
{ | ||
auto const & j = control_message.json_data(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
json_data
returns a json object, but not a reference. This should be putting up a warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gcc issued a warning when I used a non-const reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It shouldn't be a reference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't it be more efficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If int foo() { return 5; }
,
Can you do int & x = foo();
?
You cannot assign a reference to a temporary variable. If the compiler does not generate a warning, the performance will still be the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
// Does not allocate for every sample but still gives flexibility. See: | ||
// https://github.com/eProsima/Fast-DDS/discussions/2707 | ||
// (default is PREALLOCATED_MEMORY_MODE) | ||
wqos.endpoint().history_memory_policy = eprosima::fastrtps::rtps::PREALLOCATED_WITH_REALLOC_MEMORY_MODE; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
@@ -14,8 +14,8 @@ class lrs_device_watcher : public std::enable_shared_from_this<lrs_device_watche | |||
public: | |||
lrs_device_watcher( rs2::context &_ctx ); | |||
~lrs_device_watcher(); | |||
void run( std::function< void( rs2::device ) > add_device_cb, | |||
std::function< void( rs2::device ) > remove_device_cb ); | |||
void run( std::function< void( rs2::device && ) > add_device_cb, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any special reason? rs2::device
has a shared_ptr inside so it just does a reference count
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not realize it was just hiding a shared_ptr and thought it would be more efficient. Will roll back the changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
// and stopping/closing on destruction | ||
class lrs_device_controller::lrs_sensor_streamer | ||
|
||
std::shared_ptr< dds_stream_profile > create_dds_stream_profile( rs2_stream type, nlohmann::json const & j ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not clear why we're creating new profiles rather than finding an existing profile that's part of the server streams?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can be an improvement on the tool. Not for this PR
throw std::runtime_error( "Unsupported stream type" ); | ||
} | ||
|
||
rs2_stream stream_name_to_type( std::string const & type_string ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be stream_type_to_rs2
? I.e., why is it dependent on the stream name and not the stream type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for this PR. Will change when profiles are stored in stream_server
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean... the profiles are there.
//corresponding to the requested, we have found our sensor. | ||
for ( sensor_index = 0; sensor_index < _sensors.size(); ++sensor_index ) | ||
{ | ||
for ( auto & profile : _sensors[sensor_index].get_stream_profiles() ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not do a sensor.get_info( RS2_CAMERA_INFO_NAME )
to get its name?
We could do this once and store a map of sensor-to-index, even in the ctor...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forget how confusing it is...
You're looking for a stream name, not a sensor name.
Still, I think we need to be extra careful here: stopping a stream is not the same as stopping a sensor. I.e., you can close the IR streams but leave Depth running. I'd even make that a unit-test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right that stopping a stream should not, theoretically, stop other streams, but this is not the current use case.
This tool is giving LibRS users the behavior that they expect from a USB camera, and the LibRS API does not enable to stop just a stream, but a whole sensor.
In the future we may decide to change this behavior, but not for this PR.
(Plus it would really change if we'll open/close streams based on readers availability)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not saying you should take care of this "use-case" in this specific tool. But the API and the triggers for everything need to be understood and acted on now, not later.
The way we open/close streams is in realdds and the camera-host communication, not the tool. Here we need to envision all use-cases and make sure the API is suitable for multiple readers if needed.
Don't be limited by the use-case.
@@ -2,13 +2,17 @@ | |||
// Copyright(c) 2022 Intel Corporation. All Rights Reserved. | |||
|
|||
#include <librealsense2/utilities/easylogging/easyloggingpp.h> | |||
#include <librealsense2/utilities/json.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure you need these here any more (same for flexible-msg, using json)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just those 2 small comments... otherwise good, as discussed.
Updated the PR, merge with Eran's PRs, addressed issues raised in comments and added functionality
rs-dds-server handles "open-streams" control messages
Created dds-subscriber
Added type to profile (needed by various RS tools and examples)
Added type-object support to dds-topic
Fixed some bugs