Skip to content

Add ROS2 message support #10538

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Conversation

hierophect
Copy link
Collaborator

Adds ROS2 message type support to the rclcpy module. Creating a Publisher now requires a ROS message type - all future messages must adhere to that message type. A small group of simple test messages are available in the std_msgs submodule of rclcpy, including Int32 and Bool. Message type detection is done through a type registry, and the appropriate C level information passed to the Micro-ROS interface. Ideally, future messages and message packages will be supported with an automated class and registry generator. Due to MicroROS restrictions, custom user message types cannot be supported without rebuilding Circuitpython.

Putting this up a little early to get eyes on my implementation of the registry and file arrangement while I work on updating the documentation and cleaning up formatting and translation checks. Tested for functionality with ROS2 Jazzy, and is working as expected.

Example:

import os, wifi, time
import rclcpy
print("connecting...")
wifi.radio.connect(ssid=os.getenv('CIRCUITPY_WIFI_SSID'),
                   password=os.getenv('CIRCUITPY_WIFI_PASSWORD'))
print("my IP addr:", wifi.radio.ipv4_address)
print(rclcpy.std_msgs.Int32)
rclcpy.init(os.getenv('AGENT_IP'), os.getenv('AGENT_PORT'))
mynode = rclcpy.Node("foo")
print(mynode.get_name())

mypub = mynode.create_publisher(rclcpy.std_msgs.Bool, "bar")
print(mypub.get_topic_name())
mymsg = rclcpy.std_msgs.Bool()
mymsg.data = True
mypub.publish(mymsg)

API changes to rclcpy

  • Removes the test publisher function publish_int32 and replaces it with the correct publish function, which accepts a message object.
  • Adds the MsgType parameter to publisher creation.
  • Adds the std_msgs module to the module root.

Adds ROS2 message type support to the rclcpy module. Creating a Publisher now
requires a ROS message type - all future messages must adhere to that message
type. A small group of test messages are available in the std_msgs submodule of
rclcpy, including Int32 and Bool. Message type detection is done through a type
registry, and the appropriate C level information passed to the Micro-ROS
interface. Ideally, future messages and message packages will be supported with
an automated class and registry generator. Due to MicroROS restrictions, custom
user message types cannot be supported without rebuilding Circuitpython.

API changes:
Removes the test publisher function `publish_int32` and replaces it with the
correct `publish` function, which accepts a message object. Adds the MsgType
parameter to publisher creation. Adds the std_msgs module to the module root.
@hierophect hierophect requested a review from dhalbert August 1, 2025 20:22
@hierophect hierophect added the rclcpy Micro-ROS client module label Aug 1, 2025
Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

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

Hi - some suggestions. I will make this a draft PR for now, since you are going to do more. Also awaiting doc for several new constructors, etc. Otherwise it looks quite clean.

You could use mp_arg_parse_all_kw_array() even on the simple construtors, but maybe this is simpler and less code.

Comment on lines +21 to +33
static mp_obj_t bool_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, true);
rclcpy_std_msgs_bool_obj_t *self = m_new_obj(rclcpy_std_msgs_bool_obj_t);
self->base.type = &rclcpy_std_msgs_bool_type;

if (n_args == 1) {
self->data = mp_obj_is_true(args[0]);
} else {
self->data = false;
}
return MP_OBJ_FROM_PTR(self);
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can (and should) use the new mp_obj_malloc() or mp_obj_malloc_with_finaliser() (if you need a finaliser) instead of the old m_new_obj() and setting the base.type explicitly. Take a look at some other make_news in existing modules.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh right, my bad. Was referencing old stuff from usermod for this bit.

Comment on lines +1 to +5
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland
//
// SPDX-License-Identifier: MIT
Copy link
Collaborator

Choose a reason for hiding this comment

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

Were these going to be omitted or moved to shared-module/?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I figured I would post the "default" structure first before trying any shenanigans. I'll investigate the microcontroller/ResetReason example you mentioned to see if it's a better solution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I wanted to make sure the overall module and class structure looked acceptable, since I wasn't able to find other shared-bindings modules that attempt large class collections like this.

@dhalbert dhalbert marked this pull request as draft August 4, 2025 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rclcpy Micro-ROS client module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants