ROS 2 Java

repository·main·Indexed 41 days ago

https://github.com/ros2-java/ros2_java

A client library providing bindings and tools for ROS 2 development on the JVM and Android platforms. It includes a code generator (rosidl_generator_java) and support for publishers, subscriptions, clients, services, and tunable Quality of Service (QoS). The library enables any JVM-compatible language to write ROS 2 applications.

Tokens
2.9K
Snippets
6
Records
9
Agent score
53%

What's inside ROS 2 Java

  1. Overview of ROS 2 Java client library

    main

    ROS 2 Java is a set of projects including bindings, a code generator, and examples that enable developers to write ROS 2 applications for the JVM and Android. Because it targets the JVM, any language compatible with the JVM can be used to write ROS 2 applications.

    Key Features:

    • Generation of all builtin and complex ROS types (arrays, strings, nested types, constants, etc.).
    • Support for publishers, subscriptions, clients, and services.
    • Tunable Quality of Service (QoS).
    • Timers and Composition (multiple nodes per process).
    • Time handling (system and steady; ROS time support is currently in development).
    • Parameter services and clients (both synchronous and asynchronous).
    • Support for Android.
  2. Download and Build ROS 2 Java for Android

    main

    Building for Android requires the Android SDK (Lollipop/API 21 or greater) and the Android NDK. You must set ANDROID_HOME and ANDROID_NDK environment variables.

    Requirements:

    • DDS Vendor: Use Fast-RTPS (specifically this revision).
    • Environment Variables: ANDROID_HOME and ANDROID_NDK must be set.

    Build Process:

    1. Set up the workspace and import repositories using ros2_java_android.repos.
    2. Configure Python paths and Android build variables (ANDROID_ABI, ANDROID_NATIVE_API_LEVEL, etc.).
    3. Run colcon build while ignoring specific packages that cannot be cross-compiled (e.g., cyclonedds, rosidl_generator_py).
    # 1. Set up workspace
    mkdir -p $HOME/ros2_android_ws/src
    cd $HOME/ros2_android_ws
    curl https://raw.githubusercontent.com/ros2-java/ros2_java/main/ros2_java_android.repos | vcs import src
    
    # 2. Set Android build configuration
    export PYTHON3_EXEC="$( which python3 )"
    export PYTHON3_LIBRARY="$( ${PYTHON3_EXEC} -c 'import os.path; from distutils import sysconfig; print(os.path.realpath(os.path.join(sysconfig.get_config_var("LIBPL"), sysconfig.get_config_var("LDLIBRARY"))))' )"
    export PYTHON3_INCLUDE_DIR="$( ${PYTHON3_EXEC} -c 'from distutils import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))' )"
    export ANDROID_ABI=armeabi-v7a
    export ANDROID_NATIVE_API_LEVEL=android-21
    export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang
    
    # 3. Build
    colcon build \
      --packages-ignore cyclonedds rcl_logging_log4cxx rosidl_generator_py \
      --packages-up-to rcljava \
      --cmake-args \
      -DPYTHON_EXECUTABLE=${PYTHON3_EXEC} \
      -DPYTHON_LIBRARY=${PYTHON3_LIBRARY} \
      -DPYTHON_INCLUDE_DIR=${PYTHON3_INCLUDE_DIR} \
      -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
      -DANDROID_FUNCTION_LEVEL_LINKING=OFF \
      -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \
      -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} \
      -DANDROID_STL=c++_shared \
      -DANDROID_ABI=${ANDROID_ABI} \
      -DANDROID_NDK=${ANDROID_NDK} \
      -DTHIRDPARTY=ON \
      -DCOMPILE_EXAMPLES=OFF \
      -DCMAKE_FIND_ROOT_PATH="${PWD}/install"
  3. Install dependencies for ROS 2 Java

    main

    Before building ROS 2 Java, ensure you have the following dependencies installed:

    1. ROS 2: Install via the official ROS 2 installation guide.
    2. Java/JDK: Install a JDK (e.g., sudo apt install default-jdk on Ubuntu).
    3. Gradle: Version 3.2 or later is required.
    4. Build Tools: curl, python3-colcon-common-extensions, python3-pip, and python3-vcstool.
    5. Colcon Gradle Extensions: Install these via pip to enable Gradle support in colcon.

    Note on Java/Gradle compatibility: If you encounter issues between Gradle 3.x and Java 9, consider using Java 8.

    # Install build tools (Ubuntu)
    sudo apt install curl python3-colcon-common-extensions python3-pip python3-vcstool
    
    # Install Gradle extensions for colcon
    python3 -m pip install -U git+https://github.com/colcon/colcon-gradle
    python3 -m pip install --no-deps -U git+https://github.com/colcon/colcon-ros-gradle
  4. Download and Build ROS 2 Java for Desktop

    main

    To build the desktop version of ROS 2 Java, follow these steps to set up a workspace and compile using colcon.

    1. Source your ROS 2 installation.
    2. Create a workspace and import the repositories using the ros2_java_desktop.repos file.
    3. (Linux only) Install ROS dependencies using rosdep.
    4. Build the packages using colcon build.

    Note for Windows users: Use the --merge-install flag during the build process.

    # 1. Source ROS 2
    source /opt/ros/galactic/setup.bash
    
    # 2. Download repositories
    mkdir -p ros2_java_ws/src
    cd ros2_java_ws
    curl -skL https://raw.githubusercontent.com/ros2-java/ros2_java/main/ros2_java_desktop.repos | vcs import src
    
    # 3. Install dependencies (Linux only)
    rosdep install --from-paths src -y -i --skip-keys "ament_tools"
    
    # 4. Build (Linux)
    colcon build --symlink-install
    
    # 4. Build (Windows)
    colcon build --merge-install
  5. Check or wait for service availability

    main

    Before sending requests, you should ensure the service server is available using one of the following methods:

    • boolean isServiceAvailable(): Returns true immediately if the service is available, false otherwise.
    • boolean waitForService(): Blocks the current thread until the service is available or the ROS context is invalidated. Returns true if available, false if the context was shutdown.
    • boolean waitForService(Duration timeout): Blocks until the service is available, the timeout expires, or the ROS context is invalidated.
      • A zero value timeout checks availability and returns immediately.
      • A negative value is treated as an infinite timeout.
      • Returns true if the service is available, false otherwise.
  6. Interact with ROS 2 services using the Client interface

    main

    The Client<T extends ServiceDefinition> interface is the primary way to interact with ROS 2 services in Java. It allows you to send asynchronous requests and wait for service availability.

    Key Capabilities:

    • Asynchronous Requests: Use asyncSendRequest to send a request and receive a Future representing the eventual response. You can also provide a Consumer callback to handle the result.
    • Service Availability: Check if a service server is currently online using isServiceAvailable(), or block execution until it becomes available using waitForService() or waitForService(Duration timeout).
    • Type Inspection: Retrieve the expected request and response message classes via getRequestType() and getResponseType().

    Usage Pattern:

    Typically, you will use waitForService() before attempting to send requests to ensure the server is ready to process them.

    // Example conceptual usage of a Client
    Client<MyServiceDefinition> client = ...;
    
    // Wait up to 5 seconds for the service to appear
    if (client.waitForService(Duration.ofSeconds(5))) {
        MyRequest request = new MyRequest();
        // Set request fields...
        
        // Send request asynchronously
        Future<MyResponse> future = client.asyncSendRequest(request);
        
        // Handle response via Future
        MyResponse response = future.get(); 
    }
  7. Use rosidl_generator_java to generate Java ROS interfaces

    main

    The rosidl_generator_java CLI tool is used to generate Java code from ROS 2 interface definitions. It requires a generator arguments file and a list of typesupport implementations.

    Arguments:

    • --generator-arguments-file: Path to the file containing the generator arguments.
    • --typesupport-impls: A semicolon-separated list (;) of available typesupport implementations.
    rosidl_generator_java --generator-arguments-file <path_to_args_file> --typesupport-impls <impl1>;<impl2>
  8. Send asynchronous service requests with Client.asyncSendRequest()

    main

    The asyncSendRequest method is used to dispatch a service request without blocking the calling thread. It supports two overloads:

    1. Future<V> asyncSendRequest(U request): Returns a Future that will contain the response once the service completes.
    2. Future<V> asyncSendRequest(U request, Consumer<Future<V>> callback): Returns a Future and accepts a callback that is triggered when the request is processed.

    Note: U must be a type extending MessageDefinition that matches the client's request type.

    // Using the callback version
    client.asyncSendRequest(request, (future) -> {
        try {
            MyResponse response = future.get();
            // Process response
        } catch (Exception e) {
            // Handle error
        }
    });