ROS 2 names, RIHS01 type hashes, CDR encoding, and rmw_zenoh key assembly, with no ROS 2 installed. One capability of pamoja, one memory-safe Rust core with bindings for TypeScript, Python, and C#.
npm install @pamoja/ros2
This pulls in @pamoja/native, the compiled engine. npm install pamoja is the whole framework in one package.
The test that runs in CI, spliced here as it ran.
From bindings/node/guides/ros2.ts:
import { EntityKind, name } from '@pamoja/ros2'
// A name is slash-separated tokens. A token may hold letters, digits, and underscores, and
// may not begin with a digit, which is the rule that catches most generated names.
for (const candidate of ['/robot1/camera_left/image_raw', '/2foo']) {
console.log(`${candidate} is a valid name: ${name.isValid(candidate)}`)
}
console.log(`chatter is fully qualified: ${name.isFullyQualified('chatter')}`)
console.log(`/chatter is fully qualified: ${name.isFullyQualified('/chatter')}`)
// On the wire a topic carries a prefix that says what kind of endpoint it is, so a
// subscription and a service request never collide in the same DDS partition.
const published = name.ddsTopic('/robot1/cmd_vel', EntityKind.Topic)
const asked = name.ddsTopic('/robot1/add', EntityKind.ServiceRequest)
const answered = name.ddsTopic('/robot1/add', EntityKind.ServiceResponse)
console.log(`a topic becomes ${published}`)
console.log(`a request becomes ${asked}`)
console.log(`a response becomes ${answered}`)
// A message type maps to a DDS type name the same way, so both ends agree on what is being
// carried before a byte is exchanged.
console.log(`std_msgs/msg/String becomes ${name.ddsTypeName('std_msgs/msg/String')}`)
console.log(`a malformed type name becomes ${name.ddsTypeName('not a type')}`)
| Language | Package | Reference |
|---|---|---|
| Rust | pamoja-ros2 |
reference, docs.rs, install |
| TypeScript | @pamoja/ros2 |
reference, install |
| Python | pamoja-ros2 |
reference, install |
| C# | Pamoja.Ros2 |
reference, install |
@pamoja/ros2 reference, every class, function, and type this package exports.MIT
Ergonomic facade over the generated ROS 2 binding.
What makes a topic name legal, what it becomes on the DDS wire, the RIHS type hash that identifies a message definition, and the CDR encoding the payload itself is written in.
None of it needs a ROS 2 installation. A gateway written in TypeScript can validate a name, derive the DDS topic and the Zenoh key an
rmw_zenohpeer subscribes on, and encode ageometry_msgs/msg/Twistwith no ROS distribution anywhere near it. Driving a live graph does need one, so that stays in the Rust crate.