### Source ROS 2 Installation Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Sources the ROS 2 environment setup script. This command should be run in your current shell session to make ROS 2 commands available. ```bash source /opt/ros/galactic/setup.bash ``` -------------------------------- ### Install Gradle on Windows Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Installs Gradle on Windows using Chocolatey. This command assumes Chocolatey is already installed. ```bash choco install gradle ``` -------------------------------- ### Install Gradle on Ubuntu Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Installs Gradle version 3.2 or later on Ubuntu. This is a prerequisite for building ROS 2 Java projects. ```bash sudo apt install gradle ``` -------------------------------- ### Complete Publisher-Subscriber Example in Java Source: https://context7.com/ros2-java/ros2_java/llms.txt This example demonstrates initializing ROS 2 Java, creating a node, publisher, subscriber, and a timer for periodic message publishing. It includes proper resource cleanup. Use this for a full-fledged publisher-subscriber implementation. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.concurrent.Callback; import org.ros2.rcljava.consumers.Consumer; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.publisher.Publisher; import org.ros2.rcljava.subscription.Subscription; import org.ros2.rcljava.timer.WallTimer; import org.ros2.rcljava.qos.QoSProfile; import java.util.concurrent.TimeUnit; public class PubSubExample { private static int messageCount = 0; public static void main(String[] args) { // Initialize ROS 2 Java RCLJava.rclJavaInit(); // Create node Node node = RCLJava.createNode("pubsub_node"); // Create publisher Publisher publisher = node.createPublisher(std_msgs.msg.String.class, "chatter", QoSProfile.keepLast(10)); // Create subscription Subscription subscription = node.createSubscription( std_msgs.msg.String.class, "chatter", new Consumer() { @Override public void accept(std_msgs.msg.String msg) { System.out.println("Received: " + msg.getData()); } }, QoSProfile.keepLast(10) ); // Create timer to publish messages periodically WallTimer timer = node.createWallTimer(1000, TimeUnit.MILLISECONDS, new Callback() { @Override public void call() { std_msgs.msg.String message = new std_msgs.msg.String(); message.setData("Hello, ROS 2! Message #" + (++messageCount)); publisher.publish(message); System.out.println("Published: " + message.getData()); } }); System.out.println("Node '" + node.getName() + "' started"); System.out.println("Publishing and subscribing on topic 'chatter'"); System.out.println("Press Ctrl+C to stop...\n"); // Spin until shutdown try { while (RCLJava.ok() && messageCount < 10) { RCLJava.spinOnce(node); } } finally { // Cleanup resources timer.cancel(); subscription.dispose(); publisher.dispose(); node.dispose(); RCLJava.shutdown(); System.out.println("\nShutdown complete"); } } } ``` -------------------------------- ### Install OpenJDK on Ubuntu Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Installs the default OpenJDK package on Ubuntu systems. Ensure Java is installed before proceeding with ROS 2 Java development. ```bash sudo apt install default-jdk ``` -------------------------------- ### Install Build Tools Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Installs essential build tools required for ROS 2 Java development, including colcon extensions. ```bash sudo apt install curl python3-colcon-common-extensions python3-pip python3-vcstool ``` -------------------------------- ### Install Gradle on macOS Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Installs Gradle using Homebrew on macOS. If compatibility issues arise with Java 9, consider using Java 8. ```bash brew install gradle brew tap caskroom/versions brew cask install java8 export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.8.0.jdk/Contents/Home ``` -------------------------------- ### ROS 2 Java QoS Profile Examples Source: https://context7.com/ros2-java/ros2_java/llms.txt Demonstrates the creation and usage of various QoS profiles in ROS 2 Java, including predefined, keep-last, keep-all, custom chained, and best-effort profiles. Shows how to create publishers with these profiles and print QoS settings. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.publisher.Publisher; import org.ros2.rcljava.qos.QoSProfile; import org.ros2.rcljava.qos.policies.Durability; import org.ros2.rcljava.qos.policies.History; import org.ros2.rcljava.qos.policies.Reliability; import java.time.Duration; public class QoSExample { public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("qos_node"); // Predefined QoS profiles QoSProfile sensorQos = QoSProfile.sensorData(); QoSProfile servicesQos = QoSProfile.servicesDefault(); QoSProfile parametersQos = QoSProfile.parametersDefault(); QoSProfile systemQos = QoSProfile.systemDefault(); // Keep last N messages QoSProfile keepLastQos = QoSProfile.keepLast(10); // Keep all messages QoSProfile keepAllQos = QoSProfile.keepAll(); // Custom QoS with method chaining QoSProfile customQos = QoSProfile.keepLast(100) .setReliability(Reliability.RELIABLE) .setDurability(Durability.TRANSIENT_LOCAL) .setDeadline(Duration.ofSeconds(1)) .setLifespan(Duration.ofSeconds(10)); // Best effort for high-frequency sensor data QoSProfile bestEffortQos = QoSProfile.keepLast(1) .setReliability(Reliability.BEST_EFFORT) .setHistory(History.KEEP_LAST); // Create publishers with different QoS profiles Publisher reliablePub = node.createPublisher(std_msgs.msg.String.class, "reliable_topic", keepLastQos); Publisher sensorPub = node.createPublisher(std_msgs.msg.String.class, "sensor_topic", sensorQos); System.out.println("QoS History: " + customQos.getHistory()); System.out.println("QoS Depth: " + customQos.getDepth()); System.out.println("QoS Reliability: " + customQos.getReliability()); System.out.println("QoS Durability: " + customQos.getDurability()); // Cleanup reliablePub.dispose(); sensorPub.dispose(); node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Install Colcon Gradle Extensions Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Installs the necessary Gradle extensions for colcon, enabling integration with ROS 2 build processes. ```bash 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 ``` -------------------------------- ### ROS 2 Java Executor Examples Source: https://context7.com/ros2-java/ros2_java/llms.txt Demonstrates the usage of SingleThreadedExecutor and MultiThreadedExecutor for managing node callbacks. Includes examples of spinning once, spinning some, and blocking spins. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.executors.MultiThreadedExecutor; import org.ros2.rcljava.executors.SingleThreadedExecutor; import org.ros2.rcljava.node.BaseComposableNode; import org.ros2.rcljava.node.ComposableNode; import org.ros2.rcljava.node.Node; public class ExecutorExample { public static void main(String[] args) { RCLJava.rclJavaInit(); // Create composable nodes ComposableNode publisherNode = new BaseComposableNode("publisher_node"); ComposableNode subscriberNode = new BaseComposableNode("subscriber_node"); // Single-threaded executor - processes callbacks sequentially SingleThreadedExecutor singleExecutor = new SingleThreadedExecutor(); singleExecutor.addNode(publisherNode); singleExecutor.addNode(subscriberNode); // Execute callbacks singleExecutor.spinOnce(); // Process one callback singleExecutor.spinOnce(1000); // Process one callback with 1ms timeout singleExecutor.spinSome(); // Process all available callbacks singleExecutor.spinSome(1000000); // Process callbacks for up to 1ms // Remove nodes singleExecutor.removeNode(publisherNode); singleExecutor.removeNode(subscriberNode); // Multi-threaded executor - processes callbacks concurrently MultiThreadedExecutor multiExecutor = new MultiThreadedExecutor(4); // 4 threads multiExecutor.addNode(publisherNode); multiExecutor.addNode(subscriberNode); // Start spinning in multiple threads (blocking call) // multiExecutor.spin(); // Alternative: Default to number of available processors MultiThreadedExecutor autoExecutor = new MultiThreadedExecutor(); // Using RCLJava convenience methods for simple cases Node simpleNode = RCLJava.createNode("simple_node"); // Spin once RCLJava.spinOnce(simpleNode); // Spin some RCLJava.spinSome(simpleNode); // Blocking spin until shutdown // RCLJava.spin(simpleNode); // Cleanup publisherNode.getNode().dispose(); subscriberNode.getNode().dispose(); simpleNode.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### ROS2 Java Generator Installation Rules Source: https://github.com/ros2-java/ros2_java/blob/main/rosidl_generator_java/CMakeLists.txt Defines the installation rules for the rosidl_generator_java package. It specifies where the executable program and other resource files should be installed on the system. ```cmake install( PROGRAMS bin/rosidl_generator_java DESTINATION lib/rosidl_generator_java ) install( DIRECTORY cmake resource DESTINATION share/${PROJECT_NAME} ) ament_package( CONFIG_EXTRAS "cmake/rosidl_generator_java_get_typesupports.cmake" "cmake/register_java.cmake" "rosidl_generator_java-extras.cmake.in" ) ``` -------------------------------- ### Create and Use a ROS 2 Publisher in Java Source: https://context7.com/ros2-java/ros2_java/llms.txt Shows how to create a ROS 2 publisher to send messages on a topic. Supports default and custom Quality of Service (QoS) profiles. Includes an example of publishing a String message. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.publisher.Publisher; import org.ros2.rcljava.qos.QoSProfile; public class PublisherExample { public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("publisher_node"); // Create a publisher with default QoS Publisher publisher = node.createPublisher(std_msgs.msg.String.class, "my_topic"); // Create a publisher with custom QoS (depth 10, reliable) Publisher reliablePublisher = node.createPublisher(std_msgs.msg.String.class, "reliable_topic", QoSProfile.keepLast(10)); // Create and publish a message std_msgs.msg.String message = new std_msgs.msg.String(); message.setData("Hello, ROS 2 from Java!"); publisher.publish(message); System.out.println("Published: " + message.getData()); System.out.println("Number of publishers: " + node.getPublishers().size()); // Cleanup publisher.dispose(); reliablePublisher.dispose(); node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Create and Use a ROS 2 Service Client Source: https://context7.com/ros2-java/ros2_java/llms.txt Use `node.createClient()` to create a client for calling ROS 2 services. This example shows how to send a request asynchronously and handle the response, including waiting for service availability and disposing of resources. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.client.Client; import org.ros2.rcljava.node.Node; import java.time.Duration; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; public class ClientExample { public static void main(String[] args) throws Exception { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("client_node"); // Create a client for the AddTwoInts service Client client = node.createClient(rcljava.srv.AddTwoInts.class, "add_two_ints"); // Wait for the service to become available (timeout: 10 seconds) if (!client.waitForService(Duration.ofSeconds(10))) { System.out.println("Service not available, exiting..."); return; } // Create a request rcljava.srv.AddTwoInts_Request request = new rcljava.srv.AddTwoInts_Request(); request.setA(5); request.setB(7); // Send the request asynchronously Future future = client.asyncSendRequest(request); // Wait for the response (timeout: 10 seconds) rcljava.srv.AddTwoInts_Response response = future.get(10, TimeUnit.SECONDS); System.out.println("Result: " + request.getA() + " + " + request.getB() + " = " + response.getSum()); // Check service availability System.out.println("Service available: " + client.isServiceAvailable()); // Cleanup client.dispose(); node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Build ROS 2 Java Desktop Packages (Windows) Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Builds the ROS 2 Java desktop packages using colcon with merge installation. The `--merge-install` option is specific to Windows builds. ```bash colcon build --merge-install ``` -------------------------------- ### Install ROS Dependencies on Linux Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Installs ROS dependencies for the downloaded packages on Linux systems using rosdep. This ensures all required system libraries are present. ```bash rosdep install --from-paths src -y -i --skip-keys "ament_tools" ``` -------------------------------- ### Build ROS 2 Java Desktop Packages (Linux) Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Builds the ROS 2 Java desktop packages using colcon with symlink installation. This is the standard build command for Linux. ```bash colcon build --symlink-install ``` -------------------------------- ### Create and Use a ROS 2 Timer Source: https://context7.com/ros2-java/ros2_java/llms.txt Use `node.createWallTimer()` to schedule callbacks at regular intervals. This example demonstrates creating a timer, handling its callbacks, checking its status, and canceling it. Ensure `RCLJava.spinOnce(node)` is called to process timer events. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.concurrent.Callback; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.timer.WallTimer; import java.util.concurrent.TimeUnit; public class TimerExample { private static int counter = 0; public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("timer_node"); // Create a timer that fires every 500 milliseconds WallTimer timer = node.createWallTimer(500, TimeUnit.MILLISECONDS, new Callback() { @Override public void call() { counter++; System.out.println("Timer callback #" + counter); // Stop after 10 iterations if (counter >= 10) { System.out.println("Timer completed"); } } }); System.out.println("Timer period: " + timer.getTimerPeriodNS() + " ns"); System.out.println("Timer canceled: " + timer.isCanceled()); // Spin while timer is active while (RCLJava.ok() && counter < 10) { RCLJava.spinOnce(node); } // Cancel and reset timer timer.cancel(); System.out.println("Timer canceled: " + timer.isCanceled()); // Cleanup node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### ROS 2 Java Publisher Event Handler Setup Source: https://context7.com/ros2-java/ros2_java/llms.txt Shows how to create and register event handlers for publisher status changes, such as liveliness lost and offered deadline missed events. Event handlers are removed when no longer needed. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.consumers.Consumer; import org.ros2.rcljava.events.EventHandler; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.publisher.Publisher; import org.ros2.rcljava.publisher.statuses.LivelinessLost; import org.ros2.rcljava.publisher.statuses.OfferedDeadlineMissed; import org.ros2.rcljava.publisher.statuses.OfferedQosIncompatible; public class PublisherEventExample { public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("event_node"); Publisher publisher = node.createPublisher(std_msgs.msg.String.class, "event_topic"); // Monitor liveliness lost events EventHandler livelinessHandler = publisher.createEventHandler( LivelinessLost.factory, new Consumer() { @Override public void accept(LivelinessLost status) { System.out.println("Liveliness lost! Total count: " + status.totalCount); System.out.println("Count change: " + status.totalCountChange); } } ); // Monitor offered deadline missed events EventHandler deadlineHandler = publisher.createEventHandler( OfferedDeadlineMissed.factory, status -> { System.out.println("Deadline missed! Total: " + status.totalCount); } ); System.out.println("Event handlers registered: " + publisher.getEventHandlers().size()); // Remove event handler when no longer needed publisher.removeEventHandler(livelinessHandler); // Cleanup deadlineHandler.dispose(); publisher.dispose(); node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### ROS 2 Java Package CMake Configuration Source: https://github.com/ros2-java/ros2_java/blob/main/ament_cmake_export_jni_libraries/CMakeLists.txt Standard CMake configuration for a ROS 2 Java package. Includes finding core ament packages and setting up installation. ```cmake cmake_minimum_required(VERSION 3.5) project(ament_cmake_export_jni_libraries NONE) find_package(ament_cmake_core REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() endif() ament_package( CONFIG_EXTRAS "ament_cmake_export_jni_libraries-extras.cmake" ) install( DIRECTORY cmake DESTINATION share/${PROJECT_NAME} ) ``` -------------------------------- ### Introspect ROS 2 Graph in Java Source: https://context7.com/ros2-java/ros2_java/llms.txt This Java code snippet shows how to query the ROS 2 graph to discover nodes, topics, and services. It also demonstrates how to get publisher and subscription information for a specific topic. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.graph.EndpointInfo; import org.ros2.rcljava.graph.NameAndTypes; import org.ros2.rcljava.graph.NodeNameInfo; import org.ros2.rcljava.node.Node; import java.util.Collection; public class GraphIntrospectionExample { public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("introspection_node"); // Get all node names in the graph Collection nodeNames = node.getNodeNames(); System.out.println("Discovered nodes:"); for (NodeNameInfo info : nodeNames) { System.out.println(" - " + info); } // Get all topic names and their types Collection topics = node.getTopicNamesAndTypes(); System.out.println("\nDiscovered topics:"); for (NameAndTypes topic : topics) { System.out.println(" - " + topic); } // Get all service names and their types Collection services = node.getServiceNamesAndTypes(); System.out.println("\nDiscovered services:"); for (NameAndTypes service : services) { System.out.println(" - " + service); } // Get publisher info for a specific topic Collection publisherInfo = node.getPublishersInfo("/my_topic"); System.out.println("\nPublishers on /my_topic:"); for (EndpointInfo info : publisherInfo) { System.out.println(" - " + info); } // Get subscription info for a specific topic Collection subscriptionInfo = node.getSubscriptionsInfo("/my_topic"); System.out.println("\nSubscriptions on /my_topic:"); for (EndpointInfo info : subscriptionInfo) { System.out.println(" - " + info); } // Cleanup node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### ROS 2 Java Build Configuration Source: https://github.com/ros2-java/ros2_java/blob/main/ament_cmake_export_jars/CMakeLists.txt This CMakeLists.txt file configures the build for a ROS 2 Java package. It finds necessary packages, handles testing dependencies, and defines package installation. ```cmake cmake_minimum_required(VERSION 3.5) project(ament_cmake_export_jars NONE) find_package(ament_cmake_core REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) ament_lint_auto_find_test_dependencies() endif() ament_package( CONFIG_EXTRAS "ament_cmake_export_jars-extras.cmake" ) install( DIRECTORY cmake DESTINATION share/${PROJECT_NAME} ) ``` -------------------------------- ### Declare and Manage ROS 2 Java Node Parameters Source: https://context7.com/ros2-java/ros2_java/llms.txt This snippet demonstrates how to declare parameters with different data types (string, int, double, boolean), nested parameters, and parameters with descriptors. It also shows how to retrieve parameter values, use fallback defaults, get parameters by prefix, set parameter values, and check for parameter existence. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.parameters.ParameterCallback; import org.ros2.rcljava.parameters.ParameterVariant; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; public class ParameterExample { public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("parameter_node"); // Declare parameters with initial values node.declareParameter(new ParameterVariant("my_string", "default_value")); node.declareParameter(new ParameterVariant("my_int", 42)); node.declareParameter(new ParameterVariant("my_double", 3.14)); node.declareParameter(new ParameterVariant("my_bool", true)); node.declareParameter(new ParameterVariant("nested.param", "nested_value")); // Declare parameter with descriptor rcl_interfaces.msg.ParameterDescriptor descriptor = new rcl_interfaces.msg.ParameterDescriptor(); descriptor.setName("described_param"); descriptor.setDescription("A parameter with description"); node.declareParameter(new ParameterVariant("described_param", 100), descriptor); // Get parameter values ParameterVariant stringParam = node.getParameter("my_string"); System.out.println("String parameter: " + stringParam.asString()); ParameterVariant intParam = node.getParameter("my_int"); System.out.println("Integer parameter: " + intParam.asInt()); // Get parameter with default fallback ParameterVariant defaultParam = node.getParameterOr("nonexistent", new ParameterVariant("fallback", "default")); System.out.println("Fallback parameter: " + defaultParam.asString()); // Get parameters by prefix Map nestedParams = node.getParametersByPrefix("nested"); System.out.println("Nested parameters: " + nestedParams.size()); // Set parameter value rcl_interfaces.msg.SetParametersResult result = node.setParameter(new ParameterVariant("my_int", 100)); System.out.println("Set parameter successful: " + result.getSuccessful()); // Add callback for parameter changes node.addOnSetParametersCallback(new ParameterCallback() { @Override public rcl_interfaces.msg.SetParametersResult callback(List parameters) { rcl_interfaces.msg.SetParametersResult cbResult = new rcl_interfaces.msg.SetParametersResult(); for (ParameterVariant param : parameters) { System.out.println("Parameter changed: " + param.getName() + " = " + param.getTypeName()); } cbResult.setSuccessful(true); return cbResult; } }); // Check if parameter exists System.out.println("Has 'my_string': " + node.hasParameter("my_string")); // Undeclare parameter node.undeclareParameter("my_bool"); System.out.println("Has 'my_bool': " + node.hasParameter("my_bool")); // Cleanup node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Create ROS 2 Nodes in Java Source: https://context7.com/ros2-java/ros2_java/llms.txt Demonstrates creating ROS 2 nodes with different configurations, including a simple node, a namespaced node, and a node with custom options like allowing undeclared parameters. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.contexts.Context; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.node.NodeOptions; public class NodeExample { public static void main(String[] args) { RCLJava.rclJavaInit(); // Create a simple node Node simpleNode = RCLJava.createNode("simple_node"); // Create a node with namespace Context context = RCLJava.getDefaultContext(); Node namespacedNode = RCLJava.createNode("namespaced_node", "/my_namespace", context); // Create a node with custom options NodeOptions options = new NodeOptions(); options.setAllowUndeclaredParameters(true); Node customNode = RCLJava.createNode("custom_node", "", context, options); System.out.println("Simple node: " + simpleNode.getName()); System.out.println("Namespaced node: " + namespacedNode.getNamespace() + "/" + namespacedNode.getName()); // Cleanup simpleNode.dispose(); namespacedNode.dispose(); customNode.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Download ROS 2 Java Repositories Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Downloads the ROS 2 Java desktop repositories into a new workspace using vcs import. This sets up the source directory for building. ```bash 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 ``` -------------------------------- ### Monitor Subscription Events in Java Source: https://context7.com/ros2-java/ros2_java/llms.txt This snippet demonstrates how to set up event handlers for liveliness changes and requested deadline misses on a ROS 2 subscription. Ensure the necessary ROS 2 Java libraries are included. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.consumers.Consumer; import org.ros2.rcljava.events.EventHandler; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.subscription.Subscription; import org.ros2.rcljava.subscription.statuses.LivelinessChanged; import org.ros2.rcljava.subscription.statuses.MessageLost; import org.ros2.rcljava.subscription.statuses.RequestedDeadlineMissed; public class SubscriptionEventExample { public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("sub_event_node"); Subscription subscription = node.createSubscription( std_msgs.msg.String.class, "event_topic", msg -> System.out.println("Message: " + msg.getData()) ); // Monitor liveliness changes EventHandler livelinessHandler = subscription.createEventHandler( LivelinessChanged.factory, new Consumer() { @Override public void accept(LivelinessChanged status) { System.out.println("Publishers alive: " + status.aliveCount); System.out.println("Publishers not alive: " + status.notAliveCount); System.out.println("Alive change: " + status.aliveCountChange); System.out.println("Not alive change: " + status.notAliveCountChange); } } ); // Monitor requested deadline missed EventHandler deadlineHandler = subscription.createEventHandler( RequestedDeadlineMissed.factory, status -> System.out.println("Deadline missed count: " + status.totalCount) ); // Monitor lost messages (not available on all RMW implementations) // EventHandler lostHandler = // subscription.createEventHandler( // MessageLost.factory, // status -> System.out.println("Messages lost: " + status.totalCount) // ); System.out.println("Subscription event handlers: " + subscription.getEventHandlers().size()); // Cleanup livelinessHandler.dispose(); deadlineHandler.dispose(); subscription.dispose(); node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Set Android Build Configuration Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Sets environment variables required for building ROS 2 Java for Android, including Python paths, Android ABI, native API level, and toolchain name. ```bash 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 ``` -------------------------------- ### Create ROS 2 Java Subscription Source: https://context7.com/ros2-java/ros2_java/llms.txt Use `node.createSubscription()` to set up a subscription that receives messages on a specified topic. A callback function is provided to process incoming messages. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.consumers.Consumer; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.subscription.Subscription; import org.ros2.rcljava.qos.QoSProfile; public class SubscriptionExample { public static void main(String[] args) { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("subscription_node"); // Create a subscription with a callback Subscription subscription = node.createSubscription( std_msgs.msg.String.class, "my_topic", new Consumer() { @Override public void accept(std_msgs.msg.String msg) { System.out.println("Received: " + msg.getData()); } } ); // Create subscription with custom QoS Subscription reliableSubscription = node.createSubscription( std_msgs.msg.String.class, "reliable_topic", msg -> System.out.println("Reliable message: " + msg.getData()), QoSProfile.keepLast(10) ); System.out.println("Subscriptions created: " + node.getSubscriptions().size()); // Spin to receive messages while (RCLJava.ok()) { RCLJava.spinOnce(node); } // Cleanup subscription.dispose(); reliableSubscription.dispose(); node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Create ROS 2 Java Service Server Source: https://context7.com/ros2-java/ros2_java/llms.txt Use `node.createService()` to create a service server that handles incoming client requests. A callback is provided to process requests and generate responses. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.consumers.TriConsumer; import org.ros2.rcljava.node.Node; import org.ros2.rcljava.service.RMWRequestId; import org.ros2.rcljava.service.Service; public class ServiceExample { public static void main(String[] args) throws Exception { RCLJava.rclJavaInit(); Node node = RCLJava.createNode("service_node"); // Create a service that adds two integers Service service = node.createService( rcljava.srv.AddTwoInts.class, "add_two_ints", new TriConsumer() { @Override public void accept(RMWRequestId header, rcljava.srv.AddTwoInts_Request request, rcljava.srv.AddTwoInts_Response response) { long result = request.getA() + request.getB(); response.setSum(result); System.out.println("Service called: " + request.getA() + " + " + request.getB() + " = " + result); } } ); System.out.println("Service '" + service.getServiceName() + "' ready"); System.out.println("Number of services: " + node.getServices().size()); // Spin to handle service requests RCLJava.spin(node); // Cleanup service.dispose(); node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Initialize and Shutdown RCLJava Source: https://context7.com/ros2-java/ros2_java/llms.txt Initializes the ROS 2 Java runtime and shuts it down. Must be called before creating any ROS 2 objects. Displays the RMW implementation if ROS 2 is running. ```java import org.ros2.rcljava.RCLJava; import org.ros2.rcljava.node.Node; public class BasicExample { public static void main(String[] args) { // Initialize ROS 2 Java RCLJava.rclJavaInit(); // Check if ROS 2 is running if (RCLJava.ok()) { System.out.println("ROS 2 Java initialized successfully"); System.out.println("RMW Implementation: " + RCLJava.getRMWIdentifier()); } // Create a node Node node = RCLJava.createNode("my_node"); System.out.println("Node name: " + node.getName()); // Clean up resources node.dispose(); RCLJava.shutdown(); } } ``` -------------------------------- ### Clone ROS 2 and ROS 2 Java Source Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Clones the ROS 2 and ROS 2 Java source code into the specified workspace directory using vcs import. ```bash 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 ``` -------------------------------- ### ROS2 Java Generator CMakeLists.txt Configuration Source: https://github.com/ros2-java/ros2_java/blob/main/rosidl_generator_java/CMakeLists.txt This is the main CMakeLists.txt for the rosidl_generator_java package. It sets up the project, finds necessary packages like ament_cmake, rcljava_common, and Java Development Kit (JDK), and configures build options. ```cmake cmake_minimum_required(VERSION 3.5) project(rosidl_generator_java) find_package(ament_cmake REQUIRED) find_package(rcljava_common REQUIRED) include(CrossCompilingExtra) ament_export_dependencies(ament_cmake) ament_export_dependencies(rosidl_cmake) ament_python_install_package(${PROJECT_NAME}) if(CMAKE_CROSSCOMPILING) find_host_package(Java COMPONENTS Development REQUIRED) else() find_package(Java COMPONENTS Development REQUIRED) endif() if(NOT ANDROID) find_package(JNI REQUIRED) endif() include(UseJava) include(JavaExtra) ament_index_register_resource("rosidl_generator_packages") ``` -------------------------------- ### Build ROS 2 Java for Android Source: https://github.com/ros2-java/ros2_java/blob/main/README.md Builds the ROS 2 Java project for Android using colcon, excluding specific packages and configuring CMake arguments for cross-compilation. ```bash 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" ``` -------------------------------- ### Configure JNI Sources and Libraries Source: https://github.com/ros2-java/ros2_java/blob/main/rcljava/CMakeLists.txt This CMake code configures the JNI sources for the project, dynamically generating library names and setting output properties. It handles platform-specific naming conventions for shared libraries. ```cmake set(${PROJECT_NAME}_jni_sources "src/main/cpp/org_ros2_rcljava_RCLJava.cpp" "src/main/cpp/org_ros2_rcljava_Time.cpp" "src/main/cpp/org_ros2_rcljava_client_ClientImpl.cpp" "src/main/cpp/org_ros2_rcljava_contexts_ContextImpl.cpp" "src/main/cpp/org_ros2_rcljava_detail_QosIncompatibleStatus.cpp" "src/main/cpp/org_ros2_rcljava_executors_BaseExecutor.cpp" "src/main/cpp/org_ros2_rcljava_events_EventHandlerImpl.cpp" "src/main/cpp/org_ros2_rcljava_graph_EndpointInfo" "src/main/cpp/org_ros2_rcljava_publisher_statuses_LivelinessLost.cpp" "src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedDeadlineMissed.cpp" "src/main/cpp/org_ros2_rcljava_publisher_statuses_OfferedQosIncompatible.cpp" "src/main/cpp/org_ros2_rcljava_node_NodeImpl.cpp" "src/main/cpp/org_ros2_rcljava_publisher_PublisherImpl.cpp" "src/main/cpp/org_ros2_rcljava_qos_QoSProfile.cpp" "src/main/cpp/org_ros2_rcljava_service_ServiceImpl.cpp" "src/main/cpp/org_ros2_rcljava_subscription_SubscriptionImpl.cpp" "src/main/cpp/org_ros2_rcljava_subscription_statuses_LivelinessChanged.cpp" "src/main/cpp/org_ros2_rcljava_subscription_statuses_MessageLost.cpp" "src/main/cpp/org_ros2_rcljava_subscription_statuses_RequestedDeadlineMissed.cpp" "src/main/cpp/org_ros2_rcljava_subscription_statuses_RequestedQosIncompatible.cpp" "src/main/cpp/org_ros2_rcljava_time_Clock.cpp" "src/main/cpp/org_ros2_rcljava_timer_WallTimerImpl.cpp" ) foreach(_jni_source ${${PROJECT_NAME}_jni_sources}) get_filename_component(_target_name "${_jni_source}" NAME_WE) string_camel_case_to_lower_case_underscore("${_target_name}" _target_name) add_library(${_target_name} SHARED ${_jni_source} ) if(WIN32) set(_jni_prefix "") else() set(_jni_prefix "lib") endif() set_target_properties(${_target_name} PROPERTIES OUTPUT_NAME "${_jni_prefix}${_target_name}__jni" ) set_properties("${_target_name}" "") if(WIN32) set_properties("${_target_name}" "_DEBUG") set_properties("${_target_name}" "_MINSIZEREL") set_properties("${_target_name}" "_RELEASE") set_properties("${_target_name}" "_RELWITHDEBINFO") endif() ament_target_dependencies(${_target_name} "builtin_interfaces" "rcl" "rcljava_common" "rcl_interfaces" "rcpputils" ) target_include_directories(${_target_name} PUBLIC ${JNI_INCLUDE_DIRS} ) ament_export_jni_libraries(${_target_name}) install(TARGETS ${_target_name} ARCHIVE DESTINATION lib/jni LIBRARY DESTINATION lib/jni ) endforeach() ``` -------------------------------- ### Conditional Library Build with C Typesupport Source: https://github.com/ros2-java/ros2_java/blob/main/rcljava/CMakeLists.txt This snippet ensures that the rcljava library is only built if a C typesupport exists. It checks for the presence of a C typesupport library and skips the build if none is found. ```cmake get_rmw_typesupport(typesupport_impls "rmw_implementation" LANGUAGE "c") if(typesupport_impls STREQUAL "") message(STATUS "Skipping rcljava because no C typesupport library was found.") return() endif() ``` -------------------------------- ### List Java Source Files Source: https://github.com/ros2-java/ros2_java/blob/main/rcljava/CMakeLists.txt This CMake variable lists all the Java source files for the rcljava project. These files are used during the build process to compile the Java components of the library. ```cmake set(${PROJECT_NAME}_sources "src/main/java/org/ros2/rcljava/RCLJava.java" "src/main/java/org/ros2/rcljava/Time.java" "src/main/java/org/ros2/rcljava/client/Client.java" "src/main/java/org/ros2/rcljava/client/ClientImpl.java" "src/main/java/org/ros2/rcljava/concurrent/Callback.java" "src/main/java/org/ros2/rcljava/concurrent/RCLFuture.java" "src/main/java/org/ros2/rcljava/contexts/Context.java" "src/main/java/org/ros2/rcljava/contexts/ContextImpl.java" "src/main/java/org/ros2/rcljava/consumers/BiConsumer.java" "src/main/java/org/ros2/rcljava/consumers/Consumer.java" "src/main/java/org/ros2/rcljava/consumers/TriConsumer.java" "src/main/java/org/ros2/rcljava/detail/QosIncompatibleStatus.java" "src/main/java/org/ros2/rcljava/events/EventHandler.java" "src/main/java/org/ros2/rcljava/events/EventHandlerImpl.java" "src/main/java/org/ros2/rcljava/events/EventStatus.java" "src/main/java/org/ros2/rcljava/events/PublisherEventStatus.java" "src/main/java/org/ros2/rcljava/events/SubscriptionEventStatus.java" "src/main/java/org/ros2/rcljava/graph/NameAndTypes.java" "src/main/java/org/ros2/rcljava/graph/NodeNameInfo.java" "src/main/java/org/ros2/rcljava/executors/AnyExecutable.java" "src/main/java/org/ros2/rcljava/executors/BaseExecutor.java" "src/main/java/org/ros2/rcljava/executors/Executor.java" "src/main/java/org/ros2/rcljava/executors/MultiThreadedExecutor.java" "src/main/java/org/ros2/rcljava/executors/SingleThreadedExecutor.java" "src/main/java/org/ros2/rcljava/graph/EndpointInfo.java" "src/main/java/org/ros2/rcljava/node/BaseComposableNode.java" "src/main/java/org/ros2/rcljava/node/ComposableNode.java" "src/main/java/org/ros2/rcljava/node/Node.java" "src/main/java/org/ros2/rcljava/node/NodeImpl.java" "src/main/java/org/ros2/rcljava/node/NodeOptions.java" "src/main/java/org/ros2/rcljava/parameters/client/AsyncParametersClient.java" "src/main/java/org/ros2/rcljava/parameters/client/AsyncParametersClientImpl.java" "src/main/java/org/ros2/rcljava/parameters/client/SyncParametersClient.java" "src/main/java/org/ros2/rcljava/parameters/client/SyncParametersClientImpl.java" ) ```