ros2_client 0.1.0 copy "ros2_client: ^0.1.0" to clipboard
ros2_client: ^0.1.0 copied to clipboard

A type-safe, streaming ROS 2 client for Dart and Flutter. Topics, services, actions, parameters and introspection over rosbridge.

example/ros2_client_example.dart

// A console ROS 2 client: connect, introspect, subscribe, and drive.
//
// Start a bridge on the robot first:
//   ros2 launch rosbridge_server rosbridge_websocket_launch.xml
//
// Then:  dart run example/ros2_client_example.dart ws://192.168.1.10:9090
import 'dart:async';
import 'dart:io';

import 'package:ros2_client/ros2_client.dart';

Future<void> main(List<String> args) async {
  registerStandardMessages();

  final uri = Uri.parse(args.isNotEmpty ? args.first : 'ws://127.0.0.1:9090');
  final ros = Ros2Client(uri, defaultCompression: Compression.cbor);

  ros.states.listen((state) => print('[connection] ${state.name}'));
  ros.status.listen((status) => print('[bridge] $status'));

  print('Connecting to $uri …');
  await ros.connect();

  // --- Introspection: what is actually running on this robot? ---------------
  final topics = await ros.listTopics();
  print('\n${topics.length} topics:');
  for (final topic in topics.take(15)) {
    print('  $topic');
  }

  final nodes = await ros.listNodes();
  print('\n${nodes.length} nodes: ${nodes.take(8).join(', ')}');

  // --- Subscribe to whatever interesting topics exist -----------------------
  final names = topics.map((t) => t.name).toSet();

  if (names.contains('/odom')) {
    ros.subscribe<Odometry>('/odom', throttleRate: 500).listen((odom) {
      final p = odom.pose.position;
      print('[odom] x=${p.x.toStringAsFixed(2)} '
          'y=${p.y.toStringAsFixed(2)} '
          'yaw=${odom.pose.orientation.yaw.toStringAsFixed(2)}');
    });
  }

  if (names.contains('/scan')) {
    // Lidar is published best-effort; the default reliable QoS matches nothing.
    ros
        .subscribe<LaserScan>('/scan',
            qos: QosProfile.sensorData, throttleRate: 1000)
        .listen((scan) {
      final valid = scan.ranges.where((r) => r.isFinite && r > 0);
      final closest =
          valid.isEmpty ? double.nan : valid.reduce((a, b) => a < b ? a : b);
      print('[scan] ${scan.ranges.length} beams, '
          'closest ${closest.toStringAsFixed(2)} m');
    });
  }

  if (names.contains('/battery_state')) {
    ros.subscribe<BatteryState>('/battery_state').listen(
        (b) => print('[battery] ${(b.percentage * 100).toStringAsFixed(0)}% '
            '${b.isCharging ? '(charging)' : ''}'));
  }

  // --- Drive forward briefly, then stop ------------------------------------
  if (names.contains('/cmd_vel')) {
    final cmdVel = ros.advertise<Twist>('/cmd_vel');
    print('\nDriving forward for 2 s …');
    final ticker = Timer.periodic(const Duration(milliseconds: 100),
        (_) => cmdVel.publish(Twist.drive(forward: 0.15)));

    await Future<void>.delayed(const Duration(seconds: 2));
    ticker.cancel();
    cmdVel.publish(Twist.stop);
    print('Stopped.');
  }

  print('\nStreaming for 15 s — Ctrl-C to quit.');
  await Future<void>.delayed(const Duration(seconds: 15));

  await ros.close();
  exit(0);
}
0
likes
160
points
54
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A type-safe, streaming ROS 2 client for Dart and Flutter. Topics, services, actions, parameters and introspection over rosbridge.

Repository (GitHub)
View/report issues

Topics

#ros #ros2 #robotics #rosbridge #websocket

License

BSD-3-Clause (license)

Dependencies

async, cbor, collection, meta, typed_data, web_socket_channel

More

Packages that depend on ros2_client