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

Add overloaded Request for non-blocking calls using abstract types #386

Open
wants to merge 3 commits into
base: gz-transport12
Choose a base branch
from

Conversation

srmainwaring
Copy link

@srmainwaring srmainwaring commented Feb 24, 2023

🎉 New feature

Summary

Add an overloaded Request method to the class Node that accepts references to abstract request and response types, specifically the type google::protobuf::Message.

The addition is to support a non-blocking version of the service call used in cmdServiceReq (gz-transport/src/cmd/gz.hh). The existing Request methods accepting a callback function all require a concrete type as they call Request().GetTypeName() and Response().GetTypeName(). This does not work when the request or response types are the abstract base class google::protobuf::Message. The instance calls _request->GetTypeName() and _response->GetTypeName() on the other hand are valid, and this is what the new overload function uses.

There is also a change to the template specialisation of ReqHandler to support callbacks.

Test it

Tasks

  • Change target to main because of ABI changes.
  • Add a test to gz-transport

The current use case is in a downstream project providing python bindings for gz-msgs and gz-transport: https://github.com/srmainwaring/gz-python/tree/srmainwaring/service-request

At present only blocking service requests are supported. The Python bindings use the same approach as the gz service command line tools. This PR allows asynchronous callbacks as well. The example below is for a service that allows the PID settings of a joint controller to be updated in Python at runtime. Both blocking and non-blocking versions of the call are demonstrated.

import time

from gz.msgs.pid_pb2 import PID

from gz.transport import Node

# service response callback 
def rep_cb(msg, result):
    print("Result: {}".format(result))
    print("Response: {}".format(msg))

def main():
    # create a transport node
    node = Node()
    service = "/model/iris_with_ardupilot/"\
              "joint/iris_with_standoffs::rotor_0_joint/pid"
    req_type_name = PID.DESCRIPTOR.full_name
    rep_type_name = PID.DESCRIPTOR.full_name

    # populate PID message
    req = PID()
    req.p_gain_optional.data = 0.2
    req.i_gain_optional.data = 0.0
    req.d_gain_optional.data = 0.0
    req.i_max_optional.data = 1.0
    req.i_min_optional.data = -1.0
    req.limit_optional.data = 10.0

    # timeout in ms
    timeout = 1000

    # call service (blocking)
    print("Blocking service call")
    executed = node.request(service, req, timeout, rep_type_name)

    # update PID so we can verify second call
    req.p_gain_optional.data = 0.3

    # call service (non-blocking)
    print("Non-blocking service call")
    executed = node.request(service, req, rep_cb, rep_type_name)

    # wait for response before exiting
    time.sleep(timeout/1000)
    print("Done")

if __name__ == "__main__":
    main()

Expected console output:

% ~/Code/osrf/gz_garden_ws/src/gz-python/python/pid_service.py
Blocking service call
Non-blocking service call
Result: True
Response: p_gain_optional {
  data: 0.3
}
i_gain_optional {
}
d_gain_optional {
}
i_max_optional {
  data: 1.0
}
i_min_optional {
  data: -1.0
}
limit_optional {
  data: 10.0
}

Done

Expected gz sim output (using a modified version of the ArduPilot plugin: srmainwaring/ardupilot_gazebo-1@c938fd5):

[Msg] Updated PIDs for [iris_with_standoffs::rotor_0_joint]
p_gain: 0.2
i_gain: 0
d_gain: 0
i_max: 1
i_min: -1
cmd_max: 10
cmd_min: -10
[Msg] Updated PIDs for [iris_with_standoffs::rotor_0_joint]
p_gain: 0.3
i_gain: 0
d_gain: 0
i_max: 1
i_min: -1
cmd_max: 10
cmd_min: -10

Checklist

  • Signed all commits for DCO
  • Added tests
  • Added example and/or tutorial
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers

Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining Signed-off-by messages.

@github-actions github-actions bot added the 🌱 garden Ignition Garden label Feb 24, 2023
@srmainwaring srmainwaring changed the title Add overloaded Request method to Node for non-blocking calls using abstract types Add overloaded Request method non-blocking calls using abstract types Feb 24, 2023
@srmainwaring srmainwaring changed the title Add overloaded Request method non-blocking calls using abstract types Add overloaded Request for non-blocking calls using abstract types Feb 24, 2023
@srmainwaring srmainwaring mentioned this pull request Feb 24, 2023
@codecov
Copy link

codecov bot commented Feb 24, 2023

Codecov Report

Attention: Patch coverage is 16.66667% with 15 lines in your changes missing coverage. Please review.

Project coverage is 87.06%. Comparing base (1db0afe) to head (c3898f4).
Report is 9 commits behind head on gz-transport12.

Files Patch % Lines
include/gz/transport/ReqHandler.hh 16.66% 15 Missing ⚠️
Additional details and impacted files
@@                Coverage Diff                 @@
##           gz-transport12     #386      +/-   ##
==================================================
- Coverage           87.23%   87.06%   -0.18%     
==================================================
  Files                  60       60              
  Lines                5211     5227      +16     
==================================================
+ Hits                 4546     4551       +5     
- Misses                665      676      +11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Collaborator

@caguero caguero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the patch @srmainwaring ! Could you also add a C++ example under example/ that exercises the new Request() API?

@srmainwaring
Copy link
Author

Could you also add a C++ example under example/ that exercises the new Request() API?

Thanks for the review @caguero - yes will add a test + example.

@mjcarroll
Copy link
Contributor

@srmainwaring friendly ping on the test + example so we can get this in before code freeze.

@azeey azeey removed the beta Targeting beta release of upcoming collection label Aug 25, 2023
…stract types.

- Add overloaded method to Node.
- Update specialisation of ReqHandler to handle callbacks using google::protobuf::Message.

Signed-off-by: Rhys Mainwaring <[email protected]>
@srmainwaring srmainwaring force-pushed the srmainwaring/12/node-abstract-request branch from f5c8bf9 to 73ef858 Compare September 3, 2023 10:12
@caguero
Copy link
Collaborator

caguero commented Jan 4, 2024

@srmainwaring , friendly reminder. I can help you with a test if you commit an example with the new functionality.

@azeey azeey added beta Targeting beta release of upcoming collection and removed beta Targeting beta release of upcoming collection labels Jul 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🌱 garden Ignition Garden
Projects
Status: In progress
Development

Successfully merging this pull request may close these issues.

5 participants