This guide is for teams that use ROS 2 as the robot control plane and want peaqOS as the machine identity, credit, and asset layer.
The ROS 2 node wraps the same peaqOS capabilities documented in the JavaScript SDK and Python SDK , but changes the security boundary: callers pass EVM addresses over ROS, while signing keys stay in a local registry file.
Prerequisites
ROS 2 Jazzy on a native host, or the repository Docker image with ROS 2 Humble
A peaq EVM RPC endpoint
https://mcr.peaq.xyz for MCR reads
https://depinstation.peaq.network for Gas Station flows
A funded peaq EVM signer for registration, minting , events, smart accounts , and bridge transactions
Base ETH on the signer only if you need Base to peaq bridge operations
Create a local config:
cp peaq_ros2_examples/config/peaq_robot.example.yaml \
peaq_ros2_examples/config/peaq_robot.yaml
Set the peaqOS section:
peaq_os :
enabled : true
rpc_url : "https://quicknode1.peaq.xyz"
api_url : "https://mcr.peaq.xyz"
faucet :
base_url : "https://depinstation.peaq.network"
qr_format : "svg"
wallet_registry :
path : "~/.peaq_robot/peaqos_wallets.json"
Do not commit peaq_robot.yaml after adding real addresses, local registry paths, or operational credentials.
Build and start
source /opt/ros/jazzy/setup.bash
# In the Docker image, use: source /opt/ros/humble/setup.bash
python3 -m pip install -r requirements.txt
colcon build --packages-select peaq_ros2_interfaces peaq_ros2_peaqos peaq_ros2_examples
source install/setup.bash
ros2 run peaq_ros2_peaqos peaqos_node --ros-args \
-p config.yaml_path:=peaq_ros2_examples/config/peaq_robot.yaml
Open another terminal, source the same ROS environment, then call services.
1. Create a local machine wallet
ros2 service call /peaqos_node/wallet/create \
peaq_ros2_interfaces/srv/PeaqosCreateWallet \
"{label: 'robot-001'}"
Save the returned address. The private key is stored in the local registry and is not returned.
You can inspect or remove local wallet metadata without exposing keys:
ros2 service call /peaqos_node/wallet/list \
peaq_ros2_interfaces/srv/PeaqosListWallets \
"{}"
ros2 service call /peaqos_node/wallet/get \
peaq_ros2_interfaces/srv/PeaqosGetWallet \
"{address: '<MACHINE_EVM_ADDRESS>'}"
The returned wallet JSON includes public peaq EVM account metadata:
address, account_id, chain_id, network, label, and created_at.
2. Fund the machine wallet
Registration signs from the machine wallet and requires enough native peaq for gas plus the IdentityRegistry registration bond . Fund the returned <MACHINE_EVM_ADDRESS> before calling register.
You can use the Gas Station flow with owner 2FA:
ros2 service call /peaqos_node/faucet/setup_2fa \
peaq_ros2_interfaces/srv/PeaqosSetupFaucet2FA \
"{owner_address: '<OWNER_EVM_ADDRESS>', qr_format: 'svg'}"
ros2 service call /peaqos_node/faucet/confirm_2fa \
peaq_ros2_interfaces/srv/PeaqosConfirmFaucet2FA \
"{owner_address: '<OWNER_EVM_ADDRESS>', two_factor_code: '123456'}"
ros2 service call /peaqos_node/wallet/fund \
peaq_ros2_interfaces/srv/PeaqosFundWallet \
"{owner_address: '<OWNER_EVM_ADDRESS>', target_address: '<MACHINE_EVM_ADDRESS>', chain_id: '3338', two_factor_code: '123456', request_id: ''}"
Or transfer native peaq directly to <MACHINE_EVM_ADDRESS> from an already funded wallet. Wait for the balance to be available before registration.
3. Register the machine
For a self-managed machine, the node looks up <MACHINE_EVM_ADDRESS> in the local registry and signs the registration transaction with that wallet.
For a self-managed machine:
ros2 service call /peaqos_node/machine/register \
peaq_ros2_interfaces/srv/PeaqosRegisterMachine \
"{address: '<MACHINE_EVM_ADDRESS>'}"
For a proxy operator :
ros2 service call /peaqos_node/machine/register_for \
peaq_ros2_interfaces/srv/PeaqosRegisterFor \
"{proxy_address: '<PROXY_EVM_ADDRESS>', machine_address: '<MACHINE_EVM_ADDRESS>'}"
Registration returns machine_id. This is the IdentityRegistry machine ID . It is not necessarily the Machine NFT token ID .
4. Mint the Machine NFT and write DID attributes
ros2 service call /peaqos_node/nft/mint \
peaq_ros2_interfaces/srv/PeaqosMintNft \
"{signer_address: '<SIGNER_EVM_ADDRESS>', machine_id: 1, recipient: '<MACHINE_EVM_ADDRESS>'}"
Read the Machine NFT token ID:
ros2 service call /peaqos_node/nft/token_id_of \
peaq_ros2_interfaces/srv/PeaqosTokenIdOf \
"{signer_address: '<SIGNER_EVM_ADDRESS>', machine_id: 1}"
Link the machine’s DID to its Machine NFT and metadata endpoints:
ros2 service call /peaqos_node/did/write_machine_attributes \
peaq_ros2_interfaces/srv/PeaqosWriteMachineDidAttributes \
"{signer_address: '<SIGNER_EVM_ADDRESS>', machine_id: 1, nft_token_id: 1, operator_did: 'did:peaq:<OPERATOR_EVM_ADDRESS>', documentation_url: 'https://docs.example/robot-001', data_api: 'https://api.example/robot-001', data_visibility: 'onchain'}"
Verify a single attribute:
ros2 service call /peaqos_node/did/read_attribute \
peaq_ros2_interfaces/srv/PeaqosReadDidAttribute \
"{signer_address: '<SIGNER_EVM_ADDRESS>', did_address: '<MACHINE_EVM_ADDRESS>', name: 'machineId'}"
5. Query MCR and machine profile
ros2 service call /peaqos_node/mcr/query \
peaq_ros2_interfaces/srv/PeaqosQueryMcr \
"{did: 'did:peaq:<MACHINE_EVM_ADDRESS>'}"
ros2 service call /peaqos_node/mcr/machine \
peaq_ros2_interfaces/srv/PeaqosQueryMachine \
"{did: 'did:peaq:<MACHINE_EVM_ADDRESS>'}"
Newly registered machines can return Provisioned until enough event history exists.
6. Validate and submit events
Validate before broadcasting:
ros2 service call /peaqos_node/events/validate \
peaq_ros2_interfaces/srv/PeaqosValidateEvent \
"{machine_id: 1, event_type: 1, value: 1, timestamp: 1770000000, raw_data_hex: '0x73656e736f723a6f6b', trust_level: 0, source_chain_id: 3338, source_tx_hash: '', metadata_hex: '0x7b7d'}"
Submit one event:
ros2 service call /peaqos_node/events/submit \
peaq_ros2_interfaces/srv/PeaqosSubmitEvent \
"{signer_address: '<MACHINE_EVM_ADDRESS>', machine_id: 1, event_type: 1, value: 1, timestamp: 1770000000, raw_data_hex: '0x73656e736f723a6f6b', trust_level: 0, source_chain_id: 3338, source_tx_hash: '', metadata_hex: '0x7b7d'}"
Batch submission uses events_json, a JSON array using the same event field names.
7. Predict or deploy a machine smart account
ros2 service call /peaqos_node/smart_account/address \
peaq_ros2_interfaces/srv/PeaqosGetSmartAccountAddress \
"{signer_address: '<SIGNER_EVM_ADDRESS>', owner: '<OWNER_EVM_ADDRESS>', machine: '<MACHINE_EVM_ADDRESS>', daily_limit: '', salt: '0'}"
Deploy with the same parameters:
ros2 service call /peaqos_node/smart_account/deploy \
peaq_ros2_interfaces/srv/PeaqosDeploySmartAccount \
"{signer_address: '<SIGNER_EVM_ADDRESS>', owner: '<OWNER_EVM_ADDRESS>', machine: '<MACHINE_EVM_ADDRESS>', daily_limit: '', salt: '0'}"
8. Bridge Machine NFT from peaq to Base
ros2 service call /peaqos_node/bridge/nft \
peaq_ros2_interfaces/srv/PeaqosBridgeNft \
"{signer_address: '<OWNER_EVM_ADDRESS>', token_id: 1, source: 'peaq', destination: 'base', recipient: '<RECIPIENT_EVM_ADDRESS>', base_rpc_url: '', base_nft_address: '', options_hex: ''}"
Wait for the NFT to appear on Base:
ros2 service call /peaqos_node/bridge/wait_arrival \
peaq_ros2_interfaces/srv/PeaqosWaitForBridgeArrival \
"{dst_rpc_url: 'https://mainnet.base.org', dst_nft_address: '0xee8A521eA434b11F956E2402beC5eBfa753Babfa', token_id: 1, timeout: 900}"
Production checklist
Keep peaq_os.wallet_registry.path local to the robot or machine.
Keep the wallet registry file permissioned as 0600.
Quote all EVM addresses in ROS YAML service payloads.
Record pre and post balances for production bridge or payment tests.
Confirm contract addresses before release if peaqOS publishes a new deployment.
Fund Base ETH before attempting Base to peaq bridge operations.
References