diff --git a/demo_nodes_py/demo_nodes_py/events/matched_event_detect.py b/demo_nodes_py/demo_nodes_py/events/matched_event_detect.py
index 45bbd6db9..ff1a6d89a 100644
--- a/demo_nodes_py/demo_nodes_py/events/matched_event_detect.py
+++ b/demo_nodes_py/demo_nodes_py/events/matched_event_detect.py
@@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.msg import String
import rclpy
from rclpy.event_handler import PublisherEventCallbacks
@@ -39,20 +41,21 @@
class MatchedEventDetectNode(Node):
- def __init__(self, pub_topic_name: String, sub_topic_name: String):
+ def __init__(self, pub_topic_name: str, sub_topic_name: str) -> None:
super().__init__('matched_event_detection_node')
self.__any_subscription_connected = False # used for publisher event
self.__any_publisher_connected = False # used for subscription event
+ self.future: Future[bool] = Future()
pub_event_callback = PublisherEventCallbacks(matched=self.__pub_matched_event_callback)
self.pub = self.create_publisher(String, pub_topic_name, 10,
event_callbacks=pub_event_callback)
sub_event_callback = SubscriptionEventCallbacks(matched=self.__sub_matched_event_callback)
- self.sub = self.create_subscription(String, sub_topic_name, lambda msg: ...,
+ self.sub = self.create_subscription(String, sub_topic_name, lambda msg: None,
10, event_callbacks=sub_event_callback)
- def __pub_matched_event_callback(self, info: QoSPublisherMatchedInfo):
+ def __pub_matched_event_callback(self, info: QoSPublisherMatchedInfo) -> None:
if self.__any_subscription_connected:
if info.current_count == 0:
self.get_logger().info('Last subscription is disconnected.')
@@ -69,7 +72,7 @@ def __pub_matched_event_callback(self, info: QoSPublisherMatchedInfo):
self.future.set_result(True)
- def __sub_matched_event_callback(self, info: QoSSubscriptionMatchedInfo):
+ def __sub_matched_event_callback(self, info: QoSSubscriptionMatchedInfo) -> None:
if self.__any_publisher_connected:
if info.current_count == 0:
self.get_logger().info('Last publisher is disconnected.')
@@ -86,25 +89,25 @@ def __sub_matched_event_callback(self, info: QoSSubscriptionMatchedInfo):
self.future.set_result(True)
- def get_future(self):
+ def get_future(self) -> Future[bool]:
self.future = Future()
return self.future
class MultiSubNode(Node):
- def __init__(self, topic_name: String):
+ def __init__(self, topic_name: str) -> None:
super().__init__('multi_sub_node')
- self.__subs = []
+ self.__subs: list[Subscription[String]] = []
self.__topic_name = topic_name
- def create_one_sub(self) -> Subscription:
+ def create_one_sub(self) -> Subscription[String]:
self.get_logger().info('Create a new subscription.')
- sub = self.create_subscription(String, self.__topic_name, lambda msg: ..., 10)
+ sub = self.create_subscription(String, self.__topic_name, lambda msg: None, 10)
self.__subs.append(sub)
return sub
- def destroy_one_sub(self, sub: Subscription):
+ def destroy_one_sub(self, sub: Subscription[String]) -> None:
if sub in self.__subs:
self.get_logger().info('Destroy a subscription.')
@@ -114,18 +117,18 @@ def destroy_one_sub(self, sub: Subscription):
class MultiPubNode(Node):
- def __init__(self, topic_name: String):
+ def __init__(self, topic_name: str) -> None:
super().__init__('multi_pub_node')
- self.__pubs = []
+ self.__pubs: list[Publisher[String]] = []
self.__topic_name = topic_name
- def create_one_pub(self) -> Publisher:
+ def create_one_pub(self) -> Publisher[String]:
self.get_logger().info('Create a new publisher.')
pub = self.create_publisher(String, self.__topic_name, 10)
self.__pubs.append(pub)
return pub
- def destroy_one_pub(self, pub: Publisher):
+ def destroy_one_pub(self, pub: Publisher[String]) -> None:
if pub in self.__pubs:
self.get_logger().info('Destroy a publisher.')
@@ -133,7 +136,7 @@ def destroy_one_pub(self, pub: Publisher):
self.destroy_publisher(pub)
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
topic_name_for_detect_pub_matched_event = 'pub_topic_matched_event_detect'
diff --git a/demo_nodes_py/demo_nodes_py/logging/use_logger_service.py b/demo_nodes_py/demo_nodes_py/logging/use_logger_service.py
index ce8aa22be..6bf678e62 100644
--- a/demo_nodes_py/demo_nodes_py/logging/use_logger_service.py
+++ b/demo_nodes_py/demo_nodes_py/logging/use_logger_service.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2023 Sony Group Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,6 +16,8 @@
import argparse
import threading
import time
+from typing import Literal
+from typing import Union
from example_interfaces.msg import String
from rcl_interfaces.msg import LoggerLevel
@@ -66,12 +69,12 @@
class LoggerServiceNode(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('LoggerServiceNode', enable_logger_service=True)
self.child_logger = self.get_logger().get_child('child')
self.sub = self.create_subscription(String, 'output', self.callback, 10)
- def callback(self, msg):
+ def callback(self, msg: String) -> None:
self.get_logger().debug(msg.data + ' with DEBUG logger level.')
self.get_logger().info(msg.data + ' with INFO logger level.')
self.get_logger().warning(msg.data + ' with WARN logger level.')
@@ -84,7 +87,7 @@ def callback(self, msg):
class TestNode(Node):
- def __init__(self, remote_node_name):
+ def __init__(self, remote_node_name: str) -> None:
super().__init__('TestNode')
self.pub = self.create_publisher(String, 'output', 10)
self.logger_get_client = self.create_client(
@@ -93,7 +96,9 @@ def __init__(self, remote_node_name):
SetLoggerLevels, remote_node_name + '/set_logger_levels')
self._remote_node_name = remote_node_name
- def set_logger_level_on_remote_node(self, logger_level, logger_name='') -> bool:
+ def set_logger_level_on_remote_node(
+ self, logger_level: int, logger_name: str = '',
+ ) -> bool:
if not self._logger_set_client.service_is_ready():
return False
@@ -117,37 +122,42 @@ def set_logger_level_on_remote_node(self, logger_level, logger_name='') -> bool:
return True
- def get_logger_level_on_remote_node(self, logger_name=''):
+ def get_logger_level_on_remote_node(
+ self, logger_name: str = '',
+ ) -> Union[tuple[Literal[False], None], tuple[Literal[True], int]]:
if not self.logger_get_client.service_is_ready():
- return [False, None]
+ return False, None
request = GetLoggerLevels.Request()
- request.names.append(logger_name if logger_name else self._remote_node_name)
+ name = logger_name if logger_name else self._remote_node_name
+ request.names.append(name)
future = self.logger_get_client.call_async(request)
rclpy.spin_until_future_complete(self, future)
ret_results = future.result()
if not ret_results:
- return [False, None]
+ return False, None
- return [True, ret_results.levels[0].level]
+ return True, ret_results.levels[0].level
-def get_logger_level_func(test_node, child_logger_name):
- ret, level = test_node.get_logger_level_on_remote_node()
+def get_logger_level_func(test_node: TestNode, child_logger_name: str) -> None:
+ results = test_node.get_logger_level_on_remote_node()
+ ret, level = results
if ret:
test_node.get_logger().info('Current logger level: ' + str(level))
else:
test_node.get_logger().error('Failed to get logger level via logger service !')
- ret, child_level = test_node.get_logger_level_on_remote_node(child_logger_name)
+ child_results = test_node.get_logger_level_on_remote_node(child_logger_name)
+ ret, child_level = child_results
if ret:
test_node.get_logger().info('Current child logger level: ' + str(child_level))
else:
test_node.get_logger().error('Failed to get child logger level via logger service !')
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
# Check for --service-only flag before ROS 2 consumes the arguments
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--service-only', action='store_true', default=False)
diff --git a/demo_nodes_py/demo_nodes_py/parameters/async_param_client.py b/demo_nodes_py/demo_nodes_py/parameters/async_param_client.py
index 7b014a027..3f0cacda9 100644
--- a/demo_nodes_py/demo_nodes_py/parameters/async_param_client.py
+++ b/demo_nodes_py/demo_nodes_py/parameters/async_param_client.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2022 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
+from typing import Union
from ament_index_python import get_package_share_directory
import rclpy
@@ -23,7 +25,7 @@
from rclpy.parameter_client import AsyncParameterClient
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init():
node = rclpy.create_node('async_param_client')
@@ -44,63 +46,64 @@ def main(args=None):
rclpy.spin_until_future_complete(node, future)
set_parameters_result = future.result()
if set_parameters_result is not None:
- for i, v in enumerate(set_parameters_result.results):
+ for i, set_param_result in enumerate(set_parameters_result.results):
logger.info(f' {param_list[i]}:')
- logger.info(f' successful: {v.successful}')
+ logger.info(f' successful: {set_param_result.successful}')
else:
logger.error(f'Error setting parameters: {future.exception()}')
logger.info('Listing Parameters:')
- future = client.list_parameters(param_list, 10)
- rclpy.spin_until_future_complete(node, future)
- list_parameters_result = future.result()
+ list_future = client.list_parameters(param_list, 10)
+ rclpy.spin_until_future_complete(node, list_future)
+ list_parameters_result = list_future.result()
if list_parameters_result is not None:
for param_name in list_parameters_result.result.names:
logger.info(f' - {param_name}')
else:
- logger.error(f'Error listing parameters: {future.exception()}')
+ logger.error(f'Error listing parameters: {list_future.exception()}')
logger.info('Getting parameters:')
- future = client.get_parameters(param_list)
- rclpy.spin_until_future_complete(node, future)
- get_parameters_result = future.result()
+ get_future = client.get_parameters(param_list)
+ rclpy.spin_until_future_complete(node, get_future)
+ get_parameters_result = get_future.result()
if get_parameters_result is not None:
- for i, v in enumerate(get_parameters_result.values):
- logger.info(f' - {param_list[i]}: {parameter_value_to_python(v)}')
+ for i, get_param_value in enumerate(get_parameters_result.values):
+ logger.info(
+ f' - {param_list[i]}: {parameter_value_to_python(get_param_value)}')
else:
- logger.error(f'Error getting parameters: {future.exception()}')
+ logger.error(f'Error getting parameters: {get_future.exception()}')
logger.info('Loading parameters: ')
param_dir = get_package_share_directory('demo_nodes_py')
param_file_path = os.path.join(param_dir, 'params.yaml')
- future = client.load_parameter_file(param_file_path)
- rclpy.spin_until_future_complete(node, future)
- load_parameter_results = future.result()
+ load_future = client.load_parameter_file(param_file_path)
+ rclpy.spin_until_future_complete(node, load_future)
+ load_parameter_results = load_future.result()
if load_parameter_results is not None:
param_file_dict = parameter_dict_from_yaml_file(
param_file_path, False, target_nodes=['parameter_blackboard'])
- for i, v in enumerate(param_file_dict.keys()):
- logger.info(f' {v}:')
+ for i, k in enumerate(param_file_dict.keys()):
+ logger.info(f' {k}:')
logger.info(f' successful: '
f'{load_parameter_results.results[i].successful}')
logger.info(f' value: '
- f'{parameter_value_to_python(param_file_dict[v].value)}')
+ f'{parameter_value_to_python(param_file_dict[k].value)}')
else:
- logger.error(f'Error loading parameters: {future.exception()}')
+ logger.error(f'Error loading parameters: {load_future.exception()}')
logger.info('Deleting parameters: ')
params_to_delete = ['other_int_parameter', 'other_string_parameter',
'string_parameter']
- future = client.delete_parameters(params_to_delete)
- rclpy.spin_until_future_complete(node, future)
- delete_parameters_result = future.result()
+ del_future = client.delete_parameters(params_to_delete)
+ rclpy.spin_until_future_complete(node, del_future)
+ delete_parameters_result = del_future.result()
if delete_parameters_result is not None:
- for i, v in enumerate(delete_parameters_result.results):
+ for i, del_param_result in enumerate(delete_parameters_result.results):
logger.info(f' {params_to_delete[i]}:')
- logger.info(f' successful: {v.successful}')
- logger.info(f' reason: {v.reason}')
+ logger.info(f' successful: {del_param_result.successful}')
+ logger.info(f' reason: {del_param_result.reason}')
else:
- logger.error(f'Error deleting parameters: {future.exception()}')
+ logger.error(f'Error deleting parameters: {del_future.exception()}')
except (KeyboardInterrupt, ExternalShutdownException):
pass
diff --git a/demo_nodes_py/demo_nodes_py/parameters/set_parameters_callback.py b/demo_nodes_py/demo_nodes_py/parameters/set_parameters_callback.py
index 884a74721..2c8f85fc5 100644
--- a/demo_nodes_py/demo_nodes_py/parameters/set_parameters_callback.py
+++ b/demo_nodes_py/demo_nodes_py/parameters/set_parameters_callback.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2022 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from rcl_interfaces.msg import SetParametersResult
import rclpy
@@ -26,9 +29,11 @@
# node for demonstrating correct usage of pre_set, on_set
# and post_set parameter callbacks
+
+
class SetParametersCallback(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('set_parameters_callback')
# tracks 'param1' value
@@ -38,7 +43,9 @@ def __init__(self):
# setting another parameter from the callback is possible
# we expect the callback to be called for param2
- def pre_set_parameter_callback(parameter_list):
+ def pre_set_parameter_callback(
+ parameter_list: list[Parameter[float]],
+ ) -> list[Parameter[float]]:
modified_parameters = parameter_list.copy()
for param in parameter_list:
if param.name == 'param1':
@@ -47,7 +54,9 @@ def pre_set_parameter_callback(parameter_list):
return modified_parameters
# validation callback
- def on_set_parameter_callback(parameter_list):
+ def on_set_parameter_callback(
+ parameter_list: list[Parameter[float]],
+ ) -> SetParametersResult:
result = SetParametersResult()
for param in parameter_list:
if param.name == 'param1':
@@ -60,7 +69,9 @@ def on_set_parameter_callback(parameter_list):
return result
# can change internally tracked class attributes
- def post_set_parameter_callback(parameter_list):
+ def post_set_parameter_callback(
+ parameter_list: list[Parameter[float]],
+ ) -> None:
for param in parameter_list:
if param.name == 'param1':
self.internal_tracked_param_1 = param.value
@@ -72,7 +83,7 @@ def post_set_parameter_callback(parameter_list):
self.add_post_set_parameters_callback(post_set_parameter_callback)
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
node = SetParametersCallback()
diff --git a/demo_nodes_py/demo_nodes_py/services/add_two_ints_client.py b/demo_nodes_py/demo_nodes_py/services/add_two_ints_client.py
index 07ca330dc..34edabd07 100644
--- a/demo_nodes_py/demo_nodes_py/services/add_two_ints_client.py
+++ b/demo_nodes_py/demo_nodes_py/services/add_two_ints_client.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2016 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,13 +13,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.executors import ExternalShutdownException
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
node = rclpy.create_node('add_two_ints_client')
@@ -31,8 +34,10 @@ def main(args=None):
req.b = 3
future = cli.call_async(req)
rclpy.spin_until_future_complete(node, future)
- if future.result() is not None:
- node.get_logger().info('Result of add_two_ints: %d' % future.result().sum)
+ result = future.result()
+ if result is not None:
+ res_sum = result.sum
+ node.get_logger().info('Result of add_two_ints: %d' % res_sum)
else:
node.get_logger().error('Exception while calling service: %r' % future.exception())
except (KeyboardInterrupt, ExternalShutdownException):
diff --git a/demo_nodes_py/demo_nodes_py/services/add_two_ints_client_async.py b/demo_nodes_py/demo_nodes_py/services/add_two_ints_client_async.py
index 8412df405..6d88191b7 100644
--- a/demo_nodes_py/demo_nodes_py/services/add_two_ints_client_async.py
+++ b/demo_nodes_py/demo_nodes_py/services/add_two_ints_client_async.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2016 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,13 +13,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.executors import ExternalShutdownException
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
node = rclpy.create_node('add_two_ints_client')
@@ -37,8 +40,10 @@ def main(args=None):
while rclpy.ok():
rclpy.spin_once(node)
if future.done():
- if future.result() is not None:
- logger.info('Result of add_two_ints: %d' % future.result().sum)
+ result = future.result()
+ if result is not None:
+ res_sum = result.sum
+ logger.info('Result of add_two_ints: %d' % res_sum)
else:
logger.error('Exception while calling service: %r' % future.exception())
break
diff --git a/demo_nodes_py/demo_nodes_py/services/add_two_ints_server.py b/demo_nodes_py/demo_nodes_py/services/add_two_ints_server.py
index 92799b666..d6d1c37f8 100644
--- a/demo_nodes_py/demo_nodes_py/services/add_two_ints_server.py
+++ b/demo_nodes_py/demo_nodes_py/services/add_two_ints_server.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2016 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.srv import AddTwoInts
import rclpy
@@ -21,18 +24,23 @@
class AddTwoIntsServer(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('add_two_ints_server')
- self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
-
- def add_two_ints_callback(self, request, response):
+ self.srv = self.create_service(
+ AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
+
+ def add_two_ints_callback(
+ self,
+ request: AddTwoInts.Request,
+ response: AddTwoInts.Response,
+ ) -> AddTwoInts.Response:
response.sum = request.a + request.b
self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))
return response
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
node = AddTwoIntsServer()
diff --git a/demo_nodes_py/demo_nodes_py/services/introspection.py b/demo_nodes_py/demo_nodes_py/services/introspection.py
index 4712902ff..f12bd5b26 100644
--- a/demo_nodes_py/demo_nodes_py/services/introspection.py
+++ b/demo_nodes_py/demo_nodes_py/services/introspection.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2023 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.srv import AddTwoInts
from rcl_interfaces.msg import SetParametersResult
@@ -22,6 +25,7 @@
from rclpy.parameter import Parameter
from rclpy.qos import qos_profile_system_default
from rclpy.service_introspection import ServiceIntrospectionState
+from rclpy.task import Future
# This demo program shows how to configure client and service introspection
@@ -69,7 +73,11 @@
# In either case, service introspection data can be seen by running:
# ros2 topic echo /add_two_ints/_service_event
-def check_parameter(parameter_list, parameter_name):
+
+def check_parameter(
+ parameter_list: list[Parameter[str]],
+ parameter_name: str
+) -> SetParametersResult:
result = SetParametersResult()
result.successful = True
for param in parameter_list:
@@ -91,10 +99,16 @@ def check_parameter(parameter_list, parameter_name):
class IntrospectionClientNode(Node):
- def on_set_parameters_callback(self, parameter_list):
+ def on_set_parameters_callback(
+ self,
+ parameter_list: list[Parameter[str]],
+ ) -> SetParametersResult:
return check_parameter(parameter_list, 'client_configure_introspection')
- def on_post_set_parameters_callback(self, parameter_list):
+ def on_post_set_parameters_callback(
+ self,
+ parameter_list: list[Parameter[str]],
+ ) -> None:
for param in parameter_list:
if param.name != 'client_configure_introspection':
continue
@@ -111,7 +125,7 @@ def on_post_set_parameters_callback(self, parameter_list):
introspection_state)
break
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('introspection_client')
self.cli = self.create_client(AddTwoInts, 'add_two_ints')
@@ -121,9 +135,9 @@ def __init__(self):
self.declare_parameter('client_configure_introspection', 'disabled')
self.timer = self.create_timer(0.5, self.timer_callback)
- self.future = None
+ self.future: Union[Future[AddTwoInts.Response], None] = None
- def timer_callback(self):
+ def timer_callback(self) -> None:
if not self.cli.service_is_ready():
return
@@ -139,8 +153,10 @@ def timer_callback(self):
if not self.future.done():
return
- if self.future.result() is not None:
- self.get_logger().info('Result of add_two_ints: %d' % self.future.result().sum)
+ result = self.future.result()
+ if result is not None:
+ res_sum = result.sum
+ self.get_logger().info('Result of add_two_ints: %d' % res_sum)
else:
self.get_logger().error('Exception calling service: %r' % self.future.exception())
@@ -149,10 +165,16 @@ def timer_callback(self):
class IntrospectionServiceNode(Node):
- def on_set_parameters_callback(self, parameter_list):
+ def on_set_parameters_callback(
+ self,
+ parameter_list: list[Parameter[str]],
+ ) -> SetParametersResult:
return check_parameter(parameter_list, 'service_configure_introspection')
- def on_post_set_parameters_callback(self, parameter_list):
+ def on_post_set_parameters_callback(
+ self,
+ parameter_list: list[Parameter[str]],
+ ) -> None:
for param in parameter_list:
if param.name != 'service_configure_introspection':
continue
@@ -169,23 +191,28 @@ def on_post_set_parameters_callback(self, parameter_list):
introspection_state)
break
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('introspection_service')
- self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
+ self.srv = self.create_service(
+ AddTwoInts, 'add_two_ints', self.add_two_ints_callback)
self.add_on_set_parameters_callback(self.on_set_parameters_callback)
self.add_post_set_parameters_callback(self.on_post_set_parameters_callback)
self.declare_parameter('service_configure_introspection', 'disabled')
- def add_two_ints_callback(self, request, response):
+ def add_two_ints_callback(
+ self,
+ request: AddTwoInts.Request,
+ response: AddTwoInts.Response,
+ ) -> AddTwoInts.Response:
response.sum = request.a + request.b
self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))
return response
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
service_node = IntrospectionServiceNode()
diff --git a/demo_nodes_py/demo_nodes_py/topics/listener.py b/demo_nodes_py/demo_nodes_py/topics/listener.py
index 9f4ea6171..6a6017ea3 100644
--- a/demo_nodes_py/demo_nodes_py/topics/listener.py
+++ b/demo_nodes_py/demo_nodes_py/topics/listener.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2016 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.msg import String
import rclpy
@@ -21,15 +24,16 @@
class Listener(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('listener')
- self.sub = self.create_subscription(String, 'chatter', self.chatter_callback, 10)
+ self.sub = self.create_subscription(
+ String, 'chatter', self.chatter_callback, 10)
- def chatter_callback(self, msg):
+ def chatter_callback(self, msg: String) -> None:
self.get_logger().info('I heard: [%s]' % msg.data)
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
node = Listener()
diff --git a/demo_nodes_py/demo_nodes_py/topics/listener_qos.py b/demo_nodes_py/demo_nodes_py/topics/listener_qos.py
index 95e134591..40e7f3802 100644
--- a/demo_nodes_py/demo_nodes_py/topics/listener_qos.py
+++ b/demo_nodes_py/demo_nodes_py/topics/listener_qos.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2016 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,7 +29,7 @@
class ListenerQos(Node):
- def __init__(self, qos_profile):
+ def __init__(self, qos_profile: QoSProfile) -> None:
super().__init__('listener_qos')
if qos_profile.reliability is QoSReliabilityPolicy.RELIABLE:
self.get_logger().info('Reliable listener')
@@ -37,11 +38,11 @@ def __init__(self, qos_profile):
self.sub = self.create_subscription(
String, 'chatter', self.chatter_callback, qos_profile)
- def chatter_callback(self, msg):
+ def chatter_callback(self, msg: String) -> None:
self.get_logger().info('I heard: [%s]' % msg.data)
-def main(argv=sys.argv[1:]):
+def main(argv: list[str] = sys.argv[1:]) -> None:
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
'--reliable', dest='reliable', action='store_true',
diff --git a/demo_nodes_py/demo_nodes_py/topics/listener_serialized.py b/demo_nodes_py/demo_nodes_py/topics/listener_serialized.py
index 25d49fc99..09a551cbd 100644
--- a/demo_nodes_py/demo_nodes_py/topics/listener_serialized.py
+++ b/demo_nodes_py/demo_nodes_py/topics/listener_serialized.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2018 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.msg import String
import rclpy
@@ -21,7 +24,7 @@
class SerializedSubscriber(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('serialized_subscriber')
self.subscription = self.create_subscription(
String,
@@ -32,11 +35,11 @@ def __init__(self):
# We're subscribing to the serialized bytes,
# not example_interfaces.msg.String
- def listener_callback(self, msg):
- self.get_logger().info('I heard: "%s"' % msg)
+ def listener_callback(self, msg: bytes) -> None:
+ self.get_logger().info('I heard: "%r"' % msg)
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
serialized_subscriber = SerializedSubscriber()
diff --git a/demo_nodes_py/demo_nodes_py/topics/talker.py b/demo_nodes_py/demo_nodes_py/topics/talker.py
index 026b22d10..4f16db25b 100644
--- a/demo_nodes_py/demo_nodes_py/topics/talker.py
+++ b/demo_nodes_py/demo_nodes_py/topics/talker.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2016 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,6 +13,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Union
+
from example_interfaces.msg import String
import rclpy
@@ -21,14 +24,14 @@
class Talker(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('talker')
self.i = 0
self.pub = self.create_publisher(String, 'chatter', 10)
timer_period = 1.0
self.tmr = self.create_timer(timer_period, self.timer_callback)
- def timer_callback(self):
+ def timer_callback(self) -> None:
msg = String()
msg.data = 'Hello World: {0}'.format(self.i)
self.i += 1
@@ -36,7 +39,7 @@ def timer_callback(self):
self.pub.publish(msg)
-def main(args=None):
+def main(args: Union[list[str], None] = None) -> None:
try:
with rclpy.init(args=args):
node = Talker()
diff --git a/demo_nodes_py/demo_nodes_py/topics/talker_qos.py b/demo_nodes_py/demo_nodes_py/topics/talker_qos.py
index 99c695e00..644b51b28 100644
--- a/demo_nodes_py/demo_nodes_py/topics/talker_qos.py
+++ b/demo_nodes_py/demo_nodes_py/topics/talker_qos.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
# Copyright 2016 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -28,9 +29,9 @@
class TalkerQos(Node):
- def __init__(self, qos_profile):
+ def __init__(self, qos_profile: QoSProfile) -> None:
super().__init__('talker_qos')
- self.i = 0
+ self.i: int = 0
if qos_profile.reliability is QoSReliabilityPolicy.RELIABLE:
self.get_logger().info('Reliable talker')
else:
@@ -40,7 +41,7 @@ def __init__(self, qos_profile):
timer_period = 1.0
self.tmr = self.create_timer(timer_period, self.timer_callback)
- def timer_callback(self):
+ def timer_callback(self) -> None:
msg = String()
msg.data = 'Hello World: {0}'.format(self.i)
self.i += 1
@@ -48,7 +49,7 @@ def timer_callback(self):
self.pub.publish(msg)
-def main(argv=sys.argv[1:]):
+def main(argv: list[str] = sys.argv[1:]) -> None:
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument(
'--reliable', dest='reliable', action='store_true',
diff --git a/demo_nodes_py/package.xml b/demo_nodes_py/package.xml
index c155a0a28..35bd968a3 100644
--- a/demo_nodes_py/package.xml
+++ b/demo_nodes_py/package.xml
@@ -26,6 +26,7 @@
ament_copyright
ament_flake8
ament_pep257
+ ament_mypy
ament_xmllint
python3-pytest
diff --git a/demo_nodes_py/test/test_copyright.py b/demo_nodes_py/test/test_copyright.py
index cc8ff03f7..1f8698345 100644
--- a/demo_nodes_py/test/test_copyright.py
+++ b/demo_nodes_py/test/test_copyright.py
@@ -18,6 +18,6 @@
@pytest.mark.copyright
@pytest.mark.linter
-def test_copyright():
+def test_copyright() -> None:
rc = main(argv=['.', 'test'])
assert rc == 0, 'Found errors'
diff --git a/demo_nodes_py/test/test_flake8.py b/demo_nodes_py/test/test_flake8.py
index 27ee1078f..eac16eef9 100644
--- a/demo_nodes_py/test/test_flake8.py
+++ b/demo_nodes_py/test/test_flake8.py
@@ -18,7 +18,7 @@
@pytest.mark.flake8
@pytest.mark.linter
-def test_flake8():
+def test_flake8() -> None:
rc, errors = main_with_errors(argv=[])
assert rc == 0, \
'Found %d code style errors / warnings:\n' % len(errors) + \
diff --git a/demo_nodes_py/test/test_mypy.py b/demo_nodes_py/test/test_mypy.py
new file mode 100644
index 000000000..8b1a09e35
--- /dev/null
+++ b/demo_nodes_py/test/test_mypy.py
@@ -0,0 +1,21 @@
+# Copyright 2026 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from ament_mypy.main import main
+
+
+def test_mypy() -> None:
+ rc = main(argv=['--ament-strict'])
+ assert rc == 0, 'Found code style errors / warnings'
diff --git a/demo_nodes_py/test/test_pep257.py b/demo_nodes_py/test/test_pep257.py
index b234a3840..b6808e1d8 100644
--- a/demo_nodes_py/test/test_pep257.py
+++ b/demo_nodes_py/test/test_pep257.py
@@ -18,6 +18,6 @@
@pytest.mark.linter
@pytest.mark.pep257
-def test_pep257():
+def test_pep257() -> None:
rc = main(argv=['.', 'test'])
assert rc == 0, 'Found code style errors / warnings'
diff --git a/quality_of_service_demo/rclpy/package.xml b/quality_of_service_demo/rclpy/package.xml
index 729ffe9c8..9f715c9c3 100644
--- a/quality_of_service_demo/rclpy/package.xml
+++ b/quality_of_service_demo/rclpy/package.xml
@@ -21,6 +21,7 @@
ament_copyright
ament_flake8
ament_pep257
+ ament_mypy
ament_xmllint
python3-pytest
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/common_nodes.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/common_nodes.py
index 331fd1121..3a1c6644d 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/common_nodes.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/common_nodes.py
@@ -12,15 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from typing import Optional
+
from example_interfaces.msg import String
+from rclpy.event_handler import PublisherEventCallbacks
+from rclpy.event_handler import SubscriptionEventCallbacks
from rclpy.node import Node
+from rclpy.publisher import Publisher
+from rclpy.qos import QoSProfile
+from rclpy.subscription import Subscription
+from rclpy.timer import Timer
class Talker(Node):
def __init__(
- self, topic_name, qos_profile, event_callbacks,
- publish_count=0, assert_topic_period=None
- ):
+ self,
+ topic_name: str,
+ qos_profile: QoSProfile,
+ event_callbacks: Optional[PublisherEventCallbacks],
+ publish_count: int = 0,
+ assert_topic_period: Optional[float] = None
+ ) -> None:
"""
Create a Talker.
@@ -32,20 +44,20 @@ def __init__(
"""
super().__init__('talker')
self.get_logger().info('Talker starting up')
- self.publisher = self.create_publisher(
+ self.publisher: Publisher[String] = self.create_publisher(
String, topic_name, qos_profile,
event_callbacks=event_callbacks)
- self.publish_timer = self.create_timer(0.5, self.publish)
+ self.publish_timer: Timer = self.create_timer(0.5, self.publish)
if assert_topic_period:
- self.assert_topic_timer = self.create_timer(
+ self.assert_topic_timer: Optional[Timer] = self.create_timer(
assert_topic_period, self.publisher.assert_liveliness)
else:
self.assert_topic_timer = None
- self.pause_timer = None
+ self.pause_timer: Optional[Timer] = None
self.publish_count = 0
self.stop_at_count = publish_count
- def pause_for(self, seconds):
+ def pause_for(self, seconds: float) -> None:
"""
Stop publishing for a while.
@@ -61,13 +73,14 @@ def pause_for(self, seconds):
self.publish_timer.cancel()
self.pause_timer = self.create_timer(seconds, self._pause_expired)
- def _pause_expired(self):
+ def _pause_expired(self) -> None:
self.publish()
self.publish_timer.reset()
- self.destroy_timer(self.pause_timer)
+ if self.pause_timer is not None:
+ self.destroy_timer(self.pause_timer)
self.pause_timer = None
- def publish(self):
+ def publish(self) -> None:
"""
Publish a single message.
@@ -81,7 +94,7 @@ def publish(self):
self.publish_timer.cancel()
self.publisher.publish(message)
- def stop(self):
+ def stop(self) -> None:
"""Cancel publishing and any manual liveliness assertions."""
if self.assert_topic_timer:
self.assert_topic_timer.cancel()
@@ -91,7 +104,13 @@ def stop(self):
class Listener(Node):
- def __init__(self, topic_name, qos_profile, event_callbacks, defer_subscribe=False):
+ def __init__(
+ self,
+ topic_name: str,
+ qos_profile: QoSProfile,
+ event_callbacks: Optional[SubscriptionEventCallbacks],
+ defer_subscribe: bool = False
+ ) -> None:
"""
Create a Listener.
@@ -101,14 +120,14 @@ def __init__(self, topic_name, qos_profile, event_callbacks, defer_subscribe=Fal
@param defer_subscribe Don't create Subscription until user calls start_listening()
"""
super().__init__('listener')
- self.subscription = None
+ self.subscription: Optional[Subscription[String]] = None
self.topic_name = topic_name
self.qos_profile = qos_profile
self.event_callbacks = event_callbacks
if not defer_subscribe:
self.start_listening()
- def start_listening(self):
+ def start_listening(self) -> None:
"""
Instantiate Subscription.
@@ -121,5 +140,5 @@ def start_listening(self):
event_callbacks=self.event_callbacks)
self.get_logger().info('Listener starting up')
- def _message_callback(self, message):
+ def _message_callback(self, message: String) -> None:
self.get_logger().info('Listener heard: [{}]'.format(message.data))
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/deadline.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/deadline.py
index d23822299..9501821a5 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/deadline.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/deadline.py
@@ -14,6 +14,7 @@
import argparse
import sys
+from typing import Optional
from quality_of_service_demo_py.common_nodes import Listener
from quality_of_service_demo_py.common_nodes import Talker
@@ -21,6 +22,8 @@
import rclpy
from rclpy.duration import Duration
from rclpy.event_handler import PublisherEventCallbacks
+from rclpy.event_handler import QoSOfferedDeadlineMissedInfo
+from rclpy.event_handler import QoSRequestedDeadlineMissedInfo
from rclpy.event_handler import SubscriptionEventCallbacks
from rclpy.executors import ExternalShutdownException
from rclpy.executors import SingleThreadedExecutor
@@ -28,7 +31,7 @@
from rclpy.qos import QoSProfile
-def parse_args():
+def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument(
'deadline', type=int,
@@ -43,7 +46,7 @@ def parse_args():
return parser.parse_args()
-def main(args=None):
+def main(args: Optional[list[str]] = None) -> int:
try:
parsed_args = parse_args()
@@ -55,7 +58,7 @@ def main(args=None):
depth=10,
deadline=deadline)
- def sub_deadline_event(event):
+ def sub_deadline_event(event: QoSRequestedDeadlineMissedInfo) -> None:
count = event.total_count
delta = event.total_count_change
get_logger('listener').info(
@@ -64,7 +67,7 @@ def sub_deadline_event(event):
subscription_callbacks = SubscriptionEventCallbacks(deadline=sub_deadline_event)
listener = Listener(topic, qos_profile, event_callbacks=subscription_callbacks)
- def pub_deadline_event(event):
+ def pub_deadline_event(event: QoSOfferedDeadlineMissedInfo) -> None:
count = event.total_count
delta = event.total_count_change
get_logger('talker').info(f'Offered deadline missed - total {count} delta {delta}')
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/incompatible_qos.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/incompatible_qos.py
index 1efcc4f9d..9e34761fa 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/incompatible_qos.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/incompatible_qos.py
@@ -14,6 +14,7 @@
import argparse
import sys
+from typing import Optional
from quality_of_service_demo_py.common_nodes import Listener
from quality_of_service_demo_py.common_nodes import Talker
@@ -21,6 +22,8 @@
import rclpy
from rclpy.duration import Duration
from rclpy.event_handler import PublisherEventCallbacks
+from rclpy.event_handler import QoSOfferedIncompatibleQoSInfo
+from rclpy.event_handler import QoSRequestedIncompatibleQoSInfo
from rclpy.event_handler import SubscriptionEventCallbacks
from rclpy.event_handler import UnsupportedEventTypeError
from rclpy.executors import ExternalShutdownException
@@ -32,7 +35,7 @@
from rclpy.qos import QoSReliabilityPolicy
-def get_parser():
+def get_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser()
parser.add_argument(
'incompatible_qos_policy_name',
@@ -43,7 +46,7 @@ def get_parser():
return parser
-def main(args=None):
+def main(args: Optional[list[str]] = None) -> int:
try:
# Argument parsing and usage
parser = get_parser()
@@ -118,7 +121,7 @@ def main(args=None):
topic = 'incompatible_qos_chatter'
num_msgs = 5
- def sub_incompatible_qos_event(event):
+ def sub_incompatible_qos_event(event: QoSRequestedIncompatibleQoSInfo) -> None:
count = event.total_count
delta = event.total_count_change
policy = event.last_policy_kind
@@ -126,7 +129,7 @@ def sub_incompatible_qos_event(event):
f'Requested incompatible qos - total {count} delta {delta} '
f'last_policy_kind: {policy}')
- def pub_incompatible_qos_event(event):
+ def pub_incompatible_qos_event(event: QoSOfferedIncompatibleQoSInfo) -> None:
count = event.total_count
delta = event.total_count_change
policy = event.last_policy_kind
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/lifespan.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/lifespan.py
index a7838f360..ed70d3ca9 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/lifespan.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/lifespan.py
@@ -14,6 +14,7 @@
import argparse
import sys
+from typing import Optional
from quality_of_service_demo_py.common_nodes import Listener
from quality_of_service_demo_py.common_nodes import Talker
@@ -27,7 +28,7 @@
from rclpy.qos import QoSReliabilityPolicy
-def parse_args():
+def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument(
'lifespan', type=int,
@@ -46,7 +47,7 @@ def parse_args():
return parser.parse_args()
-def main(args=None):
+def main(args: Optional[list[str]] = None) -> int:
try:
parsed_args = parse_args()
with rclpy.init(args=args):
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/liveliness.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/liveliness.py
index 147aa6dfa..635a74a22 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/liveliness.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/liveliness.py
@@ -14,6 +14,7 @@
import argparse
import sys
+from typing import Optional
from quality_of_service_demo_py.common_nodes import Listener
from quality_of_service_demo_py.common_nodes import Talker
@@ -21,6 +22,8 @@
import rclpy
from rclpy.duration import Duration
from rclpy.event_handler import PublisherEventCallbacks
+from rclpy.event_handler import QoSLivelinessChangedInfo
+from rclpy.event_handler import QoSLivelinessLostInfo
from rclpy.event_handler import SubscriptionEventCallbacks
from rclpy.executors import ExternalShutdownException
from rclpy.executors import SingleThreadedExecutor
@@ -34,14 +37,14 @@
}
-def parse_args():
+def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument(
'liveliness_lease_duration', type=int,
help='Duration in positive integer milliseconds of the Liveliness lease_duration '
'QoS setting.')
parser.add_argument(
- '--policy', type=str, choices=POLICY_MAP.keys(), default='AUTOMATIC',
+ '--policy', type=str, choices=list(POLICY_MAP.keys()), default='AUTOMATIC',
help='The Liveliness policy type.')
parser.add_argument(
'--topic-assert-period', type=int, default=0,
@@ -53,7 +56,7 @@ def parse_args():
return parser.parse_args()
-def main(args=None):
+def main(args: Optional[list[str]] = None) -> int:
try:
parsed_args = parse_args()
with rclpy.init(args=args):
@@ -67,7 +70,7 @@ def main(args=None):
liveliness=liveliness_policy,
liveliness_lease_duration=liveliness_lease_duration)
- def sub_liveliness_event(event):
+ def sub_liveliness_event(event: QoSLivelinessChangedInfo) -> None:
get_logger('listener').info('Liveliness changed event:')
get_logger('listener').info(f' alive_count: {event.alive_count}')
get_logger('listener').info(f' not_alive_count: {event.not_alive_count}')
@@ -78,13 +81,10 @@ def sub_liveliness_event(event):
subscription_callbacks = SubscriptionEventCallbacks(liveliness=sub_liveliness_event)
listener = Listener(topic, qos_profile, event_callbacks=subscription_callbacks)
- def pub_liveliness_event(event):
- get_logger('talker').info('Liveliness changed event:')
- get_logger('talker').info(f' alive_count: {event.alive_count}')
- get_logger('talker').info(f' not_alive_count: {event.not_alive_count}')
- get_logger('talker').info(f' alive_count_change: {event.alive_count_change}')
- get_logger('talker').info(
- f' not_alive_count_change: {event.not_alive_count_change}')
+ def pub_liveliness_event(event: QoSLivelinessLostInfo) -> None:
+ get_logger('talker').info('Liveliness lost event:')
+ get_logger('talker').info(f' total_count: {event.total_count}')
+ get_logger('talker').info(f' total_count_change: {event.total_count_change}')
publisher_callbacks = PublisherEventCallbacks(liveliness=pub_liveliness_event)
talker = Talker(
@@ -94,7 +94,7 @@ def pub_liveliness_event(event):
executor = SingleThreadedExecutor()
- def kill_talker():
+ def kill_talker() -> None:
if liveliness_policy == QoSLivelinessPolicy.AUTOMATIC:
executor.remove_node(talker)
talker.destroy_node()
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/message_lost_listener.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/message_lost_listener.py
index caf991c64..0c04d6593 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/message_lost_listener.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/message_lost_listener.py
@@ -13,8 +13,10 @@
# limitations under the License.
import sys
+from typing import Optional
import rclpy
+from rclpy.event_handler import QoSMessageLostInfo
from rclpy.event_handler import SubscriptionEventCallbacks
from rclpy.executors import ExternalShutdownException
from rclpy.executors import SingleThreadedExecutor
@@ -27,7 +29,7 @@
class MessageLostListener(Node):
"""Listener node to demonstrate how to get a notification on lost messages."""
- def __init__(self):
+ def __init__(self) -> None:
"""Create a MessageLostListener."""
super().__init__('message_lost_listener')
@@ -44,14 +46,14 @@ def __init__(self):
1,
event_callbacks=event_callbacks)
- def _message_callback(self, message):
+ def _message_callback(self, message: Image) -> None:
"""Log when a message is received."""
now = self.get_clock().now()
diff = now - Time.from_msg(message.header.stamp)
self.get_logger().info(
f'I heard an Image. Message single trip latency: [{diff.nanoseconds}]\n---')
- def _message_lost_event_callback(self, message_lost_status):
+ def _message_lost_event_callback(self, message_lost_status: QoSMessageLostInfo) -> None:
"""Log the number of lost messages when the event is triggered."""
self.get_logger().info(
'Some messages were lost:\n>\tNumber of new lost messages: '
@@ -60,7 +62,7 @@ def _message_lost_event_callback(self, message_lost_status):
)
-def main(args=None):
+def main(args: Optional[list[str]] = None) -> int:
try:
with rclpy.init(args=args):
listener = MessageLostListener()
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_listener.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_listener.py
index b1336e6d8..87eafe04f 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_listener.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_listener.py
@@ -13,19 +13,21 @@
# limitations under the License.
import sys
+from typing import Optional
from example_interfaces.msg import String
import rclpy
from rclpy.executors import ExternalShutdownException
from rclpy.node import Node
+from rclpy.qos import QoSProfile
from rclpy.qos_overriding_options import QosCallbackResult
from rclpy.qos_overriding_options import QoSOverridingOptions
class Listener(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('qos_overrides_listener')
self.sub = self.create_subscription(
String, 'qos_overrides_chatter', self.chatter_callback, 10,
@@ -34,10 +36,10 @@ def __init__(self):
# entity_id='my_custom_id', # Use this if you want a custo qos override id.
))
- def chatter_callback(self, msg):
+ def chatter_callback(self, msg: String) -> None:
self.get_logger().info('I heard: [%s]' % msg.data)
- def qos_callback(self, qos):
+ def qos_callback(self, qos: QoSProfile) -> QosCallbackResult:
result = QosCallbackResult()
if qos.depth <= 10:
result.successful = True
@@ -47,7 +49,7 @@ def qos_callback(self, qos):
return result
-def main(args=None):
+def main(args: Optional[list[str]] = None) -> int:
try:
with rclpy.init(args=args):
node = Listener()
diff --git a/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_talker.py b/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_talker.py
index 30bd295b5..757c3dbe0 100644
--- a/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_talker.py
+++ b/quality_of_service_demo/rclpy/quality_of_service_demo_py/qos_overrides_talker.py
@@ -13,19 +13,21 @@
# limitations under the License.
import sys
+from typing import Optional
from example_interfaces.msg import String
import rclpy
from rclpy.executors import ExternalShutdownException
from rclpy.node import Node
+from rclpy.qos import QoSProfile
from rclpy.qos_overriding_options import QosCallbackResult
from rclpy.qos_overriding_options import QoSOverridingOptions
class Talker(Node):
- def __init__(self):
+ def __init__(self) -> None:
super().__init__('qos_overrides_talker')
self.i = 0
self.pub = self.create_publisher(
@@ -37,14 +39,14 @@ def __init__(self):
timer_period = 1.0
self.tmr = self.create_timer(timer_period, self.timer_callback)
- def timer_callback(self):
+ def timer_callback(self) -> None:
msg = String()
msg.data = 'Hello World: {0}'.format(self.i)
self.i += 1
self.get_logger().info('Publishing: "{0}"'.format(msg.data))
self.pub.publish(msg)
- def qos_callback(self, qos):
+ def qos_callback(self, qos: QoSProfile) -> QosCallbackResult:
result = QosCallbackResult()
if qos.depth <= 10:
result.successful = True
@@ -54,7 +56,7 @@ def qos_callback(self, qos):
return result
-def main(args=None):
+def main(args: Optional[list[str]] = None) -> int:
try:
with rclpy.init(args=args):
node = Talker()
diff --git a/quality_of_service_demo/rclpy/test/test_linters.py b/quality_of_service_demo/rclpy/test/test_linters.py
index 3344f3bf0..708f12762 100644
--- a/quality_of_service_demo/rclpy/test/test_linters.py
+++ b/quality_of_service_demo/rclpy/test/test_linters.py
@@ -21,7 +21,7 @@
@pytest.mark.copyright
@pytest.mark.linter
-def test_copyright():
+def test_copyright() -> None:
# Test is called from package root
rc = ament_copyright.main.main(argv=['.'])
assert rc == 0, 'Found copyright errors'
@@ -29,7 +29,7 @@ def test_copyright():
@pytest.mark.flake8
@pytest.mark.linter
-def test_flake8():
+def test_flake8() -> None:
# Test is called from package root
rc = ament_flake8.main.main(argv=['.'])
assert rc == 0, 'Found flake8 errors'
@@ -37,7 +37,7 @@ def test_flake8():
@pytest.mark.linter
@pytest.mark.pep257
-def test_pep257():
+def test_pep257() -> None:
# Test is called from package root
rc = ament_pep257.main.main(argv=['.'])
assert rc == 0, 'Found PEP257 code style error / warnings'
diff --git a/quality_of_service_demo/rclpy/test/test_mypy.py b/quality_of_service_demo/rclpy/test/test_mypy.py
new file mode 100644
index 000000000..d5c759300
--- /dev/null
+++ b/quality_of_service_demo/rclpy/test/test_mypy.py
@@ -0,0 +1,21 @@
+# Copyright 2019 Canonical, Ltd.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+from ament_mypy.main import main
+
+
+def test_mypy() -> None:
+ rc = main(argv=['--ament-strict'])
+ assert rc == 0, 'Found code style errors / warnings'