Skip to content
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

Is there a direct way to communicate XRCE requesters and repliers and ROS-2 node via Micro-ROS agent #358

Open
arshPratap opened this issue Jun 6, 2023 · 6 comments
Assignees

Comments

@arshPratap
Copy link

Currently I am trying to recreate the ReplyAdder example to communicate with ROS-2 nodes and was fairly successful in doing so with the ROS-2 nodes via integration services. My current question is that is there a way to directly communicate with ROS-2 nodes using the micro-ros agent (similar to how it was tackled in #250 ).
Based on the docs , my current replier configuration is as follows :

    const char* replier_xml = "<dds>"
            "<replier profile_name=\"rr/my_requester\""
            "service_name=\"rs/AddTwoInts\""
            "request_type=\"example_interfaces::srv::dds_::AddTwoInts_Request\""
            "reply_type=\"example_interfaces::srv::dds_::AddTwoInts_Response\">"
            "</replier>"
            "</dds>";

But on the ROS-2 side there is no corresponding service listed when I run : ros2 service list

Any ideas how to proceed with this ?
Thanks

@arshPratap
Copy link
Author

@pablogs9 any idea how to proceed with this ?

@Acuadros95 Acuadros95 self-assigned this Jun 28, 2023
@arshPratap
Copy link
Author

@Acuadros95 any updates on this ?
I would really like to know how to proceed with this issue

@pablogs9
Copy link
Member

Hello @arshPratap have you considered taking a look at micro-ROS RWM, there we are using XRCE to create ROS 2 interoperable services. Probably following the same approach, you will be able to use ROS 2 services directly from XRCE: https://github.com/micro-ROS/rmw_microxrcedds/blob/bc4eb312ac4601a4137c35f4a56b9b83b4b18339/rmw_microxrcedds_c/src/rmw_service.c#L30

@arshPratap
Copy link
Author

arshPratap commented Jul 20, 2023

Thanks for the response @pablogs9
I am currently going through the code .. if possible could this implementation be further strecthed to use ros2-actions ?

@srmainwaring
Copy link
Contributor

Here's how we solved this for the DDS client implementation used in ArduPilot's AP_DDS library, using the ArmMotors service definition as an example:

ROS 2 service definition: ardupilot_msgs/srv/ArmMotors.srv

# This service requests the vehicle to arm or disarm its motors.

# Set true to arm motors, false to disarm motors.
bool arm
---
# True if arming/disarming request for motors was successful , false otherwise. 
bool result

IDL:

// generated from rosidl_adapter/resource/srv.idl.em
// with input from ardupilot_msgs/srv/ArmMotors.srv
// generated code does not contain a copyright notice


module ardupilot_msgs {
  module srv {
    struct ArmMotors_Request {
      @verbatim (language="comment", text=
        "This service requests the vehicle to arm or disarm its motors." "\n"
        "Set true to arm motors, false to disarm motors.")
      boolean arm;
    };
    @verbatim (language="comment", text=
      "True if arming/disarming request for motors was successful , false otherwise. ")
    struct ArmMotors_Response {
      boolean result;
    };
  };
};

The micro XRCE DDS client creates the service Replier using uxr_buffer_create_replier_ref, and the key to auto mapping the DDS messages to ROS 2 is using the following naming in the refs file:

<?xml version="1.0"?>
<profiles>
  <participant profile_name="participant_profile">
    <rtps>
      <name>ardupilot_dds</name>
    </rtps>
  </participant>
  ...
  <replier
      profile_name="arm_motors__replier"
      service_name="rs/ap/arm_motorsService"
      request_type="ardupilot_msgs::srv::dds_::ArmMotors_Request_"
      reply_type="ardupilot_msgs::srv::dds_::ArmMotors_Response_">
    <request_topic_name>rq/ap/arm_motorsRequest</request_topic_name>
    <reply_topic_name>rr/ap/arm_motorsReply</reply_topic_name>
  </replier>
</profiles>

with this choice the ArmMotors service may be called from the ROS 2 CLI without the need to run an Integration Service instance:

$ ros2 service call /ap/arm_motors ardupilot_msgs/srv/ArmMotors "{arm: True}"
requester: making request: ardupilot_msgs.srv.ArmMotors_Request(arm=True)

response:
ardupilot_msgs.srv.ArmMotors_Response(result=True)

@arshPratap
Copy link
Author

Yup can confirm that the approach works.. Thanks a lot for the help @srmainwaring

Here's how we solved this for the DDS client implementation used in ArduPilot's AP_DDS library, using the ArmMotors service definition as an example:

ROS 2 service definition: ardupilot_msgs/srv/ArmMotors.srv

# This service requests the vehicle to arm or disarm its motors.

# Set true to arm motors, false to disarm motors.
bool arm
---
# True if arming/disarming request for motors was successful , false otherwise. 
bool result

IDL:

// generated from rosidl_adapter/resource/srv.idl.em
// with input from ardupilot_msgs/srv/ArmMotors.srv
// generated code does not contain a copyright notice


module ardupilot_msgs {
  module srv {
    struct ArmMotors_Request {
      @verbatim (language="comment", text=
        "This service requests the vehicle to arm or disarm its motors." "\n"
        "Set true to arm motors, false to disarm motors.")
      boolean arm;
    };
    @verbatim (language="comment", text=
      "True if arming/disarming request for motors was successful , false otherwise. ")
    struct ArmMotors_Response {
      boolean result;
    };
  };
};

The micro XRCE DDS client creates the service Replier using uxr_buffer_create_replier_ref, and the key to auto mapping the DDS messages to ROS 2 is using the following naming in the refs file:

<?xml version="1.0"?>
<profiles>
  <participant profile_name="participant_profile">
    <rtps>
      <name>ardupilot_dds</name>
    </rtps>
  </participant>
  ...
  <replier
      profile_name="arm_motors__replier"
      service_name="rs/ap/arm_motorsService"
      request_type="ardupilot_msgs::srv::dds_::ArmMotors_Request_"
      reply_type="ardupilot_msgs::srv::dds_::ArmMotors_Response_">
    <request_topic_name>rq/ap/arm_motorsRequest</request_topic_name>
    <reply_topic_name>rr/ap/arm_motorsReply</reply_topic_name>
  </replier>
</profiles>

with this choice the ArmMotors service may be called from the ROS 2 CLI without the need to run an Integration Service instance:

$ ros2 service call /ap/arm_motors ardupilot_msgs/srv/ArmMotors "{arm: True}"
requester: making request: ardupilot_msgs.srv.ArmMotors_Request(arm=True)

response:
ardupilot_msgs.srv.ArmMotors_Response(result=True)

Yup can confirm that the approach works.. Thanks a lot for the help @srmainwaring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants