Conversation
|
I am sorry that my latest PR #44 made this conflict. I will rebase your patch against master and comment here when it is ready. |
dhood
left a comment
There was a problem hiding this comment.
This is great - thank you for this PR! The custom mapping works well and I can get service calls working in both directions. I've been testing it out a bit and I have a couple of issues:
- unsupported server-clients cause the bridge to crash, e.g. if you run ROS 2
parameter_eventsexample you get
terminate called after throwing an instance of 'std::runtime_error'
what(): No template specialization for the service: ros2:rcl_interfaces/DescribeParameters
- using a ROS 1 client and a ROS 2 server results in two requests being received, for both Connext and Fast RTPS (running e.g.
rosrun rospy_tutorials add_two_ints_client 3 4andadd_two_ints_servergives:
dhood@osrf-esteve:~ [~]$ add_two_ints_server__rmw_connext_cpp
RTI Data Distribution Service EVAL License issued to OSRF dhood@osrfoundation.org For non-production use only.
Expires on 07-Jan-2017 See www.rti.com for more information.
Incoming request
a: 3 b: 4
Incoming request
a: 3 b: 4
^Csignal_handler(2)
- removing a ROS 1 server - ROS 2 client bridge (e.g.
rosrun roscpp_tutorials add_two_ints_serverandadd_two_ints_client_async__rmw_connext_cpp) crashes for Connext with:
Removed 2 to 1 bridge for service add_two_ints
terminate called after throwing an instance of 'std::runtime_error'
what(): rcl_wait() failed: read condition handle is null, at /home/dhood/ros2_ws/install_isolated/rmw_connext_shared_cpp/include/rmw_connext_shared_cpp/shared_functions.hpp:440, at /home/dhood/ros2_ws/src/ros2/rcl/rcl/src/rcl/wait.c:581
Aborted (core dumped)
- if you use a ROS 1 server - ROS 2 client bridge (as in 3) with Fast RTPS, then remove it, then try to use it again, the client never re-connects (might be related to the topics never going away for fastrtps):
dhood@osrf-esteve:~ [~]$ add_two_ints_client_async
service not available, waiting again...
service not available, waiting again...
service not available, waiting again...
service not available, waiting again...
| Example mapping rules file | ||
| -------------------------- | ||
|
|
||
| Example package mapping rule:: |
There was a problem hiding this comment.
this is appropriate formatting for .rst (I know it looks like a type if it were .md). this applies to the lines below as well
ros1_bridge/__init__.py
Outdated
| resources = ament_index_python.get_resources(resource_type) | ||
| for package_name, prefix_path in resources.items(): | ||
| resource, _ = ament_index_python.get_resource(resource_type, package_name) | ||
| resource = ament_index_python.get_resource(resource_type, package_name) |
There was a problem hiding this comment.
this change reverts #35 which was in place because of an update to the ament_index API. If it's not working for you locally how it was, you probably have to update your ament/ament_index checkout to master. similarly at https://github.com/ros2/ros1_bridge/pull/36/files#diff-3db064ef68c7605e1de4bc963ee60609R186
src/dynamic_bridge.cpp
Outdated
| service_bridges_1_to_2.find(name) == service_bridges_1_to_2.end()) | ||
| { | ||
| auto factory = ros1_bridge::get_service_factory("ros1", details.at("package"), details.at("name")); | ||
| service_bridges_2_to_1[name] = factory->service_bridge_2_to_1(ros1_node, ros2_node, name); |
There was a problem hiding this comment.
this is throwing a runtime error that causes the bridge to crash if it's not a supported service
|
Thanks for the review! Ad. 1. Fixed, factory is not throwing anymore as it is a normal situation when there is no bridge for a service Ad. 2. This client written in Python makes two calls add_two_ints_client Ad. 3. I added error handling when removing a bridge but I cannot verify it because I cannot build ROS2 with RTI Connext DDS. What Connext version do you use? I use 5.2.3 for open source projects and it fails during linking. When I used a trial version it was fine but it has expired. Ad. 4. It is probably related to this issue. If the bridge finds a ROS1 server it creates a ROS2 server. If ROS1 server is removed, the bridge removes its own ROS2 server. But this server does not disappear and the bridge thinks that it found a new ROS2 server... so it prepares for routing from ROS1 and ROS2 and will never route again from ROS2 to ROS1. |
We can build ROS 2 against the professional version (which requires a license) as well as against the evaluation version (which can be downloaded from their website). Maybe you can post more information what exactly fails for you in order to resolve the problem. |
- printing errors to stderr - replaced boost library with std - fixed indentation in templates - support for a manual service matching - simplified an example in README
- Service factory does not raise errors anymore - Handling exceptions while creating/removing bridges - Fixed syntax in index.rst
78c93d7 to
4d938fd
Compare
|
My branch is rebased + one more commit with some updates after rebase. |
|
Here is a log file from building ROS2 with RTI Connext DDS for open source projects: gist/rti_connext_dds.log |
|
|
||
| While building, ros1_bridge looks for all installed ROS and ROS2 services. | ||
| Found services are matched by comparing package name, service name and fields | ||
| in a request and a response. If all names are the same in ROS and ROS2 service, |
There was a problem hiding this comment.
Please add a newline after every sentence.
| ROS1_T & ros1_msg); | ||
| }; | ||
|
|
||
| template <class R1_TYPE, class R1_REQ, class R1_RES, class R2_TYPE, class R2_REQ, class R2_RES> |
There was a problem hiding this comment.
Please remove the template arguments for request / response. They can be derived with e.g. R1_TYPE::Request.
There was a problem hiding this comment.
Please use the same template names as for pub / sub: e.g. ROS1_T.
| private: | ||
|
|
||
| void translate_1_to_2(const R1_REQ&, R2_REQ&); | ||
| void translate_1_to_2(const R1_RES&, R2_RES&); |
There was a problem hiding this comment.
These should be able to reuse the conversion functions already being generated for messages. The request and response are normal messages - the only difference is that they are in the srv namespace rather then msg.
There was a problem hiding this comment.
They do reuse those generated functions. They call convert*() functions for all non-primitive data types.
If you mean, that we could use that template generating convert*() to generate functions converting requests and responses, it is possible but not that trivial. I would need to rewrite this python script and I do not have time to do it now.
There was a problem hiding this comment.
Yes, currently the implementation of these functions iterate over the fields. I think we can get rid of this of we expand the already existing message templates for the request / response. I will look into it...
| void translate_1_to_2(const R1_REQ&, R2_REQ&); | ||
| void translate_1_to_2(const R1_RES&, R2_RES&); | ||
| void translate_2_to_1(R1_REQ&, const R2_REQ&); | ||
| void translate_2_to_1(R1_RES&, const R2_RES&); |
There was a problem hiding this comment.
Please swap the argument order to match the name of the functions. Might become obsolete with the comment above.
There was a problem hiding this comment.
I swapped the arguments.
| R1_TYPE srv; | ||
| translate_2_to_1(srv.request, *request); | ||
| if (client.call(srv)) | ||
| { |
There was a problem hiding this comment.
Please place the { and } within functions not on a separate line to match the code style of the rest of the file.
| for export in pkg.exports: | ||
| if export.tagname != 'ros1_bridge': | ||
| continue | ||
| if 'service_mapping_rules' not in export.attributes: |
There was a problem hiding this comment.
Please avoid a second different export for these mappings. They should be specified in a single mapping file together with the message mapping.
| 'ros1_service_name', | ||
| 'ros2_package_name', | ||
| 'ros2_message_name', | ||
| 'ros2_service_name', |
There was a problem hiding this comment.
A single mapping shouldn't be able to have a message name as well as a service name.
There was a problem hiding this comment.
I changed conditionals so it is either message mapping or service mapping, never both at the same time.
There was a problem hiding this comment.
After all, I created two separate classes: MessageMappingRule and ServiceMappingRule.
| "type": ros2_type.rstrip("[]"), | ||
| "name": ros2_name, | ||
| } | ||
| }) |
There was a problem hiding this comment.
This custom code shouldn't be necessary. Messages can already be converted between ROS 1 and ROS 2. There shouldn't be a need to reimplement this.
There was a problem hiding this comment.
As I mentioned before, it is possible to unify some functions in this script but it might not be that easy and I do not have time to do it now.
| if (factory) { | ||
| try { | ||
| service_bridges_2_to_1[name] = factory->service_bridge_2_to_1(ros1_node, ros2_node, name); | ||
| // printf("Created 2 to 1 bridge for service %s\n", name.data()); |
There was a problem hiding this comment.
These messages should be printed (same as for pub / sub) so that the user sees what is happening.
| self.assertEqual(None, self.bridge.poll(), "Bridge exited prematurely") | ||
|
|
||
| if __name__ == '__main__': | ||
| unittest.main() |
There was a problem hiding this comment.
Please use 4 space indentation for Python code (see PEP8).
|
Building the package also results in compiler warning about unused variables ( |
| # Shell C: | ||
| . <ros-install-dir>/setup.bash | ||
| export ROS_MASTER_URI=http://localhost:11311 | ||
| <ros-install-dir>/lib/roscpp_tutorials/add_two_ints_server |
There was a problem hiding this comment.
This line should use rosrun to start the node.
|
It works for me when starting a ROS 1 server and a ROS 2 client. But when I stop the ROS 1 server and start it again, the ROS 2 client doesn't find the server anymore. |
|
I committed a fix for the merge conflict. |
|
@haueck Please let me know when you will have time to address the comments. Depending on the timeline we might merge the patch as is in order to get it in before the beta freeze and the comments need to be addressed in a follow up PR. |
|
I will merge the current state for now. Please create a follow up PR soon. |
|
@dirk-thomas, thank you for the review!
I didn't use variables with those names, no idea what it is.
@dhood already asked about it:
I think I will finish rework tomorrow. |
|
Thank you for the quick update! |
|
FYI the unused variable warnings referred to come from the generated files e.g.: |
* Added support for bridging services * Added tests and fixes after the review - printing errors to stderr - replaced boost library with std - fixed indentation in templates - support for a manual service matching - simplified an example in README * Fixed issues after a review - Service factory does not raise errors anymore - Handling exceptions while creating/removing bridges - Fixed syntax in index.rst * Updated services to use separate compilation units
* Removed separate file for mapping services * Other minor changes
* Removed separate file for mapping services * Other minor changes
|
New pull requests: #48 ros2/examples#153 |
Rework after the review (#36)
|
The PR has leads to a crash of the bridge whenever any topic happens to be of length 4. Consider the following example: One possible solution is to explicitly filter out |
* Removed separate file for mapping services * Other minor changes
|
@Karsten1987, thank you for this information! I've created a fix for the issue #58 |
#33