### Install Compiled Linux Kernel and Headers Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Installs the newly compiled Linux kernel image and header packages using `sudo apt install`. This makes the real-time kernel available for booting on the system. ```console $ sudo apt install ../linux-headers-$KERNEL_VERSION-rt$RT_PATCH_VERSION*.deb \ ../linux-image-$KERNEL_VERSION-rt$RT_PATCH_VERSION*.deb ``` -------------------------------- ### CMakeLists.txt for C++ UR Dashboard Client Example with FetchContent Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/installation.rst CMake configuration file for the minimal C++ dashboard client example. It uses FetchContent to download and build the ur_client_library as part of the project, ensuring all dependencies are met without prior system installation. ```cmake cmake_minimum_required(VERSION 3.11.0) # That's the minimum required version for FetchContent project(minimal_example) include(FetchContent) FetchContent_Declare( ur_client_library GIT_REPOSITORY https://github.com/UniversalRobots/Universal_Robots_Client_Library.git GIT_TAG master ) # This will download the ur_client_library and replace the `find_package(ur_client_library)` call. FetchContent_MakeAvailable(ur_client_library) add_executable(db_client main.cpp) target_link_libraries(db_client ur_client_library::urcl) ``` -------------------------------- ### Start URSim Docker with Mounted URCaps and Programs Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command starts the URSim Docker container, similar to the basic startup, but includes bind mounts for the local URCaps and programs directories. This allows the simulated robot to access custom URCaps and persist program changes made within the simulator. ```bash docker run --rm -it -p 5900:5900 -p 6080:6080 -v ${HOME}/.ursim/urcaps:/urcaps -v ${HOME}/.ursim/programs:/ursim/programs --name ursim universalrobots/ursim_e-series ``` -------------------------------- ### C++ Example: Connect to UR Dashboard Server and Get PolyScope Version Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/installation.rst A minimal C++ example demonstrating how to use the ur_client_library to connect to a Universal Robots dashboard server, send the 'PolyscopeVersion' command, and print the received answer. Note that this example will not work on PolyScope X versions. ```cpp #include #include int main(int argc, char* argv[]) { urcl::DashboardClient my_client("192.168.56.101"); bool connected = my_client.connect(); if (connected) { std::string answer = my_client.sendAndReceive("PolyscopeVersion\n"); std::cout << answer << std::endl; my_client.disconnect(); } return 0; } ``` -------------------------------- ### C++ ScriptSender Example for Universal Robots Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/script_sender.rst This C++ snippet illustrates the basic setup of a ScriptSender to listen on port 12345 and send a simple textmsg("Hello, World!") script to a Universal Robots controller upon request. It simulates the core logic of the script_sender.cpp example from the Universal Robots Client Library, showing how to define the port, initialize a sender, and simulate sending a script. ```c++ constexpr uint32_t PORT = 12345; #include #include #include #include // Placeholder for a simplified ScriptSender class or function // In a real library, this would be a more complex class handling network communication. class ScriptSender { public: ScriptSender(uint32_t port) : listenPort_(port) { std::cout << "ScriptSender initialized on port " << listenPort_ << std::endl; // In a real implementation, this would start a server thread // or prepare for incoming connections. } // Simulate sending a script when requested void sendScript(const std::string& scriptContent) { std::cout << "Received request to send script: \"" << scriptContent << "\"" << std::endl; // This is where the actual communication with the robot would happen. // For this example, we just print it. std::cout << "Script \"" << scriptContent << "\" sent to robot." << std::endl; } private: uint32_t listenPort_; }; int main() { ScriptSender sender(PORT); // Simulate a request coming in after some time std::cout << "Waiting for a request to send script..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(2)); // Simulate delay // When a request comes, send the predefined script sender.sendScript("textmsg(\"Hello, World!\")"); std::cout << "Example finished." << std::endl; return 0; } ``` -------------------------------- ### Build and Run C++ UR Dashboard Client Example Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/installation.rst Commands to compile the C++ dashboard client example using CMake and then execute the compiled binary. Requires a Universal Robots controller to be available at the specified IP address (192.168.56.101). ```console $ mkdir build && cd build $ cmake .. $ cmake --build . $ ./db_client ``` -------------------------------- ### Install Lowlatency Kernel on Ubuntu Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This command installs the `linux-lowlatency` package, providing a kernel optimized for reduced latency. This option is simpler to implement and can be sufficient for many real-time applications, offering improved performance over a generic kernel. ```console $ sudo apt install linux-lowlatency ``` -------------------------------- ### Install Build Dependencies for PREEMPT_RT Kernel Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This command installs essential tools and libraries required to compile a custom Linux kernel from source. These dependencies include compilers, build utilities, and development headers necessary for a successful kernel build process. ```console $ sudo apt-get install build-essential bc ca-certificates gnupg2 libssl-dev wget gawk flex bison libelf-dev dwarves ``` -------------------------------- ### CMake Configuration for Universal Robots Client Library Examples Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/examples/CMakeLists.txt This CMakeLists.txt file configures the build process for various example applications demonstrating the use of the Universal Robots Client Library. It defines multiple executables, each corresponding to a specific example (e.g., driver, RTDE client, dashboard, force mode), and links them against the `ur_client_library::urcl` target. ```CMake cmake_minimum_required(VERSION 3.14.0) project(ur_driver_examples) # find_package(ur_client_library REQUIRED) add_executable(driver_example full_driver.cpp) target_link_libraries(driver_example ur_client_library::urcl) add_executable(primary_pipeline_example primary_pipeline.cpp) target_link_libraries(primary_pipeline_example ur_client_library::urcl) add_executable(primary_pipeline_calibration_example primary_pipeline_calibration.cpp) target_link_libraries(primary_pipeline_calibration_example ur_client_library::urcl) add_executable(rtde_client_example rtde_client.cpp) target_link_libraries(rtde_client_example ur_client_library::urcl) add_executable(dashboard_example dashboard_example.cpp) target_link_libraries(dashboard_example ur_client_library::urcl) add_executable(spline_example spline_example.cpp) target_link_libraries(spline_example ur_client_library::urcl) add_executable(tool_contact_example tool_contact_example.cpp) target_link_libraries(tool_contact_example ur_client_library::urcl) add_executable(freedrive_example freedrive_example.cpp) target_link_libraries(freedrive_example ur_client_library::urcl) add_executable(force_mode_example force_mode_example.cpp) target_link_libraries(force_mode_example ur_client_library::urcl) add_executable(script_sender_example script_sender.cpp) target_link_libraries(script_sender_example ur_client_library::urcl) add_executable(trajectory_point_interface_example trajectory_point_interface.cpp) target_link_libraries(trajectory_point_interface_example ur_client_library::urcl) add_executable(instruction_executor instruction_executor.cpp) target_link_libraries(instruction_executor ur_client_library::urcl) ``` -------------------------------- ### Install and Initialize Pre-Commit for Code Formatting Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/README.md This snippet provides the commands to install `pre-commit` using `pipx` and then initialize it for the current repository. `pre-commit` is a tool that helps automate code formatting and other checks, preventing falsely formatted code from being committed. ```bash pipx install pre-commit pre-commit install ``` -------------------------------- ### Start URSim Docker Container for Universal Robots Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command starts a URSim Docker container, configuring it to run on `192.168.56.101` with the `external_control` URCap preinstalled. User-created programs and installation changes will be persistently stored in `${HOME}/.ursim/programs`. This script can be run directly from the package's `scripts` folder if the client library was installed from a source other than ROS/ROS 2 or compiled manually. ```bash ros2 run ur_client_library start_ursim.sh ``` -------------------------------- ### Example GRUB Default Entry String Format Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This snippet illustrates the required format for the GRUB default entry string. It combines a submenu name and an entry name, separated by a `>`. It is critical to use double quotes and ensure no spaces around the `>` character for correct parsing by GRUB. ```text "Advanced options for Ubuntu>Ubuntu, with Linux 5.15.158-rt76" ``` -------------------------------- ### Start URSim with ROS 1 Script Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command executes a convenience script from the ur_client_library package for ROS 1. It automates the startup of a URSim Docker container, pre-configuring it with the external_control URCap and persistent storage for programs, accessible at a static IP. ```bash rosrun ur_client_library start_ursim.sh ``` -------------------------------- ### Install CPU Frequency Utilities (cpufrequtils) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This command installs the `cpufrequtils` package, which provides tools like `cpufreq-info` to inspect and manage CPU frequency scaling settings. This utility is a prerequisite for configuring the CPU governor to a fixed performance mode, preventing dynamic clock frequency changes. ```console $ sudo apt install cpufrequtils ``` -------------------------------- ### Build Universal Robots Client Library Standalone with CMake Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/installation.rst Steps to clone the repository, create a build directory, configure with CMake, compile, and install the ur_client_library into the system for standalone use. ```console $ git clone https://github.com/UniversalRobots/Universal_Robots_Client_Library ur_client_library $ cd ur_client_library $ mkdir build && cd build $ cmake .. $ make $ sudo make install ``` -------------------------------- ### Verify Network Connection with Ping Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/network_setup.rst Example of using the 'ping' command from the remote PC to confirm successful network connectivity with the UR robot's IP address. A successful ping indicates the connection is established. ```console $ ping 192.168.56.101 PING 192.168.56.101 (192.168.56.101) 56(84) bytes of data. 64 bytes from 192.168.56.101: icmp_seq=1 ttl=64 time=0.037 ms 64 bytes from 192.168.56.101: icmp_seq=2 ttl=64 time=0.043 ms 64 bytes from 192.168.56.101: icmp_seq=3 ttl=64 time=0.047 ms ``` -------------------------------- ### Import GPG Keys for Kernel Source Verification Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This command imports the public GPG keys of prominent kernel developers. Importing these keys allows for the verification of digital signatures on downloaded kernel source and patch files, ensuring their authenticity and integrity before installation. ```console $ gpg2 --locate-keys torvalds@kernel.org gregkh@kernel.org ``` -------------------------------- ### Initialize Universal Robots Driver in C++ Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/tool_contact_example.rst Initializes the Universal Robots driver, setting up the connection for robot control. This snippet shows how to create and configure the driver instance, typically in headless mode, before registering callbacks or starting operations. ```C++ bool headless_mode = true; // ... driver initialization and connection code for g_my_robot ... ``` -------------------------------- ### Assembling and Running the Primary Interface Pipeline Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/primary_pipeline.rst This snippet illustrates how to connect the producer and consumer to form the complete pipeline. It shows the instantiation of the Pipeline class, passing in the configured producer, consumer, a name, and a notifier, followed by initiating the pipeline's execution. ```c++ urcl::Pipeline pipeline(std::move(prod), std::move(consumer), "primary_pipeline", std::make_unique()); pipeline.run(); ``` -------------------------------- ### Start URSim Docker Container Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command starts a Docker container named "ursim" running a simulated UR5e robot. It exposes ports 5900 (VNC) and 6080 (browser-based Polyscope) to the host machine. Users can skip port forwarding for increased security, accessing Polyscope via the container's IP, or restrict forwarding to specific network interfaces. ```bash docker run --rm -it -p 5900:5900 -p 6080:6080 --name ursim universalrobots/ursim_e-series ``` -------------------------------- ### Setting up the Producer for Primary Interface Data Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/primary_pipeline.rst This snippet demonstrates how to initialize the producer component of the pipeline. It involves creating a stream to read data, a parser to interpret the data, and then setting up the producer with these components to begin data acquisition. ```c++ // First of all, we need a stream auto stream = std::make_unique(); auto parser = std::make_unique(); urcl::primary_interface::PrimaryProducer prod(std::move(stream), std::move(parser)); prod.setupProducer(); ``` -------------------------------- ### Build Linux Kernel Debian Packages Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Compiles the Linux kernel and packages it into Debian format (`.deb`) using all available CPU cores. This command generates installable kernel image and header packages. ```console $ make -j `getconf _NPROCESSORS_ONLN` deb-pkg ``` -------------------------------- ### List Available GRUB Boot Entries Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This command uses `awk` to parse the GRUB configuration file and list all available menu entries and submenus. This output is crucial for identifying the exact string needed to set a specific kernel as the default boot option. ```console $ awk -F\' '/menuentry |submenu / {print $1 $2}' /boot/grub/grub.cfg ``` -------------------------------- ### Install Universal Robots Client Library in ROS/ROS 2 via apt Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/installation.rst Command to install the ur_client_library binary package using apt for ROS distributions. This is the recommended method for users not contributing to the library. ```console $ sudo apt install ros-$ROS_DISTRO-ur-client-library ``` -------------------------------- ### Create Local Directories for URSim External Control Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst These commands create local directories on the host machine to store URSim programs and URCaps. These folders will be bind-mounted into the Docker container to persist changes and install custom components like the external_control URCap. ```bash mkdir -p ${HOME}/.ursim/programs mkdir -p ${HOME}/.ursim/urcaps ``` -------------------------------- ### Download External Control URCap JAR File Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command downloads the specified version of the external_control URCap JAR file from GitHub. The downloaded file is placed into the previously created local URCaps directory, making it available for installation within the URSim Docker container. ```bash URCAP_VERSION=1.0.5 # latest version as if writing this curl -L -o ${HOME}/.ursim/urcaps/externalcontrol-${URCAP_VERSION}.jar \ https://github.com/UniversalRobots/Universal_Robots_ExternalControl_URCap/releases/download/v${URCAP_VERSION}/externalcontrol-${URCAP_VERSION}.jar ``` -------------------------------- ### Start URSim Docker with Static IP on Custom Network Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command starts the URSim Docker container, attaching it to the previously created "ursim_net" and assigning it a static IP address (192.168.56.101). Using a static IP can simplify access to the simulated robot, especially when skipping port exposure. ```bash docker run --rm -it -p 5900:5900 -p 6080:6080 --net ursim_net --ip 192.168.56.101 universalrobots/ursim_e-series ``` -------------------------------- ### Initialize Robot Driver for Force Mode Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/force_mode.rst This snippet demonstrates how to create and initialize an `ExampleRobotWrapper` object, which sets up the UR driver and dashboard client for communication with the Universal Robots arm. This is a prerequisite for utilizing force mode. ```c++ bool headless_mode = true; std::string robot_ip = "192.168.56.101"; // Replace with your robot's IP std::string script_path = ""; // Path to the external script if used std::string log_level = "INFO"; // Create and initialize the robot driver auto robot_wrapper = std::make_unique( robot_ip, script_path, headless_mode, log_level); if (!robot_wrapper->initialize()) { URCL_LOG_ERROR("Could not initialize robot wrapper"); return 1; } // End of initialization ``` -------------------------------- ### Verify GPG Signature of RT Patch (Initial Attempt) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Demonstrates an initial attempt to verify the GPG signature of a real-time kernel patch, which typically fails due to a missing public key. This step highlights the necessity of importing the key first. ```console $ gpg2 --verify patch-$KERNEL_VERSION-rt$RT_PATCH_VERSION.patch.sign gpg: assuming signed data in 'patch-5.15.158-rt76.patch' gpg: Signature made Fri May 3 17:12:45 2024 UTC gpg: using RSA key AD85102A6BE1CDFE9BCA84F36CEF3D27CA5B141E gpg: Can't check signature: No public key ``` -------------------------------- ### Start Force Mode on Universal Robots Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/force_mode.rst This code shows how to initiate force mode on the robot by calling the `startForceMode()` function. Parameters for force mode are passed directly to this function, and it can be called again to change active parameters. Note that CB3 robots have different function signatures. ```c++ // Start force mode std::vector task_frame = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Example task frame std::vector selection_vector = {1, 1, 1, 0, 0, 0}; // Example selection vector (x, y, z forces) std::vector wrench = {10.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Example wrench (10N in x) int type = 2; // Example type (e.g., FRAME) std::vector limits = {0.05, 0.05, 0.05, 0.05, 0.05, 0.05}; // Example limits double gain_scaling = 0.1; // Example gain scaling bool success = robot_wrapper->startForceMode(task_frame, selection_vector, wrench, type, limits, gain_scaling); if (!success) ``` -------------------------------- ### Setting up the Consumer for Primary Interface Data Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/primary_pipeline.rst This snippet shows how to configure the consumer component, which processes data produced by the producer. It uses a ShellExecutor that will try to print each package's content to the shell output, illustrating how to handle incoming data. ```c++ // The shell consumer auto consumer = std::make_unique(); ``` -------------------------------- ### Select Fully Preemptible Kernel Preemption Model Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Illustrates the interactive selection of the 'Fully Preemptible Kernel (Real-Time)' option during kernel configuration. This setting is crucial for achieving real-time performance. ```console Preemption Model 1. No Forced Preemption (Server) (PREEMPT_NONE) > 2. Voluntary Kernel Preemption (Desktop) (PREEMPT_VOLUNTARY) 3. Preemptible Kernel (Low-Latency Desktop) (PREEMPT) 4. Fully Preemptible Kernel (Real-Time) (PREEMPT_RT) (NEW) choice[1-4?]: 4 ``` -------------------------------- ### Import GPG Public Key for RT Patch Verification Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Imports the necessary GPG public key from a keyserver to enable successful verification of the real-time kernel patch signature. This key is crucial for authenticating the patch source. ```console gpg2 --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys AD85102A6BE1CDFE9BCA84F36CEF3D27CA5B141E ``` -------------------------------- ### Verify GPG Signature of Linux Kernel Source Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Verifies the GPG signature of the main Linux kernel source tarball after importing the necessary public key. This step ensures the integrity and authenticity of the downloaded kernel source. ```console $ gpg2 --verify linux-$KERNEL_VERSION.tar.sign gpg: assuming signed data in 'linux-5.15.158.tar' gpg: Signature made Thu May 2 14:28:07 2024 UTC gpg: using RSA key 647F28654894E3BD457199BE38DBBDC86092693E gpg: Good signature from "Greg Kroah-Hartman " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: 647F 2865 4894 E3BD 4571 99BE 38DB BDC8 6092 693E ``` -------------------------------- ### Configure UR Robot Network Settings Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/network_setup.rst Instructions for setting static IP addresses on the UR robot's teach pendant. This configuration establishes a direct network connection and helps minimize latency for communication. ```text IP address: 192.168.56.101 Subnet mask: 255.255.255.0 Default gateway: 192.168.56.1 Preferred DNS server: 192.168.56.1 Alternative DNS server: 0.0.0.0 ``` -------------------------------- ### Create and Navigate to Kernel Build Directory Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst These commands create a new temporary directory for building the real-time kernel and then change the current working directory into it. This ensures all subsequent build commands are executed in the correct, isolated location, preventing conflicts with other system files. ```console $ mkdir -p ${HOME}/rt_kernel_build $ cd ${HOME}/rt_kernel_build ``` -------------------------------- ### Read Data from RTDE Client (C++) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/rtde_client.rst After initializing the RTDE client, communication must be started. This snippet shows a loop that continuously reads data packages from the client using getDataPackage(). Reading data is crucial to prevent the internal pipeline queue from overflowing. ```c++ // Once RTDE communication is started my_client.startCommunication(); while (true) { urcl::rtde_client::RTDEPackage data_package = my_client.getDataPackage(); if (data_package) { // Process data_package, e.g., print joint positions std::cout << "Joint Q: " << data_package->get>("joint_q") << std::endl; } // Simulate some delay or condition to break loop if (some_condition_to_stop) { break; } } ``` -------------------------------- ### Create Real-Time User Group and Add Current User Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Creates a new system group named 'realtime' and adds the current user to this group. This prepares the system for configuring real-time scheduling privileges for a dedicated user group. ```console $ sudo groupadd realtime $ sudo usermod -aG realtime $(whoami) ``` -------------------------------- ### Initialize DashboardClient and send commands (C++) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/architecture/dashboard_client.rst Demonstrates how to initialize a `DashboardClient` object, connect to the dashboard server, send a command using `sendAndReceive()`, and use a blocking `commandCloseSafetyPopup()` function. This example shows basic interaction with the UR robot's dashboard. ```c++ std::make_unique my_dashboard = std::make_unique("192.168.1.1", 29999); try { my_dashboard->connect(); std::string response = my_dashboard->sendAndReceive("play"); // Further processing of response my_dashboard->commandCloseSafetyPopup(); } catch (const UrException& e) { // Handle exception std::cerr << "UrException: " << e.what() << std::endl; } ``` -------------------------------- ### Keeping the Primary Interface Pipeline Active Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/primary_pipeline.rst This snippet demonstrates how to keep the example program running for a duration to allow the pipeline to process incoming data from the robot. It uses a simple loop to prevent the program from exiting immediately, ensuring data can be observed. ```c++ do { std::this_thread::sleep_for(std::chrono::seconds(1)); } while (true); // Simplified for example, original might have a condition or timeout return 0; ``` -------------------------------- ### Verify GPG Signature of RT Patch (Successful) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Successfully verifies the GPG signature of the real-time kernel patch after the public key has been imported. This confirms the authenticity and integrity of the patch file. ```console $ gpg2 --verify patch-$KERNEL_VERSION-rt$RT_PATCH_VERSION.patch.sign gpg: assuming signed data in 'patch-5.15.158-rt76.patch' gpg: Signature made Fri May 3 17:12:45 2024 UTC gpg: using RSA key AD85102A6BE1CDFE9BCA84F36CEF3D27CA5B141E gpg: Good signature from "Joseph Salisbury " [unknown] gpg: aka "Joseph Salisbury " [unknown] gpg: aka "Joseph Salisbury " [unknown] gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. Primary key fingerprint: AD85 102A 6BE1 CDFE 9BCA 84F3 6CEF 3D27 CA5B 141E ``` -------------------------------- ### Configure Linux Kernel with oldconfig Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Initiates the kernel configuration process using `make oldconfig`, which prompts the user for various kernel options. This command is used to adapt the kernel to specific hardware and desired features. ```console $ make oldconfig ``` -------------------------------- ### Execute a Sequence of Motion Primitives on UR Robot Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/instruction_executor.rst This example shows how to execute a predefined sequence of motion primitives on the UR robot. It involves creating an `std::vector` of `urcl::cointrol::MotionPrimitive` objects, each representing a different motion type (e.g., `MoveJ`, `MoveL`, `MoveP`). The sequence is then passed to the `executeMotion` function. Parameters for each primitive are forwarded to the underlying URScript functions, with time-based execution having priority over acceleration/velocity. ```c++ // Trajectory definition std::vector> motion_sequence; motion_sequence.push_back(std::make_shared(urcl::kinematics::Joints({-0.5, -1.5, 1.5, -1.5, -1.5, 0.0}), 0.5, 0.5, 0.0, 0.0, 0.0)); motion_sequence.push_back(std::make_shared(urcl::kinematics::Joints({0.5, -1.5, 1.5, -1.5, -1.5, 0.0}), 0.5, 0.5, 0.0, 0.0, 0.0)); motion_sequence.push_back(std::make_shared(urcl::kinematics::Pose({0.4, -0.4, 0.4, 0.0, 3.14, 0.0}), 0.5, 0.5, 0.0, 0.0, 0.0)); motion_sequence.push_back(std::make_shared(urcl::kinematics::Pose({0.4, -0.4, 0.6, 0.0, 3.14, 0.0}), 0.5, 0.5, 0.0, 0.0, 0.0)); instruction_executor->executeMotion(motion_sequence); ``` -------------------------------- ### Configure Remote PC Network Settings Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/network_setup.rst Steps to set up a new wired connection on the remote PC with a static IPv4 address. This ensures the PC is in the same subnet as the UR robot for direct communication. ```text IPv4 Manual Address: 192.168.56.1 Netmask: 255.255.255.0 ``` -------------------------------- ### Create Custom Docker Network for URSim Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command creates a new Docker network named "ursim_net" with a specified subnet. This custom network allows for assigning static IP addresses to containers, providing a more explicit and stable network setup for the simulated robot. ```bash docker network create --subnet=192.168.56.0/24 ursim_net ``` -------------------------------- ### Extract Kernel Source and Apply RT Patch Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Extracts the Linux kernel source tarball and then applies the real-time patch to the extracted source directory. This prepares the kernel source for compilation with real-time capabilities. ```console $ tar xf linux-$KERNEL_VERSION.tar $ cd linux-$KERNEL_VERSION $ xzcat ../patch-$KERNEL_VERSION-rt$RT_PATCH_VERSION.patch.xz | patch -p1 ``` -------------------------------- ### Download Linux Kernel Sources and RT Patch Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst These commands download the compressed Linux kernel source archive, the real-time patch file, and their corresponding signature files from kernel.org. These files are fundamental components required for applying the real-time patch and compiling a PREEMPT_RT kernel. ```console $ wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/$KERNEL_MAJOR_VERSION.$KERNEL_MINOR_VERSION/patch-$KERNEL_VERSION-rt$RT_PATCH_VERSION.patch.xz $ wget https://cdn.kernel.org/pub/linux/kernel/projects/rt/$KERNEL_MAJOR_VERSION.$KERNEL_MINOR_VERSION/patch-$KERNEL_VERSION-rt$RT_PATCH_VERSION.patch.sign $ wget https://www.kernel.org/pub/linux/kernel/v$KERNEL_MAJOR_VERSION.x/linux-$KERNEL_VERSION.tar.xz $ wget https://www.kernel.org/pub/linux/kernel/v$KERNEL_MAJOR_VERSION.x/linux-$KERNEL_VERSION.tar.sign ``` -------------------------------- ### Initialize InstructionExecutor for UR Robot Communication Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/instruction_executor.rst This snippet demonstrates the creation of an `InstructionExecutor` object, which is essential for communicating with the UR robot. It requires an established connection to the `reverse_interface` and the robot to be in `remote_control` mode. The `URDriver` object is passed for communication. ```c++ bool headless_mode = true; // If the robot is in remote_control mode, the example will automatically start the reverse_interface // program on the robot. auto instruction_executor = std::make_shared(g_my_robot->getUrDriver()); ``` -------------------------------- ### Verify Kernel Real-time Preemption Capabilities Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This command checks if the currently running kernel supports real-time scheduling by examining its version string for the `PREEMPT_RT` flag. This step confirms that the system has successfully booted into a real-time kernel, which is essential for real-time applications. ```console $ uname -v | cut -d" " -f1-4 ``` -------------------------------- ### Create Custom Log Handler in C++ for UR Client Library Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/README.md This C++ example illustrates how to implement a custom log handler by inheriting from `urcl::LogHandler`. This allows developers to override the default logging behavior, such as redirecting log messages to a file, a custom console, or a different logging framework. The example demonstrates printing messages to `std::cout` with custom prefixes based on log level. ```C++ #include "ur_client_library/log.h" #include class MyLogHandler : public urcl::LogHandler { public: MyLogHandler() = default; void log(const char* file, int line, urcl::LogLevel loglevel, const char* log) override { switch (loglevel) { case urcl::LogLevel::INFO: std::cout << "INFO " << file << " " << line << ": " << log << std::endl; break; case urcl::LogLevel::DEBUG: std::cout << "DEBUG " << file << " " << line << ": " << log << std::endl; break; case urcl::LogLevel::WARN: std::cout << "WARN " << file << " " << line << ": " << log << std::endl; break; case urcl::LogLevel::ERROR: std::cout << "ERROR " << file << " " << line << ": " << log << std::endl; break; case urcl::LogLevel::FATAL: std::cout << "ERROR " << file << " " << line << ": " << log << std::endl; break; default: break; } } }; int main(int argc, char* argv[]) { urcl::setLogLevel(urcl::LogLevel::DEBUG); std::unique_ptr log_handler(new MyLogHandler); urcl::registerLogHandler(std::move(log_handler)); URCL_LOG_DEBUG("logging debug message"); URCL_LOG_INFO("logging info message"); return 0; } ``` -------------------------------- ### Execute MoveJ Trajectory with Universal Robots in C++ Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/trajectory_point_interface.rst This example demonstrates how to define and execute a 2-point trajectory using the `movej` function, which interpolates in joint space. It also shows how to maintain an active connection to the robot during trajectory execution by sending NOOP messages. ```c++ // Define a 2-point trajectory for movej urcl::control::TrajectoryPoint p1_movej; p1_movej.joint_positions = {0.0, -M_PI_2, 0.0, -M_PI_2, 0.0, 0.0}; p1_movej.duration = 5.0; // seconds g_my_robot->getUrDriver()->writeTrajectoryPoint(p1_movej); urcl::control::TrajectoryPoint p2_movej; p2_movej.joint_positions = {M_PI_4, -M_PI_4, M_PI_4, -M_PI_4, M_PI_4, M_PI_4}; p2_movej.max_velocity = 0.5; // rad/s p2_movej.max_acceleration = 1.0; // rad/s^2 g_my_robot->getUrDriver()->writeTrajectoryPoint(p2_movej); // Keep connection active while trajectory is running g_my_robot->getUrDriver()->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP); ``` -------------------------------- ### Write Data to RTDE Client (C++) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/rtde_client.rst This example illustrates how to send data to the RTDE client, specifically oscillating the speed slider. It uses the RTDEWriter object, accessible via my_client.getWriter(), which provides methods for sending various data types. The input recipe must contain the necessary keys for the data being sent. ```c++ my_client.getWriter().sendSpeedSlider(speed_slider_value); if (increasing) { speed_slider_value += 0.01; if (speed_slider_value >= 1.0) { increasing = false; } } else { speed_slider_value -= 0.01; if (speed_slider_value <= 0.0) { increasing = true; } } std::this_thread::sleep_for(std::chrono::milliseconds(50)); if (some_other_condition_to_stop) { break; } } ``` -------------------------------- ### Initialize RTDE Client (C++) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/rtde_client.rst This code demonstrates how to create and initialize an RTDE client instance. It requires the robot's IP address, an INotifier object, and the previously defined output and input recipes. An optional communication frequency can also be specified. ```c++ comm::INotifier notifier; std::string robot_ip = "192.168.1.100"; urcl::rtde_client::RTDEClient my_client(robot_ip, notifier, OUTPUT_RECIPE, INPUT_RECIPE); my_client.init(); ``` -------------------------------- ### Initialize UrDriver Object in C++ Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/trajectory_point_interface.rst This snippet demonstrates how to create a `UrDriver` object, which is essential for interacting with Universal Robots. It sets up the basic connection parameters for the robot. ```c++ bool headless_mode = true; // --------------- INITIALIZATION START ------------------- urcl::UrDriver driver("192.168.1.100", "robot", "password", headless_mode); g_my_robot = std::make_unique("192.168.1.100", "robot", "password", headless_mode); ``` -------------------------------- ### Decompress Linux Kernel and RT Patch Archives Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst These commands decompress the downloaded `.xz` archives for the real-time patch and the Linux kernel sources. Decompression is a necessary step before the patch can be applied and the kernel compilation process can begin. ```console $ xz -dk patch-$KERNEL_VERSION-rt$RT_PATCH_VERSION.patch.xz $ xz -d linux-$KERNEL_VERSION.tar.xz ``` -------------------------------- ### Launch UR Robot Driver with ROS 1 Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command launches the ur_robot_driver for ROS 1, connecting to the simulated UR5e robot running in Docker. It specifies the robot's IP address, allowing the ROS system to communicate with the URSim instance. ```bash roslaunch ur_robot_driver ur5e_bringup.launch robot_ip:=192.168.56.101 ``` -------------------------------- ### Define RTDE Input and Output Recipes (C++) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/rtde_client.rst This snippet defines the constant strings for output and input recipes, which are lists of keys used to initialize the RTDE client for streaming data from and to the robot. These recipes are typically read from external text files. ```c++ const std::string OUTPUT_RECIPE = "robot_status,joint_q,actual_q"; const std::string INPUT_RECIPE = "speed_slider_mask,speed_slider_fraction"; ``` -------------------------------- ### Configure Real-Time User Limits in limits.conf Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst Configures `/etc/security/limits.conf` to grant real-time scheduling priority and memory locking capabilities to members of the 'realtime' group. These settings are essential for applications requiring deterministic real-time performance. ```linuxconfig @realtime soft rtprio 99 @realtime soft priority 99 @realtime soft memlock 102400 @realtime hard rtprio 99 @realtime hard priority 99 @realtime hard memlock 102400 ``` -------------------------------- ### Launch UR Robot Driver with ROS 2 Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/setup/ursim_docker.rst This command launches the UR robot driver using ROS 2, specifying the robot type (e.g., `ur5e`) and the IP address of the URSim instance. It connects the ROS 2 control stack to the simulated robot, enabling control and interaction. ```bash ros2 launch ur_robot_driver ur_control.launch.py ur_type:=ur5e robot_ip:=192.168.56.101 ``` -------------------------------- ### Initialize and Read Data with RTDEClient (C++) Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/architecture/rtde_client.rst This C++ snippet demonstrates how to initialize and start an RTDEClient instance, then continuously read data packages from the RTDE interface. It highlights the importance of frequent calls to `getDataPackage()` to prevent buffer overflow, as the client's internal queue has a restricted size. ```c++ rtde_interface::RTDEClient my_client(ROBOT_IP, notifier, OUTPUT_RECIPE, INPUT_RECIPE); my_client.init(); my_client.start(); while (true) { std::unique_ptr data_pkg = my_client.getDataPackage(READ_TIMEOUT); if (data_pkg) { std::cout << data_pkg->toString() << std::endl; } } ``` -------------------------------- ### Assemble Primary Pipeline with CalibrationConsumer in C++ Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/primary_pipeline_calibration.rst This C++ snippet demonstrates how to assemble the primary pipeline for Universal Robots, replacing the default ShellConsumer with the custom CalibrationConsumer. It initializes the pipeline with a PrimaryProducer connected to the robot's IP and the specialized consumer, then runs the pipeline in a separate thread for background data processing. ```c++ // The calibration consumer CalibrationConsumer calib_consumer; // The pipeline urcl::PrimaryPipeline calib_pipeline( std::make_unique(robot_ip), std::make_unique(calib_consumer) // Pass the consumer ); // Run the pipeline in a separate thread std::thread pipeline_thread([&calib_pipeline]() { calib_pipeline.run(); }); ``` -------------------------------- ### Execute Single Motion (MoveJ/MoveL) on UR Robot Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/examples/instruction_executor.rst This snippet demonstrates how to execute a single motion command, such as `moveJ` or `moveL`, using the `InstructionExecutor`. The `InstructionExecutor` provides direct methods for these common motion types. Similar to sequence execution, time parametrization takes precedence over acceleration/velocity parameters. ```c++ double goal_time_sec = 2.0; instruction_executor->moveJ(urcl::kinematics::Joints({-0.5, -1.5, 1.5, -1.5, -1.5, 0.0}), goal_time_sec); instruction_executor->moveL(urcl::kinematics::Pose({0.4, -0.4, 0.4, 0.0, 3.14, 0.0}), goal_time_sec); ``` -------------------------------- ### Check Current Linux Kernel Version Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst This command displays the version string of the currently running Linux kernel. Knowing the current kernel version is crucial for selecting a compatible real-time patch version when building a PREEMPT_RT kernel. ```console $ uname -r ``` -------------------------------- ### Set Environment Variables for RT Kernel Version Source: https://github.com/universalrobots/universal_robots_client_library/blob/master/doc/real_time.rst These commands export environment variables defining the major, minor, patch, and RT patch versions of the chosen kernel. These variables standardize the version information, making subsequent commands for downloading and patching the kernel sources more robust and less error-prone. ```console $ export KERNEL_MAJOR_VERSION=5 $ export KERNEL_MINOR_VERSION=15 $ export KERNEL_PATCH_VERSION=158 $ export RT_PATCH_VERSION=76 $ export KERNEL_VERSION="$KERNEL_MAJOR_VERSION.$KERNEL_MINOR_VERSION.$KERNEL_PATCH_VERSION" ```