-
Notifications
You must be signed in to change notification settings - Fork 1
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
feat!: add support for generic outputs #141
base: feat/generic_pubsub_dev
Are you sure you want to change the base?
Conversation
a7eaf5f
to
448a862
Compare
c7026c4
to
a9328b1
Compare
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.
Looks nice! I'm curious if we could
- make this PR target a different staging branch
- only change C++ version, and modulo core without changing anything in modulo_components
If we can do that (basically enable generic publishing and message pairs without changing anything in the interface) then we should go for it and close this very first stage
#include <state_representation/space/cartesian/CartesianState.hpp> | ||
#include <state_representation/space/joint/JointState.hpp> | ||
|
||
namespace modulo_core::concepts { |
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.
@domire8 @eeberhard We should agree on concept names/naming convention before merging as well.
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 not really exposed to the user and derived components right? Just to know the importance of naming
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.
Well, it is included in Component.hpp
so it is exposed and can be used in that respect, yes. But it is not something the user needs to interact with to use the library (they will not have to provide them anywhere).
source/modulo_core/include/modulo_core/communication/MessagePair.hpp
Outdated
Show resolved
Hide resolved
Please target a copy of main branch here, not main directly. Will be better to stage everything and fast forward to main when we have the complete feature in cpp and python ready and tested |
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.
Very nice, some minor comments
@@ -52,6 +64,48 @@ class MessagePair : public MessagePairInterface { | |||
*/ | |||
void set_data(const std::shared_ptr<DataT>& data); | |||
|
|||
protected: |
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 this be private?
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.
yes yes, you are right.
* @throws modulo_core::exceptions::NullPointerException if the publisher pointer is null | ||
*/ | ||
void on_activate(); | ||
* @brief Activate ROS publisher. |
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 liked the previous docstrings better, or we just do @copydoc
from the parent class
PublisherType type_; ///< The type of the publisher interface | ||
PublisherType type_;///< The type of the publisher interface | ||
|
||
protected: |
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 we have public
, protected
, private
in that order please
if (this->message_pair_ == nullptr) { | ||
throw exceptions::NullPointerException("Message pair is not set, cannot deduce message type"); | ||
} | ||
if (this->message_pair_->get_type() == MessageType::CUSTOM_MESSAGE) { |
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 get this block, why do we need it?
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.
Ok, indeed this is a bit hacky, but I don't have a cleaner solution yet. We can give it a moment of thought later on in this PR or I can leave a TODO to refactor.
- What it does is:
The problem starts from the fact that for generic types we need to have MsgT
or explicitly know it. This is ok for translated types, hence PublisherInterface::publish
can be used (else block).
For generic types we need to
- override the publish in
PublisherHandler
otherwise we can't deduceMsgT
- and then explicitly call
publish(MsgT&)
which is compatible for all types
- Why the constexpr block
Since both generic and translated types will go through this publish function, it means that the compiler needs to resolve write<MsgT, MsgT>
for all MessageType
s even though there is a runtime condition for MessageType::CUSTOM_MESSAGE
.
The solution is to introduce a secondary compile-time condition to hide this block when translated types are used.
I currently don't have a better alternative to this.
|| std::same_as<DataT, std_msgs::msg::Float64> || std::same_as<DataT, std_msgs::msg::Float64MultiArray> | ||
|| std::same_as<DataT, std_msgs::msg::Int32> || std::same_as<DataT, std_msgs::msg::String>; | ||
|
||
template<typename DataT> |
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 guess the TranslatedOrEncodedDataT
and NonTranslatedDataT
will be required for the integration in the components?
Also, why not add || std::same_as<DataT, EncodedState>
directly to TranslatedDataT
?
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 will now even go as far as saying that the unused concepts could be removed from this PR such that it doesn't go out of scope
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 do need to type check separately, but I do agree that this is a bit out of scope with the new form of this PR. I will remove it now and then we can discuss again in the corresponding PR
|| std::same_as<DataT, bool> || std::same_as<DataT, std::string> || std::same_as<DataT, std::vector<double>>; | ||
|
||
template<typename DataT> | ||
concept CoreDataT = StateRepresentationDataT<DataT> || CorePrimitivesT<DataT>; |
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.
concept CoreDataT = StateRepresentationDataT<DataT> || CorePrimitivesT<DataT>; | |
concept CoreDataT = std::derived_from<DataT, state_representation::State> || CorePrimitivesT<DataT>; |
Could we get rid of the StateRepresentationDataT
like that or will it be required somewhere else?
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 is honestly never used directly (apart from what you see). So yes, we can cut down. I think NonTranslatedDataT is also the same case. I'll clean this up
|
||
// Translation concepts | ||
|
||
template<typename DataT> |
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.
Ah also, now I get what was confusing me a bit here. In the translation concepts we should use MsgT
instead of DataT
and TranslatedMsgT
instead of TranslatedDataT
(and so on) no?
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 am actually not sure here. I use them to both type check DataT and MsgT. Perhaps we should drop Data/Msg altogether and stay generic by saying TranslatedTypeT and so on. What do you think?
Description
The motivation for this PR is to provide the necessary "plumbing" that allows for adding generic (but supported by ROS) output types.
This PR solves the issue by:
PublisherHandler
andPublisherInterface
PublisherHandler
andPublisherInterface
MessagePair
andMessagePairInterface
Review guidelines
Estimated Time of Review: 20 minutes
Checklist before merging: