Skip to content

Commit

Permalink
Generics Services and Clients (#1275)
Browse files Browse the repository at this point in the history
* First draft of generics

Signed-off-by: Michael Carlstrom <[email protected]>

* Fix Generic

Signed-off-by: Michael Carlstrom <[email protected]>

* Add legacy

Signed-off-by: Michael Carlstrom <[email protected]>

* Fix import order

Signed-off-by: Michael Carlstrom <[email protected]>

* fix import order

Signed-off-by: Michael Carlstrom <[email protected]>

* Add Docstrings

Signed-off-by: Michael Carlstrom <[email protected]>

* Add Docstrings

Signed-off-by: Michael Carlstrom <[email protected]>

* Add generics support to Node

Signed-off-by: Michael Carlstrom <[email protected]>

* Update type_support.py

Signed-off-by: Michael Carlstrom <[email protected]>
Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to expand_topic_name (#1238)

Signed-off-by: Michael Carlstrom <[email protected]>

* Creates Enum wrapper for ClockType and ClockChange (#1235)

* Testing out Enum wrapper for ClockType

* convert to rcl_clock_type_t

* Update create_time_point

Signed-off-by: Michael Carlstrom <[email protected]>

* Add types (#1231)

Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to exceptions.py (#1241)

* Add types to exception

* Add type checking guard

* Fix NotInitializedException

* Add missing defualt

Signed-off-by: Michael Carlstrom <[email protected]>

* added python3-yaml (#1242)

Signed-off-by: SnIcK <[email protected]>
Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to duration.py (#1233)

* Add types to logging_service.py (#1227)

* add types to logging_service

* Add types to duration.py

* Add newlines for class definintions

* update type alias name

* Update to use Protocols

Signed-off-by: Michael Carlstrom <[email protected]>

* Add Static Typing to Validate files (#1230)

* Add types to validate files

Signed-off-by: Michael Carlstrom <[email protected]>

* remove type annotations from docstrings

Signed-off-by: Michael Carlstrom <[email protected]>

* removed other type annotated docstrings

Signed-off-by: Michael Carlstrom <[email protected]>

---------

Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to TypeHash and moved away from __slots__ usage (#1232)

* Add types to TypeHash and moved away from __slots__ usage

Signed-off-by: Michael Carlstrom <[email protected]>

* remove docstring types

Signed-off-by: Michael Carlstrom <[email protected]>

---------

Signed-off-by: Michael Carlstrom <[email protected]>

* Time.py Types (#1237)

* Start typing time.py

Signed-off-by: Michael Carlstrom <[email protected]>

* Testing out Enum wrapper for ClockType

Signed-off-by: Michael Carlstrom <[email protected]>

* convert to rcl_clock_type_t

Signed-off-by: Michael Carlstrom <[email protected]>

* Undo Change to time_point.cpp

Signed-off-by: Michael Carlstrom <[email protected]>

* Update create_time_point

Signed-off-by: Michael Carlstrom <[email protected]>

* Lint fixes

Signed-off-by: Michael Carlstrom <[email protected]>

* Add debug message

Signed-off-by: Michael Carlstrom <[email protected]>

* Remove test file

Signed-off-by: Michael Carlstrom <[email protected]>

* Try extending the type assert

Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to logging_service.py (#1227)

* add types to logging_service

Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to duration.py

Signed-off-by: Michael Carlstrom <[email protected]>

* Add newlines for class definintions

Signed-off-by: Michael Carlstrom <[email protected]>

* update type alias name

Signed-off-by: Michael Carlstrom <[email protected]>

* Remove newline

Signed-off-by: Michael Carlstrom <[email protected]>

* Merge?

Signed-off-by: Michael Carlstrom <[email protected]>

* Fix failed merge

Signed-off-by: Michael Carlstrom <[email protected]>

* Update to use Protocols

Signed-off-by: Michael Carlstrom <[email protected]>

* Fix import error

Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to time.py

Signed-off-by: Michael Carlstrom <[email protected]>

* Linty

Signed-off-by: Michael Carlstrom <[email protected]>

---------

Signed-off-by: Michael Carlstrom <[email protected]>

* Revert "Add types to TypeHash and moved away from __slots__ usage (#1232)" (#1243)

This reverts commit b06baef.

Signed-off-by: Michael Carlstrom <[email protected]>

* Add back Type hash __slots__ and add test cases. (#1245)

* Add types to TypeHash and add test cases

Signed-off-by: Michael Carlstrom <[email protected]>

* Add types to context.py (#1240)

Signed-off-by: Michael Carlstrom <[email protected]>

* fix pub and sub

Signed-off-by: Michael Carlstrom <[email protected]>

* Update LifecyclePublisher

Signed-off-by: Michael Carlstrom <[email protected]>

* Fix docstring

Signed-off-by: Michael Carlstrom <[email protected]>

* Start implementation

Signed-off-by: Michael Carlstrom <[email protected]>

* Ungeneric?

Signed-off-by: Michael Carlstrom <[email protected]>

* Stuff

Signed-off-by: Michael Carlstrom <[email protected]>

* serialization generic

Signed-off-by: Michael Carlstrom <[email protected]>

* serialization generic

Signed-off-by: Michael Carlstrom <[email protected]>

* Update type_support.py

Signed-off-by: Michael Carlstrom <[email protected]>

* Client Service Generic Implementation

Signed-off-by: Michael Carlstrom <[email protected]>

* Fix debug relative import

Signed-off-by: Michael Carlstrom <[email protected]>

* Update imports

Signed-off-by: Michael Carlstrom <[email protected]>

* Add generics to node.py

Signed-off-by: Michael Carlstrom <[email protected]>

* Update import order

Signed-off-by: Michael Carlstrom <[email protected]>

* Remove double bracket

Signed-off-by: Michael Carlstrom <[email protected]>

---------

Signed-off-by: Michael Carlstrom <[email protected]>
Signed-off-by: Michael Carlstrom <[email protected]>
Signed-off-by: SnIcK <[email protected]>
Co-authored-by: SnIcK <[email protected]>
Co-authored-by: Chris Lalancette <[email protected]>
Co-authored-by: Shane Loretz <[email protected]>
  • Loading branch information
4 people authored Aug 5, 2024
1 parent fcce519 commit 464a357
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 25 deletions.
14 changes: 8 additions & 6 deletions rclpy/rclpy/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import time
from types import TracebackType
from typing import Dict
from typing import Generic
from typing import Optional
from typing import Type
from typing import TypeVar
Expand All @@ -27,19 +28,20 @@
from rclpy.qos import QoSProfile
from rclpy.service_introspection import ServiceIntrospectionState
from rclpy.task import Future
from rclpy.type_support import Srv, SrvEventT, SrvRequestT, SrvResponseT

# Used for documentation purposes only
# Left To Support Legacy TypeVars
SrvType = TypeVar('SrvType')
SrvTypeRequest = TypeVar('SrvTypeRequest')
SrvTypeResponse = TypeVar('SrvTypeResponse')


class Client:
class Client(Generic[SrvRequestT, SrvResponseT, SrvEventT]):
def __init__(
self,
context: Context,
client_impl: _rclpy.Client,
srv_type: SrvType,
srv_type: Srv[SrvRequestT, SrvResponseT, SrvEventT],
srv_name: str,
qos_profile: QoSProfile,
callback_group: CallbackGroup
Expand Down Expand Up @@ -73,9 +75,9 @@ def __init__(

def call(
self,
request: SrvTypeRequest,
request: SrvRequestT,
timeout_sec: Optional[float] = None
) -> Optional[SrvTypeResponse]:
) -> Optional[SrvResponseT]:
"""
Make a service request and wait for the result.
Expand Down Expand Up @@ -111,7 +113,7 @@ def unblock(future):
raise future.exception()
return future.result()

def call_async(self, request: SrvTypeRequest) -> Future:
def call_async(self, request: SrvRequestT) -> Future:
"""
Make a service request and asynchronously get the result.
Expand Down
14 changes: 9 additions & 5 deletions rclpy/rclpy/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
from rclpy.type_support import check_is_valid_msg_type
from rclpy.type_support import check_is_valid_srv_type
from rclpy.type_support import MsgT
from rclpy.type_support import Srv
from rclpy.type_support import SrvEventT
from rclpy.type_support import SrvRequestT
from rclpy.type_support import SrvResponseT
from rclpy.utilities import get_default_context
from rclpy.validate_full_topic_name import validate_full_topic_name
from rclpy.validate_namespace import validate_namespace
Expand Down Expand Up @@ -1673,12 +1677,12 @@ def create_subscription(

def create_client(
self,
srv_type,
srv_type: Srv[SrvRequestT, SrvResponseT, SrvEventT],
srv_name: str,
*,
qos_profile: QoSProfile = qos_profile_services_default,
callback_group: Optional[CallbackGroup] = None
) -> Client:
) -> Client[SrvRequestT, SrvResponseT, SrvEventT]:
"""
Create a new service client.
Expand Down Expand Up @@ -1715,13 +1719,13 @@ def create_client(

def create_service(
self,
srv_type,
srv_type: Srv[SrvRequestT, SrvResponseT, SrvEventT],
srv_name: str,
callback: Callable[[SrvTypeRequest, SrvTypeResponse], SrvTypeResponse],
callback: Callable[[SrvRequestT, SrvResponseT], SrvResponseT],
*,
qos_profile: QoSProfile = qos_profile_services_default,
callback_group: Optional[CallbackGroup] = None
) -> Service:
) -> Service[SrvRequestT, SrvResponseT, SrvEventT]:
"""
Create a new service server.
Expand Down
10 changes: 6 additions & 4 deletions rclpy/rclpy/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from types import TracebackType
from typing import Callable
from typing import Generic
from typing import Optional
from typing import Type
from typing import TypeVar
Expand All @@ -23,20 +24,21 @@
from rclpy.impl.implementation_singleton import rclpy_implementation as _rclpy
from rclpy.qos import QoSProfile
from rclpy.service_introspection import ServiceIntrospectionState
from rclpy.type_support import Srv, SrvEventT, SrvRequestT, SrvResponseT

# Used for documentation purposes only
SrvType = TypeVar('SrvType')
SrvTypeRequest = TypeVar('SrvTypeRequest')
SrvTypeResponse = TypeVar('SrvTypeResponse')


class Service:
class Service(Generic[SrvRequestT, SrvResponseT, SrvEventT]):
def __init__(
self,
service_impl: _rclpy.Service,
srv_type: SrvType,
srv_type: Srv[SrvRequestT, SrvResponseT, SrvEventT],
srv_name: str,
callback: Callable[[SrvTypeRequest, SrvTypeResponse], SrvTypeResponse],
callback: Callable[[SrvRequestT, SrvResponseT], SrvResponseT],
callback_group: CallbackGroup,
qos_profile: QoSProfile
) -> None:
Expand Down Expand Up @@ -64,7 +66,7 @@ def __init__(
self._executor_event = False
self.qos_profile = qos_profile

def send_response(self, response: SrvTypeResponse, header) -> None:
def send_response(self, response: SrvResponseT, header) -> None:
"""
Send a service response.
Expand Down
27 changes: 17 additions & 10 deletions rclpy/rclpy/type_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Optional, Protocol, Type, TypeVar, Union
from typing import NoReturn, Optional, Protocol, Type, TypeVar, Union

from rclpy.exceptions import NoTypeSupportImportedException

Expand Down Expand Up @@ -47,26 +47,33 @@ class MsgMetaClass(CommonMsgSrvMetaClass):


class Msg(Protocol, metaclass=MsgMetaClass):
"""Generic Message Type Alias."""

pass


# Could likely be improved if generic across Request, Response, Event
class Srv(Protocol, metaclass=CommonMsgSrvMetaClass):
"""Generic Service Type Alias."""
"""Generic Message Alias."""

pass


MsgT = TypeVar('MsgT', bound=Msg)
SrvT = TypeVar('SrvT', bound=Srv)

SrvRequestT = TypeVar('SrvRequestT', bound=Msg)
SrvResponseT = TypeVar('SrvResponseT', bound=Msg)
SrvEventT = TypeVar('SrvEventT', bound=Msg)


class Srv(Protocol[SrvRequestT, SrvResponseT, SrvEventT], metaclass=CommonMsgSrvMetaClass):
"""Generic Service Type Alias."""

Request: Type[SrvRequestT]
Response: Type[SrvResponseT]
Event: Type[SrvEventT]

def __init__(self) -> NoReturn:
...


# Can be used if https://github.com/python/typing/issues/548 ever gets approved.
SrvT = TypeVar('SrvT', bound=Type[Srv])


def check_for_type_support(msg_or_srv_type: Type[Union[Msg, Srv]]) -> None:
try:
ts = msg_or_srv_type._TYPE_SUPPORT
Expand Down

0 comments on commit 464a357

Please sign in to comment.