-
Notifications
You must be signed in to change notification settings - Fork 125
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
ROS2 message format should support enums #260
Comments
We are aware of this. Currently the
|
With the IDL changes merged this becomes more feasible. Potential follow up of #346. |
@dirk-thomas / @calvertdw is anyone working on this, or could I start attempting something on this one? On that note, I had one concern I'd like to address before I dive in on this (assuming I can). Suppose that one host has an outdated copy of the While this is definitely not good practice to do, such a mistake occurs quite easily and is not so simple to track down. So I'm not quite sure how to store such a type internally to detect such an incompatibility. @dirk-thomas maybe you have some idea? |
Nobody is currently working on this or planning to in the near future. First, any change should happen for Adding an enum value in the middle is only compatible if you explicitly specify the enum values (so that they don't change). Also I think the IDL spec already defines enums - so that part would likely be covered by the spec already. |
@allenh1 Have you started work on this? This is a feature we need as well and would be willing to contribute towards. I'm not able to open the design concept link Dirk posted above, but is there any initial thoughts on how this should be approached? |
@davidhodo This the corrected link: https://github.com/ros2/ros2_documentation/blob/master/source/Roadmap.rst#design--concept |
Is the addition of bit masks also being considered along with this (IDL v4.2 section 7.4.13.4.3.3)? |
No, bit masks are orthogonal to enums. Also nobody is currently working on enum support either. |
Is this on the roadmap? If not, can anyone give some recommendations on how to deal with checking enums are valid before publishing or after receiving, handling conversions from the ROS integer back to enums, and how to avoid maintaining a list of constants in the message file in addition to an enum in other source code? |
The roadmap is published here. In short, nobody is currently working on adding enum support. That said, if you are interested in working on it, we'd be happy to review pull requests. |
Hello, I've started to work on this task. After few days looking thru rosidl_parser code, I'm not quite sure how enum support should look like in Do we want the similar suffix for enums? Here is the example how it would look like.
For example in DDS IDL there are no such restrictions and one can have smth like (tested with Cyclone idlc generator)
|
@dirk-thomas @clalancette do you know if my assumption above makes sense? cc @allenh1 |
I'm not entirely sure why we added the additional |
Hello, just want to give a small update. We at Apex.AI already have internal implementation of ROSIDL enum support and going to upstream it soon (2-3 weeks). |
That's fantastic! |
Hi @r7vme I'm just curious if there's any progress? I'd love to know if this feature might make it into Humble. |
@apockill Unfortunately, I believe, it's won't make into Humble. |
@clalancette Hello, I created initial set of PRs (the main one). Have few questions.
|
This issue has been mentioned on ROS Discourse. There might be relevant details there: https://discourse.ros.org/t/need-reviewers-for-rosidl-related-change/26285/1 |
The constants were put into a special As an example, the LoadMap service has constants defined on the result. See the module nav_msgs {
module srv {
struct LoadMap_Request {
string map_url;
};
module LoadMap_Response_Constants {
const uint8 RESULT_SUCCESS = 0;
const uint8 RESULT_MAP_DOES_NOT_EXIST = 1;
const uint8 RESULT_INVALID_MAP_DATA = 2;
const uint8 RESULT_INVALID_MAP_METADATA = 3;
const uint8 RESULT_UNDEFINED_FAILURE = 255;
};
struct LoadMap_Response {
nav_msgs::msg::OccupancyGrid map;
uint8 result;
};
};
}; See the C++ Generator combines the constants onto the generated struct: // message struct
template<class ContainerAllocator>
struct LoadMap_Response_
{
// [...]
// field types and members
using _map_type =
nav_msgs::msg::OccupancyGrid_<ContainerAllocator>;
_map_type map;
using _result_type =
uint8_t;
_result_type result;
// [...]
// constant declarations
static constexpr uint8_t RESULT_SUCCESS =
0u;
static constexpr uint8_t RESULT_MAP_DOES_NOT_EXIST =
1u;
static constexpr uint8_t RESULT_INVALID_MAP_DATA =
2u;
static constexpr uint8_t RESULT_INVALID_MAP_METADATA =
3u;
static constexpr uint8_t RESULT_UNDEFINED_FAILURE =
255u;
// [...]
}; // struct LoadMap_Response_ All that to say, it looks like the IDL doesn't allow enum's in |
Small update here. Open PRs (#685) were paused from our side (initially mostly because of internal load). In the mean time, we've received a lot of internal and external feedback about current design / implementation. On the positive side: this design and implementation is MVP and allows to "check the box" that enums are supported. On the constructive side: People who already worked with Protobuf / FrancaIDL / OMG ODL find experience very frustrating due to many missing features in ROSIDL. Just one example, when we claim that enums are supported, expectations are that one can define enum once and use across all interfaces. This is not the case. See example below. Lessons learned:
I propose to pause existing solution (#685) and instead focus on improving ROSIDL tooling first. If high-level proposal (see lessons learned) looks ok, please let me know what can be next steps? Example mentioned above. Not supported currently, but very common use case, reuse enums in other idl files // GearBoxState.idl
module foo_msgs {
module msg {
enum GearBoxState {
NEUTRAL,
DRIVE,
REVERSE,
PARKING
};
};
}; // VehicleState.idl
#include "foo_msgs/msg/GearBoxState.idl"
module foo_msgs {
module msg {
struct FooMessage {
foo_msgs::msg::GearBoxState enum_value;
};
};
}; |
My biggest concern here (which has been a concern ever since we introduced support for straight
Yes, you are definitely not the first one to complain about this. I'd be all for making ROSIDL easier to reason about and extend.
This seems worth exploring, though I think we need to keep performance in mind here. It is already really slow to generate the code, so I don't want to slow it down further. It isn't clear to me whether using something else will be faster or slower, but we definitely need to evaluate that.
For what it is worth, that is not the version of empy that we use. That was a fork at some point. The latest release of empy was in 2019: https://pypi.org/project/empy/#history That said, I'd be much more interested in improvements to the current code rather than wholesale replacement. The fact of the matter is that our business logic is complicated, so I'm skeptical that a different templating engine (on its own) is going to yield significant readability benefits[1]. So I think we should see how much we can improve the current empy-based code rather than switching to something else. [1] I definitely could be wrong here, but I think that would have to be demonstrated before we moved forward with a replacement. |
@r7vme A small improvement here would be docstrings on the functions. I find it's hard to review changes because it takes a while to figure out what a lot of them do.
@r7vme +1 to the EmPy templates being very hard to read. It's very hard to see the difference between template logic and the static code - especially in
@r7vme What do you mean by "view model"? Is this a common design pattern, and if so, got a page I can read about it?
@r7vme If we end up rewriting the templates, I'd be all for switching to a more popular template engine
@clalancette It's hard to measure readability, but a more popular engine will have more tools to help with readability. There aren't a lot of tools or plugins for things like syntax highlighting (@dirk-thomas wrote a plugin for VSCode, but that's the only one I know of).
@clalancette Do you mean nesting types, like how would
@clalancette |
Personally I think the readability of our empy templates is due to how we use them, not the template engine itself. If I'm not wrong the "view model" being referenced implies a template engine like jinja where it's essentially just substring replacement (with a few conditionals and stuff like that), part of the MVC (model-view-controller) pattern most likely, where the view is data driven and doesn't contain logic, but I believe that our use case is quite different from those use cases. And while we could use something like jinja, I'm not convinced it would be strict win over just making an effort to improve the readability of our existing templates using empy. Also, to the idea that empy is a weird one-off template engine, I think it isn't as popular but there are many other engines that work in a very similar way, e.g. erb (embedded ruby). I think the reason that they are less popular is that the use cases for which they excel are less common, at least compared to use cases where engines like jinja or genshi are good, e.g. web development. A better reason (in my opinion) to consider switching template engines would be for something like performance (as these templates do significantly impact our build times), rather than using something that's popular. While it might be nice to have an engine that more people are immediately familiar with, the reality is that very few people need to extend the typesupport pipeline and optimizing for developer familiarity it probably not the right focus (that doesn't mean we can't try to work on that too, just want to make sure we're spending our effort on the right things). Performance and suitability for the task seem like better things to optimize. So if we do switch template engines (a time consuming and potentially bug producing exercise) I would rather see us decide to do it for those reasons as opposed to personal preference or popularity. Personally I would prefer to stay with empy, but either way that decision isn't going to make the templates magically more easy to read. In both cases we'll need to just spend time ensuring they are easy to read. -- With respect to extending rosidl (by which I mean the "ROS interface description language", e.g. .msg files, and not the entire type support pipeline in ROS 2) vs just embracing OMGIDL (i.e. .idl files), I think that a pragmatic approach is best. I don't think we should be adding every feature to ROSIDL and I'm less concerned with fragmentation (some people using ROSIDL and some using OMGIDL) in the community than @clalancette, though I would strive to stick with ROSIDL in the core, just because it's simpler and keeps things consistent. But I would prefer people to "fragment" and use OMGIDL sometimes rather than spend lots of effort extending ROSIDL. However, in the spirit of ROSIDL being easy for simple things, I think it would make sense to add enums to ROSIDL, assuming we can find someone to spend the time to do it. This is as opposed to something like adding bit fields or annotations or something like that to ROSIDL, in which cases I would personally prefer to just enable their use via OMGIDL and not try to add them to ROSIDL. So I think we should consider each use case on a case by case basis and decide if adding it to ROSIDL makes sense. And personally I would lean towards "do not extend ROSIDL" in most cases, but for enums in particular I would say we should add those to ROSIDL. |
To the point of changing template engines and differentiating between using a more popular template engine vs using one that is appropriate for the task, I would be fine with trying to find a better supported engine (more popular) but would like to see us make sure it is more like empy (which was selected for its function more than its popularity), for example we could consider mako https://www.makotemplates.org/, which is more on the "logic in templates" side of things but also more popular than empy. Other engines like Jinja and Genshi are kind of in the middle with limited logic in the templates and Python's builtin |
As a user who isn't familiar with the underlying implementation details, my
only comment is +100 for the comment about build time performance.
Generating the messages is by far the slowest part of our build. It would
be kind of nice if it were easier to select which languages the messages
were generated for... i.e for the most part, I don't care about the python
or c messages...only c++, but I haven't found any examples on how to turn
those off.
Other than enums, the only other feature that would be really nice is
something like protobuf's oneof type or some kind of union/variant.
…On Fri, Nov 11, 2022, 1:42 AM Roman ***@***.***> wrote:
What do you mean by "view model"? Is this a common design pattern, and if
so, got a page I can read about it?
@sloretz <https://github.com/sloretz> Correct, in context of Jinja2 it's
described also here
<https://flask-diamond.readthedocs.io/en/stable/developer/writing_views_with_jinja_and_blueprints/>.
Quote from the page: *View takes data from a Model and presents it
(typically to a user)*
—
Reply to this email directly, view it on GitHub
<#260 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAUKSZ6ZKHQ7R5KLJOERWDLWHXTHBANCNFSM4EK2WMKA>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
As another user who isn't familiar with the implementation details, I would agree with @wjwwood that supporting both ROSIDL and OMGIDL would be preferable. For simple use cases, you could continue to use the msg interface and ROSIDL. But for more complex use cases, OMGIDL might be required. A novice user can use the simpler format of ROSIDL without having to burden themselves to learn the OMGIDL. And I would agree with @wjwwood that it would be nice to at least add enums to ROSIDL. I will say that if you are a programmer and are used to creating nested structures and enums and unions in C++, creating OMGIDL-based idl is not very burdensome. An added benefit, which is very relevant for us, is that you can easily communicate with native DDS applications by using OMGIDL. Currently, we are having to jump through hoops converting msg files to IDL that can be used by our native DDS applications. Obviously supporting OMGIDL will require the rest of the tooling e.g. 'ros2 topic', to also support OMGIDL, which presumably is a lot of work. But I think the benefit of more richer and readable types in OMGIDL is crucial to extending ROS2 to more applications and users. |
I stumbled across this discussion while looking for enum support in ROS2. Thank you for starting this discussion! After reading through some of it, it is understandable that adding enums isnt very straightforward but I had an additional use case for enums in messages to point out nevertheless. We have recently started using ROS2 with Rust in some of our projects and the increasing community support from libraries like r2r and rclrs for this is helping a lot. With Rust, there is an additional advantage to support |
I've been doing the same in C++ with strongly typed enumerations. In that case, linters also warn about unhandled cases of switch statements. The compiler also keeps me from mixing up enumerations, e.g., lifecycle transitions and states, and generally leads to more readable code. For these reasons, I would favor |
Hello, has this discussion made any progress? Apologies for commenting on such an old thread, but it seems to have been a while since an update was provided. |
From @calvertdw on January 8, 2018 16:53
You guys know what this means.
Constants aren't good enough. They don't constrain you to the range of values and you are able to set the field to any number you want.
// Current way
// Proposed way
Copied from original issue: ros2/ros2#447
The text was updated successfully, but these errors were encountered: