Git Product home page Git Product logo

Comments (3)

minggangw avatar minggangw commented on July 24, 2024

After the call_async was introduced, I am not sure the code snippet above is right. Please correct me if I am wrong.

from rclpy.

sloretz avatar sloretz commented on July 24, 2024

Hi @minggangw thanks for the bug report. I'll close this since it looks to be working as intended. It blocks forever because there isn't an executor running. An executor must be running to unblock client.call when a service response is received.

Another detail is cli.call(req) returns the response. The client no longer has a response attribute.

The smallest change to get the code working is to replace cli.call(req) with

    future = cli.call_async(req)
    rclpy.spin_until_future_complete(node, future)
    response = future.result()

That invokes a global executor which is single-threaded. If the global executor isn't good enough for you (say you'd like callbacks to run in multiple threads), then an executor will need to be started separately.

from example_interfaces.srv import AddTwoInts
from rclpy.executors import MultiThreadedExecutor

import rclpy
import threading


def run_executor(executor, node):
    executor.add_node(node)
    try:
        executor.spin()
    finally:
        executor.shutdown()


def main(args=None):
    rclpy.init(args=args)
    node = rclpy.create_node('minimal_client')
    cli = node.create_client(AddTwoInts, 'add_two_ints')

    # Run executor that uses a thread pool in another thread so main thread is free to do what it wants
    exec = MultiThreadedExecutor(num_threads=4)
    thread = threading.Thread(target=run_executor, args=(exec, node), daemon=True)
    thread.start()

    req = AddTwoInts.Request()
    req.a = 41
    req.b = 1
    while not cli.wait_for_service(timeout_sec=1.0):
        node.get_logger().info('service not available, waiting again...')

    response = cli.call(req)

    node.get_logger().info(
        'Result of add_two_ints: for %d + %d = %d' %
        (req.a, req.b, response.sum))

    node.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

Save this as client_call_example.py

  1. ros2 run examples_rclpy_minimal_service service
  2. python3 client_call_example.py

See also ros2/examples an example of a custom executor and compose multiple nodes in a single process.

from rclpy.

minggangw avatar minggangw commented on July 24, 2024

Thanks for your explanation @sloretz .

from rclpy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.