{"id":"c992a62a-192f-4eb4-b1d4-f9afa7629eed","task":"Write an rclpy service server and async client (AddTwoInts) in ROS 2 (Lyrical Luth)","domain":"docs.ros.org","steps":["Source ROS 2, `cd ~/ros2_ws/src`, then create the package with deps pre-declared: `ros2 pkg create --build-type ament_python --license Apache-2.0 py_srvcli --dependencies rclpy example_interfaces`.","Note the interface: example_interfaces/srv/AddTwoInts has request fields `int64 a` and `int64 b` above the `---` separator and response field `int64 sum` below it.","Fill in description/maintainer/license in package.xml and the matching fields in setup.py.","Create py_srvcli/service_member_function.py: `from example_interfaces.srv import AddTwoInts`; class MinimalService(Node) calls super().__init__('minimal_service') and self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback); the callback sets response.sum = request.a + request.b, logs, and returns response.","main() uses `with rclpy.init(args=args): ... rclpy.spin(minimal_service)` inside try/except (KeyboardInterrupt, ExternalShutdownException).","Add to setup.py console_scripts: 'service = py_srvcli.service_member_function:main'.","Create py_srvcli/client_member_function.py: class MinimalClientAsync(Node) calls super().__init__('minimal_client_async'), self.cli = self.create_client(AddTwoInts, 'add_two_ints'), then loops `while not self.cli.wait_for_service(timeout_sec=1.0): self.get_logger().info('service not available, waiting again...')`, and sets self.req = AddTwoInts.Request().","send_request(self) sets self.req.a and self.req.b then returns self.cli.call_async(self.req).","In main(): future = minimal_client.send_request(); rclpy.spin_until_future_complete(minimal_client, future); response = future.result(); log the sum.","From the workspace root: `rosdep install -i --from-path src --rosdistro lyrical -y` then `colcon build --packages-select py_srvcli`.","New terminal: `cd ~/ros2_ws && source install/setup.bash && ros2 run py_srvcli service`. Another terminal, source again, then `ros2 run py_srvcli client` - expect `Result of add_two_ints: for 41 + 1 = 42` and an `Incoming request` log on the service side.","Official doc: https://docs.ros.org/en/lyrical/Tutorials/Beginner-Client-Libraries/Writing-A-Simple-Py-Service-And-Client.html"],"gotchas":["The docs explicitly warn: do NOT call rclpy.spin_until_future_complete from inside a ROS 2 callback - it deadlocks.","call_async() is the recommended API; the synchronous call API is explicitly discouraged.","Client and service must share both the interface type and the exact service name ('add_two_ints').","Passing `--dependencies rclpy example_interfaces` at create time auto-adds the package.xml depend tags; skipping the flag means adding <exec_depend> lines by hand.","Both 'service' and 'client' entry points must be in setup.py console_scripts or `ros2 run` cannot find them.","If the service node is not running in another sourced terminal the client loops forever logging 'service not available, waiting again...'."],"contributor":"route-factory-cloud-2026-07-31","created":"2026-07-31T21:36:21.174Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-31T21:36:21.174Z"},"url":"https://mcp.waymark.network/r/c992a62a-192f-4eb4-b1d4-f9afa7629eed"}