From 1fd356e9e170f30329af43f1cd5d5474e5784b7f Mon Sep 17 00:00:00 2001 From: Ali Date: Wed, 28 May 2025 06:05:17 +0200 Subject: [PATCH 01/22] [AN] (feat) fix docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f3e032c..08ec79b 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ This command builds the container defined in [`URSim/Dockerfile`](./URSim/Docker The same can be done for the ROS 2_Humble container ```bash -docker build -t ros2_humble:latest ROS2_Humble +docker build -t ros2_humble:latest ROS2_humble ``` After all the containers are successfully built and the bridge network is established we can now start both containers. On one terminal run the following command to start the URSim container From 5bf594ccea103d5015dbb7e58fed59d2857a9f9d Mon Sep 17 00:00:00 2001 From: Ali Date: Wed, 28 May 2025 06:18:43 +0200 Subject: [PATCH 02/22] [AN] (fix) relax requirements version --- README.md | 2 +- ROS2_humble/Dockerfile | 2 +- workspace/build/.built_by | 1 + workspace/build/COLCON_IGNORE | 0 .../osc_ros2/build/lib/osc_ros2/__init__.py | 0 .../osc_ros2/build/lib/osc_ros2/osc_ros2.py | 1099 +++++++++++++++++ workspace/build/osc_ros2/colcon_build.rc | 1 + .../colcon_command_prefix_setup_py.sh | 1 + .../colcon_command_prefix_setup_py.sh.env | 20 + workspace/build/osc_ros2/install.log | 14 + .../build/osc_ros2/osc_ros2.egg-info/PKG-INFO | 12 + .../osc_ros2/osc_ros2.egg-info/SOURCES.txt | 16 + .../osc_ros2.egg-info/dependency_links.txt | 1 + .../osc_ros2.egg-info/entry_points.txt | 3 + .../osc_ros2/osc_ros2.egg-info/requires.txt | 6 + .../osc_ros2/osc_ros2.egg-info/top_level.txt | 1 + .../build/osc_ros2/osc_ros2.egg-info/zip-safe | 1 + .../__pycache__/sitecustomize.cpython-310.pyc | Bin 0 -> 277 bytes .../osc_ros2/prefix_override/sitecustomize.py | 4 + workspace/install/.colcon_install_layout | 1 + workspace/install/COLCON_IGNORE | 0 workspace/install/_local_setup_util_ps1.py | 407 ++++++ workspace/install/_local_setup_util_sh.py | 407 ++++++ workspace/install/local_setup.bash | 121 ++ workspace/install/local_setup.ps1 | 55 + workspace/install/local_setup.sh | 137 ++ workspace/install/local_setup.zsh | 134 ++ .../install/osc_ros2/lib/osc_ros2/interface | 33 + .../osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO | 12 + .../SOURCES.txt | 16 + .../dependency_links.txt | 1 + .../entry_points.txt | 3 + .../requires.txt | 6 + .../top_level.txt | 1 + .../osc_ros2-1.0.0-py3.10.egg-info/zip-safe | 1 + .../site-packages/osc_ros2/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 170 bytes .../__pycache__/osc_ros2.cpython-310.pyc | Bin 0 -> 34258 bytes .../site-packages/osc_ros2/osc_ros2.py | 1099 +++++++++++++++++ .../resource_index/packages/osc_ros2 | 0 .../share/colcon-core/packages/osc_ros2 | 1 + .../share/osc_ros2/hook/ament_prefix_path.dsv | 1 + .../share/osc_ros2/hook/ament_prefix_path.ps1 | 3 + .../share/osc_ros2/hook/ament_prefix_path.sh | 3 + .../share/osc_ros2/hook/pythonpath.dsv | 1 + .../share/osc_ros2/hook/pythonpath.ps1 | 3 + .../share/osc_ros2/hook/pythonpath.sh | 3 + .../osc_ros2/share/osc_ros2/package.bash | 31 + .../osc_ros2/share/osc_ros2/package.dsv | 6 + .../osc_ros2/share/osc_ros2/package.ps1 | 116 ++ .../osc_ros2/share/osc_ros2/package.sh | 87 ++ .../osc_ros2/share/osc_ros2/package.xml | 20 + .../osc_ros2/share/osc_ros2/package.zsh | 42 + workspace/install/setup.bash | 31 + workspace/install/setup.ps1 | 29 + workspace/install/setup.sh | 45 + workspace/install/setup.zsh | 31 + workspace/log/COLCON_IGNORE | 0 .../log/build_2025-05-28_04-13-20/events.log | 46 + .../build_2025-05-28_04-13-20/logger_all.log | 126 ++ .../osc_ros2/command.log | 2 + .../osc_ros2/stderr.log | 0 .../osc_ros2/stdout.log | 35 + .../osc_ros2/stdout_stderr.log | 35 + .../osc_ros2/streams.log | 37 + .../log/build_2025-05-28_04-16-52/events.log | 30 + .../build_2025-05-28_04-16-52/logger_all.log | 126 ++ .../osc_ros2/command.log | 2 + .../osc_ros2/stderr.log | 0 .../osc_ros2/stdout.log | 19 + .../osc_ros2/stdout_stderr.log | 19 + .../osc_ros2/streams.log | 21 + workspace/log/latest | 1 + workspace/log/latest_build | 1 + workspace/src/osc_ros2/setup.py | 4 +- 75 files changed, 4571 insertions(+), 4 deletions(-) create mode 100644 workspace/build/.built_by create mode 100644 workspace/build/COLCON_IGNORE create mode 100644 workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py create mode 100644 workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py create mode 100644 workspace/build/osc_ros2/colcon_build.rc create mode 100644 workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh create mode 100644 workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env create mode 100644 workspace/build/osc_ros2/install.log create mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO create mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt create mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt create mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt create mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt create mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt create mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe create mode 100644 workspace/build/osc_ros2/prefix_override/__pycache__/sitecustomize.cpython-310.pyc create mode 100644 workspace/build/osc_ros2/prefix_override/sitecustomize.py create mode 100644 workspace/install/.colcon_install_layout create mode 100644 workspace/install/COLCON_IGNORE create mode 100644 workspace/install/_local_setup_util_ps1.py create mode 100644 workspace/install/_local_setup_util_sh.py create mode 100644 workspace/install/local_setup.bash create mode 100644 workspace/install/local_setup.ps1 create mode 100644 workspace/install/local_setup.sh create mode 100644 workspace/install/local_setup.zsh create mode 100755 workspace/install/osc_ros2/lib/osc_ros2/interface create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/osc_ros2.cpython-310.pyc create mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py create mode 100644 workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 create mode 100644 workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 create mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv create mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 create mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh create mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv create mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 create mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh create mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.bash create mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.dsv create mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.ps1 create mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.sh create mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.xml create mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.zsh create mode 100644 workspace/install/setup.bash create mode 100644 workspace/install/setup.ps1 create mode 100644 workspace/install/setup.sh create mode 100644 workspace/install/setup.zsh create mode 100644 workspace/log/COLCON_IGNORE create mode 100644 workspace/log/build_2025-05-28_04-13-20/events.log create mode 100644 workspace/log/build_2025-05-28_04-13-20/logger_all.log create mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log create mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/stderr.log create mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log create mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log create mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log create mode 100644 workspace/log/build_2025-05-28_04-16-52/events.log create mode 100644 workspace/log/build_2025-05-28_04-16-52/logger_all.log create mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log create mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/stderr.log create mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log create mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log create mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log create mode 120000 workspace/log/latest create mode 120000 workspace/log/latest_build diff --git a/README.md b/README.md index 08ec79b..d06a379 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ docker build -t ros2_humble:latest ROS2_humble After all the containers are successfully built and the bridge network is established we can now start both containers. On one terminal run the following command to start the URSim container ```bash -docker run -it --name URSIM -p 6080:6080 -p50002:50002 --network ros_ursim ursim:latest +docker run -it --name URSIM -p 6080:6080 -p8000:8000 -p7000:7000 -p5005:5005 -p50002:50002 -v./workspace:/workspace --network ros_ursim ursim:latest ``` When successfully started this container will print its IP address in the terminal. Note this down: diff --git a/ROS2_humble/Dockerfile b/ROS2_humble/Dockerfile index dcc08ea..296c693 100644 --- a/ROS2_humble/Dockerfile +++ b/ROS2_humble/Dockerfile @@ -3,4 +3,4 @@ FROM osrf/ros:humble-desktop-full RUN apt-get -y update RUN apt-get -y upgrade RUN apt-get -y install ros-humble-ur ros-humble-ros2controlcli nmap neovim tmux git nano iproute2 inetutils-ping python3-pip -RUN pip install numpy scipy spatialmath-python roboticstoolbox-python osc4py3 +RUN pip install numpy==1.22.4 scipy==1.7.3 spatialmath-python roboticstoolbox-python osc4py3 diff --git a/workspace/build/.built_by b/workspace/build/.built_by new file mode 100644 index 0000000..06e74ac --- /dev/null +++ b/workspace/build/.built_by @@ -0,0 +1 @@ +colcon diff --git a/workspace/build/COLCON_IGNORE b/workspace/build/COLCON_IGNORE new file mode 100644 index 0000000..e69de29 diff --git a/workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py b/workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py b/workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py new file mode 100644 index 0000000..0b28d5b --- /dev/null +++ b/workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py @@ -0,0 +1,1099 @@ +import rclpy +from rclpy.node import Node +from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint +from sensor_msgs.msg import JointState +from rcl_interfaces.msg import Log +from osc4py3.as_allthreads import * +from osc4py3 import oscmethod as osm +import xml.etree.ElementTree as ET +import numpy as np +import spatialmath as sm +import roboticstoolbox as rtb +from osc4py3 import oscbuildparse +import time +import os +import re +import socket + +class JointNameListener(Node): + def __init__(self): + super().__init__('joint_name_listener') + self.subscription = self.create_subscription( + JointState, + '/joint_states', + self.joint_state_callback, + 1 + ) + self.joint_names = None + + def joint_state_callback(self, msg: JointState): + self.joint_names = list(msg.name) + +class OSC_ROS2_interface(Node): + """Node to publish joint trajectories based on OSC messages.""" + + def __init__(self, joint_names, joint_velocity_limits, robot, cost_mask): + super().__init__('scaled_joint_trajectory_publisher') + + + self.subscription = self.create_subscription( + JointState, + '/joint_states', + self.joint_states_callback, + 1 + ) + + self.subscription = self.create_subscription( + Log, + '/rosout', + self.log_callback, + 100 + ) + + # Store received joint positions + self.current_joint_positions = None + self.joint_names = joint_names + self.joint_velocity_limits = joint_velocity_limits + self.cost_mask = cost_mask + self.robot = robot + self.desired = None + self.previous_desired = None + self.log_dict = { + 10: "DEBUG", + 20: "INFO", + 30: "WARN", + 40: "ERROR", + 50: "FATAL", + } + self.speed_scaling = 0.2 + self.new = False + self.n_joints = len(joint_names) + + if robot: + while True: + print('+-' * 50) + set_limits = input("Do you want to set limits for x, y and z? (y/n): ").strip().lower() + if set_limits == 'y': + while True: + try: + self.x_limits = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for x (space-separated, enter 'x' for no limit): ").split()] + self.y_limits = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for y (space-separated, enter 'x' for no limit): ").split()] + self.z_limits = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for z (space-separated, enter 'x' for no limit): ").split()] + + if len(self.x_limits) != 2 or len(self.y_limits) != 2 or len(self.z_limits) != 2: + print("Invalid input. Please enter exactly two values (or leave blank) for each limit.") + continue + + if (self.x_limits[0] is not None and self.x_limits[1] is not None and self.x_limits[0] >= self.x_limits[1]) or \ + (self.y_limits[0] is not None and self.y_limits[1] is not None and self.y_limits[0] >= self.y_limits[1]) or \ + (self.z_limits[0] is not None and self.z_limits[1] is not None and self.z_limits[0] >= self.z_limits[1]): + print("Invalid input. Lower limit must be less than upper limit for each axis.") + continue + + print(f"Current limits:") + print(f"x: {self.x_limits}") + print(f"y: {self.y_limits}") + print(f"z: {self.z_limits}") + con = True + while con: + confirm = input("Do you want your TCP to move in this range? (y/n): ").strip().lower() + if confirm == 'y': + break + elif confirm == 'n': + print("Please re-enter the limits.") + con = False + else: + print("Invalid input. Please enter 'y' or 'n'.") + if con: break + except ValueError: + print("Invalid input. Please enter numeric values only.") + break + elif set_limits == 'n': + self.x_limits = [None, None] + self.y_limits = [None, None] + self.z_limits = [None, None] + break + print("Invalid input. Please enter 'y' or 'n'.") + + while True: + print('+-' * 50) + set_limits = input("Do you want to set workspace limits in x, y and z direction? (y/n): ").strip().lower() + if set_limits == 'y': + while True: + try: + self.x_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for x (space-separated, enter 'x' for no limit): ").split()] + self.y_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for y (space-separated, enter 'x' for no limit): ").split()] + self.z_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for z (space-separated, enter 'x' for no limit): ").split()] + + if len(self.x_limits_workspace) != 2 or len(self.y_limits_workspace) != 2 or len(self.z_limits_workspace) != 2: + print("Invalid input. Please enter exactly two values (or leave blank) for each limit.") + continue + + if (self.x_limits_workspace[0] is not None and self.x_limits_workspace[1] is not None and self.x_limits_workspace[0] >= self.x_limits_workspace[1]) or \ + (self.y_limits_workspace[0] is not None and self.y_limits_workspace[1] is not None and self.y_limits_workspace[0] >= self.y_limits_workspace[1]) or \ + (self.z_limits_workspace[0] is not None and self.z_limits_workspace[1] is not None and self.z_limits_workspace[0] >= self.z_limits_workspace[1]): + print("Invalid input. Lower limit must be less than upper limit for each axis.") + continue + + print(f"Current limits:") + print(f"x: {self.x_limits_workspace}") + print(f"y: {self.y_limits_workspace}") + print(f"z: {self.z_limits_workspace}") + con = True + while con: + confirm = input("Do you want your robot to move in this range? (y/n): ").strip().lower() + if confirm == 'y': + break + elif confirm == 'n': + print("Please re-enter the limits.") + con = False + else: + print("Invalid input. Please enter 'y' or 'n'.") + if con: break + except ValueError: + print("Invalid input. Please enter numeric values only.") + break + elif set_limits == 'n': + self.x_limits_workspace = [None, None] + self.y_limits_workspace = [None, None] + self.z_limits_workspace = [None, None] + break + print("Invalid input. Please enter 'y' or 'n'.") + # Ask the user if they want to set new joint limits + + # Ask the user if they want to set new joint limits + while True: + print('+-'*50) + update_limits = input("Do you want to set new joint limits? (y/n): ").strip().lower() + if update_limits == 'y': + for i in range(len(self.joint_names)): + while True: + try: + lim = self.robot.qlim.copy() + # Find the link corresponding to the joint name + print("-" * 50) + print(f"Current position limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") + lower_limit = input(f"Enter the new lower limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() + upper_limit = input(f"Enter the new upper limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() + + if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): + print("Invalid input. Lower limit must be less than upper limit.") + continue + lower_limit = float(lower_limit) if lower_limit!="" else None + upper_limit = float(upper_limit) if upper_limit!="" else None + if lower_limit!=None: + if lower_limitlim[1][i]: + while True: + sure = input(f"Are you sure you want to set the upper limit to {upper_limit} rad which is more than the default limit {lim[1][i]} (y/n)?: ").strip().lower() + if sure == 'y': + lim[1][i] = float(upper_limit) + break + elif sure == 'n': + print("Upper limit not changed.") + break + print("Invalid input. Please enter 'y' or 'n'.") + else: lim[1][i] = float(upper_limit) + self.robot.qlim = lim + print(f"New limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") + print("-" * 50) + break + except ValueError: + print("Invalid input. Please enter numeric values or leave blank to keep current limits.") + break + if update_limits == 'n': + break + print("Invalid input. Please enter 'y' or 'n'.") + ''' + use_link_mask = input("Do you want to use a link mask? (y/n): ").strip().lower() + if use_link_mask == 'y': + while True: + try: + ''' + else: + while True: + print('+-' * 50) + update_limits = input("Do you want to set joint limits? (y/n): ").strip().lower() + if update_limits == 'y': + self.joint_lim = [[None]*self.n_joints,[None]*self.n_joints] + for i, joint in enumerate(self.joint_names): + while True: + try: + print("-" * 50) + lower_limit = input(f"Enter the new lower limit for joint '{joint}' (or press Enter for None): ").strip() + upper_limit = input(f"Enter the new upper limit for joint '{joint}' (or press Enter for None): ").strip() + + if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): + print('--' * 50) + print(" !!! Invalid input. Lower limit must be less than upper limit. !!! ") + continue + self.joint_lim[0][i] = float(lower_limit) if lower_limit!="" else None + self.joint_lim[1][i] = float(upper_limit) if upper_limit!="" else None + break + except ValueError: + print("Invalid input. Please enter numeric values or leave blank to keep current limits.") + print(f'New limits for joint:\n lower: {self.joint_lim[0]}\n upper: {self.joint_lim[1]}') + break + elif update_limits == 'n': + self.joint_lim = None + break + print("Invalid input. Please enter 'y' or 'n'.") + + + + while True: + try: + print('+-' * 50) + self.trajectory_topic_name = input("Enter the topic name to which the joint trajectory should be sent (press Enter for default: '/scaled_joint_trajectory_controller/joint_trajectory'): ").strip() + if self.trajectory_topic_name == "": + self.trajectory_topic_name = '/scaled_joint_trajectory_controller/joint_trajectory' + break + elif self.trajectory_topic_name.startswith("/"): + break + else: + print("Invalid topic name. A valid topic name should start with '/'.") + except Exception as e: + print(f"An error occurred: {e}") + + # ROS2 Publisher + self.publisher = self.create_publisher( + JointTrajectory, + self.trajectory_topic_name, + 1 + ) + + while True: + try: + print('+-' * 50) + log_ip = str(input("Enter the target IP on which you want to recieve the log as OSC Messages (or press Enter for default: '127.0.0.1'): ")) + if log_ip == "": + log_ip = "127.0.0.1" + print('--' * 50) + log_port = input("Enter the target port for the log messages (or press Enter for default: 5005): ") + if log_port == "": + log_port = 5005 + else: + log_port = int(log_port) + break + except ValueError: + print("Invalid input. Please enter a valid IP address.") + continue + while True: + try: + print('+-' * 50) + state_ip = str(input("Enter the target IP on which you want to recieve the joint states as OSC Messages (or press Enter for default: '127.0.0.1'): ")) + if state_ip == "": + state_ip = "127.0.0.1" + print('--' * 50) + state_port = input("Enter the target port for the joint state messages (or press Enter for default: 7000): ") + if state_port == "": + state_port = 7000 + else: + state_port = int(state_port) + break + except ValueError: + print("Invalid input. Please enter a valid IP address.") + continue + while True: + try: + print('+-' * 50) + commands_port = input("Enter the port you want to send your commands to (or press Enter for default: 8000): ") + if commands_port == state_port: + print("The commands port must be different from the state port.") + continue + if commands_port == "": + commands_port = 8000 + else: + commands_port = int(commands_port) + break + except ValueError: + print("Invalid input. Please enter a valid port.") + continue + + + osc_startup() + + osc_udp_client(state_ip, state_port, "osc_client") + + osc_udp_client(log_ip, log_port, "osc_log_client") + + osc_udp_server('0.0.0.0', commands_port, "osc_server") + + # Register OSC handler + osc_method("/joint_positions", self.joint_positions_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/joint_position/*", self.joint_position_handler, argscheme=osm.OSCARG_ADDRESS+osm.OSCARG_DATAUNPACK) + osc_method("/tcp_coordinates", self.tcp_coordinates_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/joint_trajectory", self.joint_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/cartesian_trajectory", self.cartesian_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/speed_scaling", self.speed_scaling_handler, argscheme=osm.OSCARG_DATAUNPACK) + print('--' * 50) + while True: + try: + print('+-' * 50) + self.hz = input("Enter the desired refresh frequency (Hz) (or press Enter for default: 100): ") + if self.hz == "": + self.hz = 100 + else: + self.hz = float(self.hz) + break + except ValueError: + print("Invalid input. Please enter a valid number.") + continue + print() + print('=-=' * 50) + print() + print(f'Sending joint states to {state_ip}:{state_port}') + print() + print('=-=' * 50) + print() + print(f'Sending log messages to {log_ip}:{log_port}') + print() + print('=-=' * 50) + print() + print(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') + print() + print('=-=' * 50) + print() + + self.get_logger().info(f"Publishing joint trajectory to {self.trajectory_topic_name}") + self.get_logger().info(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') + self.get_logger().info(f'Sending joint states to {state_ip}:{state_port}') + self.get_logger().info(f'Sending log messages to {log_ip}:{log_port}') + self.create_timer(1/self.hz, self.update_position) # Timer to update the position + self.create_timer(3, self.reset_prev) # reset the previous desired position + + def reset_prev(self): self.previous_desired = None + + def speed_scaling_handler(self, *args): + """Handles incoming OSC messages for speed scaling.""" + try: + if len(args) == 1: + if args[0] < 0: + self.speed_scaling = -float(args[0]) + else: + self.speed_scaling = float(args[0]) + if self.speed_scaling > 1: + self.get_logger().warn(f"speed_scaling_handler: Attention! Speed scaling {self.speed_scaling} is greater than 1!") + self.get_logger().info(f"Speed scaling set to {self.speed_scaling}") + else: + self.get_logger().warn(f"Invalid number of arguments for speed scaling. Expected 1, but got {len(args)}.") + except Exception as e: + self.get_logger().fatal(f"speed_scaling_handler: {e}") + + def joint_trajectory_handler(self, *args): + try: + if len(args[0]) == 6: + points = [[float(j) for j in i] for i in args] + elif len(args[0]) >= 7: + points = [[float(j) for j in i[:6]] for i in args] + self.get_logger().warn(f"joint_trajectory_handler: Duration is not supported for joint trajectory yet. Ignoring duration.") + else: + self.get_logger().warn(f"joint_trajectory_handler: Invalid number of arguments for joint trajectory. Expected {self.n_joints} ([q0, q1, q2, ..., q{self.n_joints}]) or {self.n_joints+1} ([q0, q1, q2, ..., q{self.n_joints}, duration]), but got {len(args[0])}.") + return + + self.desired = ["joint_trajectory"] + points + self.new = True + except Exception as e: + self.get_logger().fatal(f"joint_trajectory_handler: {e}") + + def joint_position_handler(self, address, *args): + """Handles incoming OSC messages for joint positions.""" + try: + joint_name = address.split("/")[-1] + + if joint_name in self.joint_names: + if len(args) == 1: + position = float(args[0]) + index = self.joint_names.index(joint_name) + if self.robot: + if position < self.robot.qlim[0][index]: + position = self.robot.qlim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." + ) + elif position > self.robot.qlim[1][index]: + position = self.robot.qlim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." + ) + else: + if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: + position = self.joint_lim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." + ) + elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: + position = self.joint_lim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." + ) + desired_joint_positions = self.current_joint_positions + desired_joint_positions[index] = position + self.desired = ["joint_positions"] + desired_joint_positions + self.new = True + elif len(args) == 2: + position = float(args[0]) + duration = float(args[1]) + index = self.joint_names.index(joint_name) + if self.robot: + if position < self.robot.qlim[0][index]: + position = self.robot.qlim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." + ) + elif position > self.robot.qlim[1][index]: + position = self.robot.qlim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." + ) + else: + if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: + position = self.joint_lim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." + ) + elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: + position = self.joint_lim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." + ) + desired_joint_positions = self.current_joint_positions + desired_joint_positions[index] = position + self.desired = ["joint_positions"] + desired_joint_positions + [duration] + self.new = True + else: + self.get_logger().warn(f"joint_position_handler: Invalid number of arguments for joint position. Expected 1, but got {len(args)}.") + else: + self.get_logger().warn(f"joint_position_handler: Joint '{joint_name}' not found in the robot model.") + except Exception as e: + self.get_logger().fatal(f"joint_position_handler: {e}") + + + def cartesian_trajectory_handler(self, *args): + """Handles incoming OSC messages for cartesian trajectory.""" + if self.robot: + try: + if len(args[0]) == 6: + points = [[float(j) for j in i] for i in args] + elif len(args[0]) >= 7: + points = [[float(j) for j in i[:6]] for i in args] + self.get_logger().warn(f"cartesian_trajectory_handler: Duration is not supported for cartesian trajectory yet. Ignoring duration.") + else: + self.get_logger().warn(f"cartesian_trajectory_handler: Invalid number of arguments for cartesian trajectory. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args[0])}.") + return + + self.desired = ["cartesian_trajectory"] + points + self.new = True + except Exception as e: + self.get_logger().fatal(f"cartesian_trajectory_handler: {e}") + else: + self.get_logger().warn("cartesian_trajectory_handler: No robot model provided. Cannot handle cartesian trajectory.") + return + + def joint_positions_handler(self, *args): + """Handles incoming OSC messages for joint positions.""" + try: + if len(args) == len(self.joint_names): + desired_joint_positions = [float(i) for i in list(args)] + elif len(args) == len(self.joint_names) + 1: + desired_joint_positions = [float(i) for i in list(args)] + else: + self.get_logger().warn(f"joint_positions_handler: Invalid number of arguments for joint positions. Expected {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]) or {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]), but got {len(args)}.") + return + + # Check if joint positions exceed limits + if self.robot: + for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): # Exclude duration if present + if position < self.robot.qlim[0][i]: + desired_joint_positions[i] = self.robot.qlim[0][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[0][i]}." + ) + elif position > self.robot.qlim[1][i]: + desired_joint_positions[i] = self.robot.qlim[1][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[1][i]}." + ) + else: + if self.joint_lim: + for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): + if self.joint_lim[0][i] is not None: + if position < self.joint_lim[0][i]: + desired_joint_positions[i] = self.joint_lim[0][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[0][i]}." + ) + elif self.joint_lim[1][i] is not None: + if position > self.joint_lim[1][i]: + desired_joint_positions[i] = self.joint_lim[1][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[1][i]}." + ) + + self.desired = ["joint_positions"] + desired_joint_positions + self.new = True + except Exception as e: + self.get_logger().fatal(f"joint_positions_handler: {e}") + return + + def tcp_coordinates_handler(self, *args): + # Ensure the desired joint positions are within the specified limits + if self.robot: + try: + if len(args) == 6: + x, y, z, r, p, yaw = [float(i) for i in list(args)] + duration = None + elif len(args) >= 7: + x, y, z, r, p, yaw, duration, *_ = [float(i) for i in list(args)] + else: + self.get_logger().warn(f"tcp_coordinates_handler: Invalid number of arguments for TCP coordinates. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args)}.") + return + + if self.x_limits[0] is not None: + x = max(self.x_limits[0], x) + if self.x_limits[1] is not None: + x = min(self.x_limits[1], x) + if self.y_limits[0] is not None: + y = max(self.y_limits[0], y) + if self.y_limits[1] is not None: + y = min(self.y_limits[1], y) + if self.z_limits[0] is not None: + z = max(self.z_limits[0], z) + if self.z_limits[1] is not None: + z = min(self.z_limits[1], z) + + if x != args[0] or y != args[1] or z != args[2]: + self.get_logger().warn( + f"tcp_coordinates_handler: Desired joint positions adjusted to fit within limits: " + f"x={x}, y={y}, z={z} (original: x={args[0]}, y={args[1]}, z={args[2]})" + ) + + self.desired = ["tcp_coordinates", x, y, z, r, p, yaw, duration] + self.new = True + except Exception as e: + self.get_logger().fatal(f"tcp_coordinates_handler: {e}") + else: + self.get_logger().warn("tcp_coordinates_handler: No robot model provided. Cannot handle TCP coordinates.") + return + + + def joint_states_callback(self, msg: JointState): + """Callback function to handle incoming joint states.""" + try: + msg_time = oscbuildparse.OSCMessage(f"/time", ',s', [str(time.time())]) + osc_send(msg_time, "osc_client") + if not(self.joint_names): self.joint_names = msg.name + joint_position_dict = dict(zip(msg.name, msg.position)) + self.current_joint_positions = [float(joint_position_dict[name]) for name in self.joint_names] + joint_position_dict = dict(zip(msg.name, msg.velocity)) + self.current_joint_velocities = [float(joint_position_dict[name]) for name in self.joint_names] + + if self.robot: + tcp_position = self.robot.fkine(self.current_joint_positions).t + tcp_orientation = self.robot.fkine(self.current_joint_positions).rpy() + + msg_tcp = oscbuildparse.OSCMessage(f"/tcp_coordinates", ',ffffff', [tcp_position[0], tcp_position[1], tcp_position[2], tcp_orientation[0], tcp_orientation[1], tcp_orientation[2]]) + #msg_x = oscbuildparse.OSCMessage(f"/tcp_coordinates/x", ',f', [tcp_position[0]]) + #msg_y = oscbuildparse.OSCMessage(f"/tcp_coordinates/y", ',f', [tcp_position[1]]) + #msg_z = oscbuildparse.OSCMessage(f"/tcp_coordinates/z", ',f', [tcp_position[2]]) + #msg_roll = oscbuildparse.OSCMessage(f"/tcp_coordinates/roll", ',f', [tcp_orientation[0]]) + #msg_pitch = oscbuildparse.OSCMessage(f"/tcp_coordinates/pitch", ',f', [tcp_orientation[1]]) + #msg_yaw = oscbuildparse.OSCMessage(f"/tcp_coordinates/yaw", ',f', [tcp_orientation[2]]) + #bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_tcp, msg_x, msg_y, msg_z, msg_roll, msg_pitch, msg_yaw]) + #osc_send(bun, "osc_client") + osc_send(msg_tcp, "osc_client") + + msg_position = oscbuildparse.OSCMessage(f"/joint_state/position", f',{"f"*self.n_joints}', [i for i in msg.position]) + msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity", f',{"f"*self.n_joints}', [i for i in msg.velocity]) + msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort", f',{"f"*self.n_joints}', [i for i in msg.effort]) + msg_name = oscbuildparse.OSCMessage(f"/joint_state/name", f',{"s"*self.n_joints}', [i for i in msg.name]) + bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_name, msg_position, msg_velocity, msg_effort]) + osc_send(bun, "osc_client") + + #for i, name in enumerate(msg.name): + # msg_position = oscbuildparse.OSCMessage(f"/joint_state/position/{name}", ',f', [msg.position[i]]) + # msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity/{name}", ',f', [msg.velocity[i]]) + # msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort/{name}", ',f', [msg.effort[i]]) + # bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_position, msg_velocity, msg_effort]) + # osc_send(bun, "osc_client") + + except Exception as e: + self.get_logger().fatal(f"joint_states_callback: {e}") + + def send_joint_positions(self): + self.previous_desired = None + self.new = False + try: + if len(self.desired) == len(self.joint_names) + 2: + desired_joint_positions = [float(i) for i in self.desired[1:-1]] + duration = self.desired[-1] + msg = JointTrajectory() + msg.joint_names = self.joint_names + point = JointTrajectoryPoint() + point.positions = desired_joint_positions + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + self.publisher.publish(msg) + elif len(self.desired) == len(self.joint_names) + 1: + desired_joint_positions = [float(i) for i in self.desired[1:]] + msg = JointTrajectory() + msg.joint_names = self.joint_names + point = JointTrajectoryPoint() + point.positions = desired_joint_positions + duration = 0 + for p1, p2, max_vel in zip(desired_joint_positions, self.current_joint_positions, self.joint_velocity_limits.values()): + duration = max(duration, abs(p1 - p2) / max_vel) + duration = duration + min(2, 0.2*duration) + duration /= self.speed_scaling + if duration == 0: + self.get_logger().warn("send_joint_positions: Duration is 0.") + return + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + self.publisher.publish(msg) + else: + self.get_logger().warn(f"send_joint_positions: Invalid number of arguments for joint positions. Expected {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]) or {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]), but got {len(self.desired)}.") + return + except Exception as e: + self.get_logger().fatal(f"send_joint_positions: {e}") + return + + def trapezoidal_timestamps(self, num_points,total_duration, flat_ratio = 0.3): + + if num_points == 2: + return [0, total_duration] + n = int(num_points*(1-flat_ratio)/2) + start = np.cos(np.linspace(0, np.pi, n))+2 + end = np.cos(np.linspace(-np.pi, 0, n))+2 + flat = np.ones(num_points-2*n) + + timestamps = np.concatenate((start, flat, end)) + timestamps *= total_duration / timestamps.sum() + timestamps = np.cumsum(timestamps) + + return timestamps.tolist() + + + def send_tcp_coordinates(self): + """Send the desired TCP coordinates to the robot.""" + try: + self.new = False + msg = JointTrajectory() + msg.joint_names = self.joint_names + steps_per_m = 100 + if self.previous_desired == None: + [x,y,z] = self.robot.fkine(self.current_joint_positions).t + [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() + else: + [x,y,z] = self.previous_desired[1:4] + [roll, pitch, yaw] = self.previous_desired[4:-1] + x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] + self.previous_desired = self.desired + steps = int(np.linalg.norm(np.array([x1, y1, z1])- self.robot.fkine(self.current_joint_positions).t) * steps_per_m) + if steps < 2: steps = 2 + cart_traj = [sm.SE3([x+(x1-x)/(steps-1)*i, y+(y1-y)/(steps-1)*i, z+(z1-z)/(steps-1)*i]) * sm.SE3.RPY([roll+(roll1-roll)/(steps-1)*i, pitch+(pitch1-pitch)/(steps-1)*i, yaw+(yaw1-yaw)/(steps-1)*i]) for i in range(steps)] + '''if self.previous_desired: + [x,y,z] = self.previous_desired[1:4] + q0 = sm.UnitQuaternion.RPY(self.previous_desired[3], self.previous_desired[4], self.previous_desired[5]) + else: + [x, y, z] = self.robot.fkine(self.current_joint_positions).t + q0 = sm.UnitQuaternion(self.robot.fkine(self.current_joint_positions).R) + + x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] + q1 = sm.UnitQuaternion.RPY(roll1, pitch1, yaw1) + + steps = int(np.linalg.norm(np.array([x1, y1, z1]) - self.robot.fkine(self.current_joint_positions).t) * steps_per_m) + if steps < 2: + steps = 2 + + cart_traj = [] + for i in range(steps): + alpha = i / (steps - 1) + + # Convert to arrays for robust interpolation if needed + q0_array = q0.vec + q1_array = q1.vec + dot = np.dot(q0_array, q1_array) + dot = np.clip(dot, -1.0, 1.0) + + if abs(dot) > 0.9995: + # Linear interpolation + normalization + q_interp_array = (1 - alpha) * q0_array + alpha * q1_array + q_interp_array = q_interp_array / np.linalg.norm(q_interp_array) + q_interp = sm.UnitQuaternion(q_interp_array) + else: + q_interp = q0.interp(q1, alpha) + + # Interpolate translation + pos_interp = [ + x + (x1 - x) * alpha, + y + (y1 - y) * alpha, + z + (z1 - z) * alpha + ] + + # Compose SE3 transform + cart_traj.append(sm.SE3(pos_interp) * q_interp.SE3())''' + + + + if self.desired[-1]: + timestamps = self.trapezoidal_timestamps(steps, self.desired[-1], 0.8) + for j in range(steps): + sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') + if sol[1] == 1: + fowards = self.robot.fkine_all(sol[0]) + out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) + if np.any(out_of_bounds): + #print(fowards.t) + #indices = np.where(out_of_bounds)[0] + #print(f"indices: {indices}") + self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") + ''' + for i in indices: + try: + print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") + except IndexError: + print(f"index {i} is out of bounds, but no corresponding joint found.") + self.previous_desired_tcp_position = self.desired_tcp_position + ''' + break + duration = timestamps[j] + if duration == 0: + prev_sol = list(sol[0]) + continue + point = JointTrajectoryPoint() + point.positions = list(sol[0]) + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + prev_sol = list(sol[0]) + else: + self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") + prev_sol = self.current_joint_positions + if len(msg.points) == 0: + self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") + self.previous_desired = self.desired + return + msg.header.stamp = self.get_clock().now().to_msg() + self.publisher.publish(msg) + self.previous_desired = self.desired + + + + else: + prev_duration = 0 + ''' + if self.previous_desired == None: + [x,y,z] = self.robot.fkine(self.current_joint_positions).t + [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() + else: + [x,y,z] = self.previous_desired[:3] + [roll, pitch, yaw] = self.previous_desired[3:] + ''' + for j in range(steps): + sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') + if sol[1] == 1: + fowards = self.robot.fkine_all(sol[0]) + out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) + if np.any(out_of_bounds): + #print(fowards.t) + #indices = np.where(out_of_bounds)[0] + #print(f"indices: {indices}") + self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") + ''' + for i in indices: + try: + print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") + except IndexError: + print(f"index {i} is out of bounds, but no corresponding joint found.") + self.previous_desired_tcp_position = self.desired_tcp_position + ''' + break + duration = 0 + prev = self.current_joint_positions if j == 0 else prev_sol + for p1, p2, max_vel in zip(sol[0], prev, self.joint_velocity_limits.values()): + duration = max(duration, abs(p1 - p2) / max_vel)#, 1/self.hz) # as minimun + prev_sol = list(sol[0]) + if duration == 0: + continue + point = JointTrajectoryPoint() + point.positions = list(sol[0]) + duration *= 1.2 + duration /= self.speed_scaling + duration += prev_duration + prev_duration = duration + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + else: + self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") + prev_sol = self.current_joint_positions + if len(msg.points) == 0: + self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") + self.previous_desired = self.desired + return + msg.header.stamp = self.get_clock().now().to_msg() + self.publisher.publish(msg) + self.previous_desired = self.desired + except Exception as e: + self.get_logger().fatal(f"send_tcp_coordinates: {e}") + + def send_joint_trajectory(self): + + try: + self.new = False + viapoints = np.array([i for i in self.desired[1:]]) + msg = JointTrajectory() + msg.joint_names = self.joint_names + traj = rtb.mstraj(viapoints, q0 = self.current_joint_positions ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=[self.speed_scaling*i for i in self.joint_velocity_limits.values()]) + msg.points = [] + for i in range(len(traj.q)): + point = JointTrajectoryPoint() + point.positions = list(traj.q[i]) + point.time_from_start.sec = int(traj.t[i]) + point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) + msg.points.append(point) + msg.header.stamp = self.get_clock().now().to_msg() + self.publisher.publish(msg) + self.previous_desired = None + except Exception as e: + print(f'Error in joint_angles_handler: {e}') + + def send_cartesian_trajectory(self): + + try: + self.new = False + viapoints = np.array([i[:6] for i in self.desired[1:]]) + msg = JointTrajectory() + msg.joint_names = self.joint_names + x,y,z = self.robot.fkine(self.current_joint_positions).t + r,p,yaw = self.robot.fkine(self.current_joint_positions).rpy() + q0 = [x, y, z, r, p, yaw] + traj = rtb.mstraj(viapoints, q0 = q0 ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=2*self.speed_scaling) + msg.points = [] + prev_sol = self.current_joint_positions + n = max(int(len(traj.q)/200), 1) + for i in range(len(traj.q)): + T = sm.SE3(traj.q[i][:3]) * sm.SE3.RPY(traj.q[i][3:], order='xyz') + sol = self.robot.ik_LM(T, q0=prev_sol, mask = self.cost_mask, joint_limits = True) + if sol[1] == 1: + point = JointTrajectoryPoint() + point.positions = list(sol[0]) + point.time_from_start.sec = int(traj.t[i]) + if traj.t[i] == 0: + continue + point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) + msg.points.append(point) + prev_sol = list(sol[0]) + else: self.get_logger().warn(f"send_cartesian_trajectory: IK could not find a solution for (x,y,z) = {traj.q[i][:3]} and (r,p,y) = {traj.q[i][3:]}!") + msg.header.stamp = self.get_clock().now().to_msg() + msg.points = msg.points[::n] + self.publisher.publish(msg) + self.previous_desired = None + except Exception as e: + print(f'Error in joint_angles_handler: {e}') + + self.previous_desired = None + + def update_position(self): + """Calls the appropriate function to update the robot's position.""" + try: + if self.desired is None or not(self.new): + return + + if self.desired[0] == "joint_positions": + self.new = False + self.send_joint_positions() + return + elif self.desired[0] == "tcp_coordinates": + self.new = False + self.send_tcp_coordinates() + return + elif self.desired[0] == "joint_trajectory": + self.new = False + self.send_joint_trajectory() + return + elif self.desired[0] == "cartesian_trajectory": + self.new = False + self.send_cartesian_trajectory() + return + else: + self.get_logger().warn(f"update_position: Unknown desired type '{self.desired[0]}'.") + return + + + except Exception as e: + self.get_logger().fatal(f'update_position: {e}') + + + def clean_log_string(self, s): + + s = str(s) + + # Remove ANSI escape sequences (e.g., \x1b[31m) + ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') + s = ansi_escape.sub('', s) + + # Replace tabs/newlines with spaces + s = s.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ').replace("'", ' '). replace('"', ' ').replace('`', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ') + + # Strip leading/trailing whitespace + s = s.strip() + + # Optionally enforce ASCII only (replace non-ASCII chars with '?') + s = s.encode('ascii', 'replace').decode('ascii') + + return s + + + def log_callback(self, msg: Log): + """Callback function to handle incoming log messages.""" + + # Send the log message as an OSC message + msg_log = oscbuildparse.OSCMessage(f"/log/{self.log_dict.get(msg.level, 'UNKNOWN')}", ',isss', [int(msg.level), str(msg.stamp.sec+msg.stamp.nanosec*1e-9) , str(msg.name), self.clean_log_string(msg.msg)]) + osc_send(msg_log, "osc_log_client") + + +def main(): + """Main function to get joint names and start the ROS 2 & OSC system.""" + rclpy.init() + while True: + use_urdf = input("Do you have a URDF file you want to use? (y/n): ").strip().lower() + if use_urdf == 'y': + while True: + robot_urdf = input("Enter the absolute path to the URDF file: ") + if os.path.isfile(robot_urdf): + if not robot_urdf.endswith('.urdf'): + print("The file is not a URDF file. Please enter a valid URDF file.") + continue + break + else: + print("Invalid path. Please enter a valid path to the URDF file.") + tree = ET.parse(robot_urdf) + root = tree.getroot() + robot = rtb.ERobot.URDF(robot_urdf) + joint_names = [joint.get('name') for joint in root.findall('joint') if joint.get('type') == 'revolute' or joint.get('type') == 'continuous' or joint.get('type') == 'prismatic'] + print(robot) + joint_velocity_limits = {} + + # Iterate over all joints in the URDF + for joint in root.findall('.//joint'): + joint_name = joint.get('name') # Get the name of the joint + + # Look for the tag under each joint + limit = joint.find('limit') + + if limit is not None: + # Extract the velocity limit (if it exists) + velocity_limit = limit.get('velocity') + + if velocity_limit is not None: + joint_velocity_limits[joint_name] = float(velocity_limit) + + while True: + try: + print('-+'*50) + print("The cost mask determines which coordinates are used for the IK.\nEach element of the cost mask corresponds to a Cartesian coordinate [x, y, z, roll, pitch, yaw].") + print("The cost mask 111000 means that the IK will only consider translation and no rotaion.") + cost_mask = [int(i) for i in input(f"Enter the cost mask (6 integers (1 or 0), of which <= {robot.n} are 1): ")] + if sum(cost_mask) <= robot.n and len(cost_mask) == 6: + break + else: + print(f"Invalid input. Expected 6 integers of which {robot.n if robot.n < 6 else 6} or less are 1.") + except ValueError: + print("Invalid input. Please enter integers only.") + print(f"The following coordinates will be used for the IK: {[j for i,j in enumerate(['x','y','z','roll','pitch','yaw']) if cost_mask[i]==1]}") + break + elif use_urdf == 'n': + node = JointNameListener() + print("Wainting 10 sec for JointState messages to extract joint names...") + rclpy.spin_once(node) + counter = 0 + while not(node.joint_names): + if counter > 100: + joint_names = None + break + counter+=1 + time.sleep(0.1) + rclpy.spin_once(node) + joint_names = node.joint_names + node.destroy_node() + if joint_names: + correct_names = input("The following joint names were found:\n" + "\n".join(joint_names) + "\nAre these correct? (y/n): ").strip().lower() + while True: + if correct_names == 'y': + break + elif correct_names == 'n': + joint_names = None + break + correct_names = input("Invalid input. Please enter 'y' or 'n'.") + if not(joint_names): + print("Please enter the joint names manually.") + while True: + joint_names = [] + print('-+'*50) + print("Enter the joint names manually one by one. Type 'done' when you are finished:") + print("Attention: The order of the joints is important. It should be the same in which you want to send the joint positions.") + while True: + print('-'*50) + joint_name = input("Enter joint name (or 'done' to finish): ").strip() + if joint_name.lower() == 'done': + break + if joint_name: + joint_names.append(joint_name) + print('-+'*50) + correct_names = input(f"Are those the joint names as defined in your JointTrajectroy recieving Node?: {joint_names}. (y/n)?: ").strip() + if correct_names.lower() == 'y': + break + else: + print("Please re-enter the joint names.") + while True: + try: + joint_velocity_limits = {} + for name in joint_names: + while True: + try: + print('--'*50) + limit = input(f"Enter the velocity limit for joint '{name}': ").strip() + if limit == "": + continue + else: + joint_velocity_limits[name] = float(limit) + break + except ValueError: + print("Invalid input. Please enter a numeric value or press Enter to skip.") + break + except ValueError: + print("Invalid input. Please enter numeric values or leave blank to skip.") + robot = None + cost_mask = None + break + print("Invalid input. Please enter 'y' or 'n'.") + + + node = OSC_ROS2_interface(joint_names, joint_velocity_limits, robot, cost_mask) + + # Run ROS 2 spin, and osc_process will be handled by the timer + try: + rclpy.spin(node) + except KeyboardInterrupt: + print("") + finally: + node.destroy_node() + osc_terminate() + +if __name__ == '__main__': + main() diff --git a/workspace/build/osc_ros2/colcon_build.rc b/workspace/build/osc_ros2/colcon_build.rc new file mode 100644 index 0000000..573541a --- /dev/null +++ b/workspace/build/osc_ros2/colcon_build.rc @@ -0,0 +1 @@ +0 diff --git a/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh b/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh new file mode 100644 index 0000000..f9867d5 --- /dev/null +++ b/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh @@ -0,0 +1 @@ +# generated from colcon_core/shell/template/command_prefix.sh.em diff --git a/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env b/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env new file mode 100644 index 0000000..5f4a769 --- /dev/null +++ b/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env @@ -0,0 +1,20 @@ +AMENT_PREFIX_PATH=/workspace/install/osc_ros2:/opt/ros/humble +COLCON=1 +COLCON_PREFIX_PATH=/workspace/install +HOME=/root +HOSTNAME=ad72f3440b4e +LANG=C.UTF-8 +LC_ALL=C.UTF-8 +LD_LIBRARY_PATH=/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib +LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36: +OLDPWD=/ +PATH=/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +PWD=/workspace/build/osc_ros2 +PYTHONPATH=/workspace/install/osc_ros2/lib/python3.10/site-packages:/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages +ROS_DISTRO=humble +ROS_LOCALHOST_ONLY=0 +ROS_PYTHON_VERSION=3 +ROS_VERSION=2 +SHLVL=1 +TERM=xterm +_=/usr/bin/colcon diff --git a/workspace/build/osc_ros2/install.log b/workspace/build/osc_ros2/install.log new file mode 100644 index 0000000..bebe111 --- /dev/null +++ b/workspace/build/osc_ros2/install.log @@ -0,0 +1,14 @@ +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/osc_ros2.cpython-310.pyc +/workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 +/workspace/install/osc_ros2/share/osc_ros2/package.xml +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt +/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt +/workspace/install/osc_ros2/lib/osc_ros2/interface diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO b/workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO new file mode 100644 index 0000000..275623c --- /dev/null +++ b/workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO @@ -0,0 +1,12 @@ +Metadata-Version: 2.1 +Name: osc-ros2 +Version: 1.0.0 +Summary: Creates an interface for communication between OSC and Ros2 +Home-page: UNKNOWN +Maintainer: Alexander Schaefer +Maintainer-email: a.schaefer@tuhh.de +License: Apache-2.0 +Platform: UNKNOWN + +UNKNOWN + diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt new file mode 100644 index 0000000..650a016 --- /dev/null +++ b/workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt @@ -0,0 +1,16 @@ +package.xml +setup.cfg +setup.py +../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt +../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +../../build/osc_ros2/osc_ros2.egg-info/requires.txt +../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +../../build/osc_ros2/osc_ros2.egg-info/zip-safe +osc_ros2/__init__.py +osc_ros2/osc_ros2.py +resource/osc_ros2 +test/test_copyright.py +test/test_flake8.py +test/test_pep257.py \ No newline at end of file diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt new file mode 100644 index 0000000..008581c --- /dev/null +++ b/workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +interface = osc_ros2.osc_ros2:main + diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt new file mode 100644 index 0000000..3c8c415 --- /dev/null +++ b/workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt @@ -0,0 +1,6 @@ +numpy==1.22.4 +osc4py3 +roboticstoolbox-python +scipy==1.7.3 +setuptools +spatialmath-python diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt new file mode 100644 index 0000000..99ee4eb --- /dev/null +++ b/workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt @@ -0,0 +1 @@ +osc_ros2 diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe b/workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe @@ -0,0 +1 @@ + diff --git a/workspace/build/osc_ros2/prefix_override/__pycache__/sitecustomize.cpython-310.pyc b/workspace/build/osc_ros2/prefix_override/__pycache__/sitecustomize.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5cfe64334ee70c5f964f01a77093a23dd61fcae0 GIT binary patch literal 277 zcmd1j<>g`k0+T+oj5Z+s7{oya%s`F<5EttKi4=wu#vFzyhE#?u#uTP(rXo=gE0rOh zDTSE@C>jr9Gp8^H1JwmHXtKNn>S6G!V$m-xE~=8&FV8Q^E-pw+PSwxMD=taQ$PO2Rv(70ky7;rFf MF>){pFtYpu06PUsga7~l literal 0 HcmV?d00001 diff --git a/workspace/build/osc_ros2/prefix_override/sitecustomize.py b/workspace/build/osc_ros2/prefix_override/sitecustomize.py new file mode 100644 index 0000000..f14fb81 --- /dev/null +++ b/workspace/build/osc_ros2/prefix_override/sitecustomize.py @@ -0,0 +1,4 @@ +import sys +if sys.prefix == '/usr': + sys.real_prefix = sys.prefix + sys.prefix = sys.exec_prefix = '/workspace/install/osc_ros2' diff --git a/workspace/install/.colcon_install_layout b/workspace/install/.colcon_install_layout new file mode 100644 index 0000000..3aad533 --- /dev/null +++ b/workspace/install/.colcon_install_layout @@ -0,0 +1 @@ +isolated diff --git a/workspace/install/COLCON_IGNORE b/workspace/install/COLCON_IGNORE new file mode 100644 index 0000000..e69de29 diff --git a/workspace/install/_local_setup_util_ps1.py b/workspace/install/_local_setup_util_ps1.py new file mode 100644 index 0000000..3c6d9e8 --- /dev/null +++ b/workspace/install/_local_setup_util_ps1.py @@ -0,0 +1,407 @@ +# Copyright 2016-2019 Dirk Thomas +# Licensed under the Apache License, Version 2.0 + +import argparse +from collections import OrderedDict +import os +from pathlib import Path +import sys + + +FORMAT_STR_COMMENT_LINE = '# {comment}' +FORMAT_STR_SET_ENV_VAR = 'Set-Item -Path "Env:{name}" -Value "{value}"' +FORMAT_STR_USE_ENV_VAR = '$env:{name}' +FORMAT_STR_INVOKE_SCRIPT = '_colcon_prefix_powershell_source_script "{script_path}"' # noqa: E501 +FORMAT_STR_REMOVE_LEADING_SEPARATOR = '' # noqa: E501 +FORMAT_STR_REMOVE_TRAILING_SEPARATOR = '' # noqa: E501 + +DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists' +DSV_TYPE_SET = 'set' +DSV_TYPE_SET_IF_UNSET = 'set-if-unset' +DSV_TYPE_SOURCE = 'source' + + +def main(argv=sys.argv[1:]): # noqa: D103 + parser = argparse.ArgumentParser( + description='Output shell commands for the packages in topological ' + 'order') + parser.add_argument( + 'primary_extension', + help='The file extension of the primary shell') + parser.add_argument( + 'additional_extension', nargs='?', + help='The additional file extension to be considered') + parser.add_argument( + '--merged-install', action='store_true', + help='All install prefixes are merged into a single location') + args = parser.parse_args(argv) + + packages = get_packages(Path(__file__).parent, args.merged_install) + + ordered_packages = order_packages(packages) + for pkg_name in ordered_packages: + if _include_comments(): + print( + FORMAT_STR_COMMENT_LINE.format_map( + {'comment': 'Package: ' + pkg_name})) + prefix = os.path.abspath(os.path.dirname(__file__)) + if not args.merged_install: + prefix = os.path.join(prefix, pkg_name) + for line in get_commands( + pkg_name, prefix, args.primary_extension, + args.additional_extension + ): + print(line) + + for line in _remove_ending_separators(): + print(line) + + +def get_packages(prefix_path, merged_install): + """ + Find packages based on colcon-specific files created during installation. + + :param Path prefix_path: The install prefix path of all packages + :param bool merged_install: The flag if the packages are all installed + directly in the prefix or if each package is installed in a subdirectory + named after the package + :returns: A mapping from the package name to the set of runtime + dependencies + :rtype: dict + """ + packages = {} + # since importing colcon_core isn't feasible here the following constant + # must match colcon_core.location.get_relative_package_index_path() + subdirectory = 'share/colcon-core/packages' + if merged_install: + # return if workspace is empty + if not (prefix_path / subdirectory).is_dir(): + return packages + # find all files in the subdirectory + for p in (prefix_path / subdirectory).iterdir(): + if not p.is_file(): + continue + if p.name.startswith('.'): + continue + add_package_runtime_dependencies(p, packages) + else: + # for each subdirectory look for the package specific file + for p in prefix_path.iterdir(): + if not p.is_dir(): + continue + if p.name.startswith('.'): + continue + p = p / subdirectory / p.name + if p.is_file(): + add_package_runtime_dependencies(p, packages) + + # remove unknown dependencies + pkg_names = set(packages.keys()) + for k in packages.keys(): + packages[k] = {d for d in packages[k] if d in pkg_names} + + return packages + + +def add_package_runtime_dependencies(path, packages): + """ + Check the path and if it exists extract the packages runtime dependencies. + + :param Path path: The resource file containing the runtime dependencies + :param dict packages: A mapping from package names to the sets of runtime + dependencies to add to + """ + content = path.read_text() + dependencies = set(content.split(os.pathsep) if content else []) + packages[path.name] = dependencies + + +def order_packages(packages): + """ + Order packages topologically. + + :param dict packages: A mapping from package name to the set of runtime + dependencies + :returns: The package names + :rtype: list + """ + # select packages with no dependencies in alphabetical order + to_be_ordered = list(packages.keys()) + ordered = [] + while to_be_ordered: + pkg_names_without_deps = [ + name for name in to_be_ordered if not packages[name]] + if not pkg_names_without_deps: + reduce_cycle_set(packages) + raise RuntimeError( + 'Circular dependency between: ' + ', '.join(sorted(packages))) + pkg_names_without_deps.sort() + pkg_name = pkg_names_without_deps[0] + to_be_ordered.remove(pkg_name) + ordered.append(pkg_name) + # remove item from dependency lists + for k in list(packages.keys()): + if pkg_name in packages[k]: + packages[k].remove(pkg_name) + return ordered + + +def reduce_cycle_set(packages): + """ + Reduce the set of packages to the ones part of the circular dependency. + + :param dict packages: A mapping from package name to the set of runtime + dependencies which is modified in place + """ + last_depended = None + while len(packages) > 0: + # get all remaining dependencies + depended = set() + for pkg_name, dependencies in packages.items(): + depended = depended.union(dependencies) + # remove all packages which are not dependent on + for name in list(packages.keys()): + if name not in depended: + del packages[name] + if last_depended: + # if remaining packages haven't changed return them + if last_depended == depended: + return packages.keys() + # otherwise reduce again + last_depended = depended + + +def _include_comments(): + # skipping comment lines when COLCON_TRACE is not set speeds up the + # processing especially on Windows + return bool(os.environ.get('COLCON_TRACE')) + + +def get_commands(pkg_name, prefix, primary_extension, additional_extension): + commands = [] + package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv') + if os.path.exists(package_dsv_path): + commands += process_dsv_file( + package_dsv_path, prefix, primary_extension, additional_extension) + return commands + + +def process_dsv_file( + dsv_path, prefix, primary_extension=None, additional_extension=None +): + commands = [] + if _include_comments(): + commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path})) + with open(dsv_path, 'r') as h: + content = h.read() + lines = content.splitlines() + + basenames = OrderedDict() + for i, line in enumerate(lines): + # skip over empty or whitespace-only lines + if not line.strip(): + continue + # skip over comments + if line.startswith('#'): + continue + try: + type_, remainder = line.split(';', 1) + except ValueError: + raise RuntimeError( + "Line %d in '%s' doesn't contain a semicolon separating the " + 'type from the arguments' % (i + 1, dsv_path)) + if type_ != DSV_TYPE_SOURCE: + # handle non-source lines + try: + commands += handle_dsv_types_except_source( + type_, remainder, prefix) + except RuntimeError as e: + raise RuntimeError( + "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e + else: + # group remaining source lines by basename + path_without_ext, ext = os.path.splitext(remainder) + if path_without_ext not in basenames: + basenames[path_without_ext] = set() + assert ext.startswith('.') + ext = ext[1:] + if ext in (primary_extension, additional_extension): + basenames[path_without_ext].add(ext) + + # add the dsv extension to each basename if the file exists + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if os.path.exists(basename + '.dsv'): + extensions.add('dsv') + + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if 'dsv' in extensions: + # process dsv files recursively + commands += process_dsv_file( + basename + '.dsv', prefix, primary_extension=primary_extension, + additional_extension=additional_extension) + elif primary_extension in extensions and len(extensions) == 1: + # source primary-only files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + primary_extension})] + elif additional_extension in extensions: + # source non-primary files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + additional_extension})] + + return commands + + +def handle_dsv_types_except_source(type_, remainder, prefix): + commands = [] + if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET): + try: + env_name, value = remainder.split(';', 1) + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the value') + try_prefixed_value = os.path.join(prefix, value) if value else prefix + if os.path.exists(try_prefixed_value): + value = try_prefixed_value + if type_ == DSV_TYPE_SET: + commands += _set(env_name, value) + elif type_ == DSV_TYPE_SET_IF_UNSET: + commands += _set_if_unset(env_name, value) + else: + assert False + elif type_ in ( + DSV_TYPE_APPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS + ): + try: + env_name_and_values = remainder.split(';') + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the values') + env_name = env_name_and_values[0] + values = env_name_and_values[1:] + for value in values: + if not value: + value = prefix + elif not os.path.isabs(value): + value = os.path.join(prefix, value) + if ( + type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and + not os.path.exists(value) + ): + comment = f'skip extending {env_name} with not existing ' \ + f'path: {value}' + if _include_comments(): + commands.append( + FORMAT_STR_COMMENT_LINE.format_map({'comment': comment})) + elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE: + commands += _append_unique_value(env_name, value) + else: + commands += _prepend_unique_value(env_name, value) + else: + raise RuntimeError( + 'contains an unknown environment hook type: ' + type_) + return commands + + +env_state = {} + + +def _append_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # append even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional leading separator + extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': extend + value}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +def _prepend_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # prepend even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional trailing separator + extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value + extend}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +# generate commands for removing prepended underscores +def _remove_ending_separators(): + # do nothing if the shell extension does not implement the logic + if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None: + return [] + + global env_state + commands = [] + for name in env_state: + # skip variables that already had values before this script started prepending + if name in os.environ: + continue + commands += [ + FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}), + FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})] + return commands + + +def _set(name, value): + global env_state + env_state[name] = value + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + return [line] + + +def _set_if_unset(name, value): + global env_state + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + if env_state.get(name, os.environ.get(name)): + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +if __name__ == '__main__': # pragma: no cover + try: + rc = main() + except RuntimeError as e: + print(str(e), file=sys.stderr) + rc = 1 + sys.exit(rc) diff --git a/workspace/install/_local_setup_util_sh.py b/workspace/install/_local_setup_util_sh.py new file mode 100644 index 0000000..f67eaa9 --- /dev/null +++ b/workspace/install/_local_setup_util_sh.py @@ -0,0 +1,407 @@ +# Copyright 2016-2019 Dirk Thomas +# Licensed under the Apache License, Version 2.0 + +import argparse +from collections import OrderedDict +import os +from pathlib import Path +import sys + + +FORMAT_STR_COMMENT_LINE = '# {comment}' +FORMAT_STR_SET_ENV_VAR = 'export {name}="{value}"' +FORMAT_STR_USE_ENV_VAR = '${name}' +FORMAT_STR_INVOKE_SCRIPT = 'COLCON_CURRENT_PREFIX="{prefix}" _colcon_prefix_sh_source_script "{script_path}"' # noqa: E501 +FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi' # noqa: E501 +FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi' # noqa: E501 + +DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists' +DSV_TYPE_SET = 'set' +DSV_TYPE_SET_IF_UNSET = 'set-if-unset' +DSV_TYPE_SOURCE = 'source' + + +def main(argv=sys.argv[1:]): # noqa: D103 + parser = argparse.ArgumentParser( + description='Output shell commands for the packages in topological ' + 'order') + parser.add_argument( + 'primary_extension', + help='The file extension of the primary shell') + parser.add_argument( + 'additional_extension', nargs='?', + help='The additional file extension to be considered') + parser.add_argument( + '--merged-install', action='store_true', + help='All install prefixes are merged into a single location') + args = parser.parse_args(argv) + + packages = get_packages(Path(__file__).parent, args.merged_install) + + ordered_packages = order_packages(packages) + for pkg_name in ordered_packages: + if _include_comments(): + print( + FORMAT_STR_COMMENT_LINE.format_map( + {'comment': 'Package: ' + pkg_name})) + prefix = os.path.abspath(os.path.dirname(__file__)) + if not args.merged_install: + prefix = os.path.join(prefix, pkg_name) + for line in get_commands( + pkg_name, prefix, args.primary_extension, + args.additional_extension + ): + print(line) + + for line in _remove_ending_separators(): + print(line) + + +def get_packages(prefix_path, merged_install): + """ + Find packages based on colcon-specific files created during installation. + + :param Path prefix_path: The install prefix path of all packages + :param bool merged_install: The flag if the packages are all installed + directly in the prefix or if each package is installed in a subdirectory + named after the package + :returns: A mapping from the package name to the set of runtime + dependencies + :rtype: dict + """ + packages = {} + # since importing colcon_core isn't feasible here the following constant + # must match colcon_core.location.get_relative_package_index_path() + subdirectory = 'share/colcon-core/packages' + if merged_install: + # return if workspace is empty + if not (prefix_path / subdirectory).is_dir(): + return packages + # find all files in the subdirectory + for p in (prefix_path / subdirectory).iterdir(): + if not p.is_file(): + continue + if p.name.startswith('.'): + continue + add_package_runtime_dependencies(p, packages) + else: + # for each subdirectory look for the package specific file + for p in prefix_path.iterdir(): + if not p.is_dir(): + continue + if p.name.startswith('.'): + continue + p = p / subdirectory / p.name + if p.is_file(): + add_package_runtime_dependencies(p, packages) + + # remove unknown dependencies + pkg_names = set(packages.keys()) + for k in packages.keys(): + packages[k] = {d for d in packages[k] if d in pkg_names} + + return packages + + +def add_package_runtime_dependencies(path, packages): + """ + Check the path and if it exists extract the packages runtime dependencies. + + :param Path path: The resource file containing the runtime dependencies + :param dict packages: A mapping from package names to the sets of runtime + dependencies to add to + """ + content = path.read_text() + dependencies = set(content.split(os.pathsep) if content else []) + packages[path.name] = dependencies + + +def order_packages(packages): + """ + Order packages topologically. + + :param dict packages: A mapping from package name to the set of runtime + dependencies + :returns: The package names + :rtype: list + """ + # select packages with no dependencies in alphabetical order + to_be_ordered = list(packages.keys()) + ordered = [] + while to_be_ordered: + pkg_names_without_deps = [ + name for name in to_be_ordered if not packages[name]] + if not pkg_names_without_deps: + reduce_cycle_set(packages) + raise RuntimeError( + 'Circular dependency between: ' + ', '.join(sorted(packages))) + pkg_names_without_deps.sort() + pkg_name = pkg_names_without_deps[0] + to_be_ordered.remove(pkg_name) + ordered.append(pkg_name) + # remove item from dependency lists + for k in list(packages.keys()): + if pkg_name in packages[k]: + packages[k].remove(pkg_name) + return ordered + + +def reduce_cycle_set(packages): + """ + Reduce the set of packages to the ones part of the circular dependency. + + :param dict packages: A mapping from package name to the set of runtime + dependencies which is modified in place + """ + last_depended = None + while len(packages) > 0: + # get all remaining dependencies + depended = set() + for pkg_name, dependencies in packages.items(): + depended = depended.union(dependencies) + # remove all packages which are not dependent on + for name in list(packages.keys()): + if name not in depended: + del packages[name] + if last_depended: + # if remaining packages haven't changed return them + if last_depended == depended: + return packages.keys() + # otherwise reduce again + last_depended = depended + + +def _include_comments(): + # skipping comment lines when COLCON_TRACE is not set speeds up the + # processing especially on Windows + return bool(os.environ.get('COLCON_TRACE')) + + +def get_commands(pkg_name, prefix, primary_extension, additional_extension): + commands = [] + package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv') + if os.path.exists(package_dsv_path): + commands += process_dsv_file( + package_dsv_path, prefix, primary_extension, additional_extension) + return commands + + +def process_dsv_file( + dsv_path, prefix, primary_extension=None, additional_extension=None +): + commands = [] + if _include_comments(): + commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path})) + with open(dsv_path, 'r') as h: + content = h.read() + lines = content.splitlines() + + basenames = OrderedDict() + for i, line in enumerate(lines): + # skip over empty or whitespace-only lines + if not line.strip(): + continue + # skip over comments + if line.startswith('#'): + continue + try: + type_, remainder = line.split(';', 1) + except ValueError: + raise RuntimeError( + "Line %d in '%s' doesn't contain a semicolon separating the " + 'type from the arguments' % (i + 1, dsv_path)) + if type_ != DSV_TYPE_SOURCE: + # handle non-source lines + try: + commands += handle_dsv_types_except_source( + type_, remainder, prefix) + except RuntimeError as e: + raise RuntimeError( + "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e + else: + # group remaining source lines by basename + path_without_ext, ext = os.path.splitext(remainder) + if path_without_ext not in basenames: + basenames[path_without_ext] = set() + assert ext.startswith('.') + ext = ext[1:] + if ext in (primary_extension, additional_extension): + basenames[path_without_ext].add(ext) + + # add the dsv extension to each basename if the file exists + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if os.path.exists(basename + '.dsv'): + extensions.add('dsv') + + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if 'dsv' in extensions: + # process dsv files recursively + commands += process_dsv_file( + basename + '.dsv', prefix, primary_extension=primary_extension, + additional_extension=additional_extension) + elif primary_extension in extensions and len(extensions) == 1: + # source primary-only files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + primary_extension})] + elif additional_extension in extensions: + # source non-primary files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + additional_extension})] + + return commands + + +def handle_dsv_types_except_source(type_, remainder, prefix): + commands = [] + if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET): + try: + env_name, value = remainder.split(';', 1) + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the value') + try_prefixed_value = os.path.join(prefix, value) if value else prefix + if os.path.exists(try_prefixed_value): + value = try_prefixed_value + if type_ == DSV_TYPE_SET: + commands += _set(env_name, value) + elif type_ == DSV_TYPE_SET_IF_UNSET: + commands += _set_if_unset(env_name, value) + else: + assert False + elif type_ in ( + DSV_TYPE_APPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS + ): + try: + env_name_and_values = remainder.split(';') + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the values') + env_name = env_name_and_values[0] + values = env_name_and_values[1:] + for value in values: + if not value: + value = prefix + elif not os.path.isabs(value): + value = os.path.join(prefix, value) + if ( + type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and + not os.path.exists(value) + ): + comment = f'skip extending {env_name} with not existing ' \ + f'path: {value}' + if _include_comments(): + commands.append( + FORMAT_STR_COMMENT_LINE.format_map({'comment': comment})) + elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE: + commands += _append_unique_value(env_name, value) + else: + commands += _prepend_unique_value(env_name, value) + else: + raise RuntimeError( + 'contains an unknown environment hook type: ' + type_) + return commands + + +env_state = {} + + +def _append_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # append even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional leading separator + extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': extend + value}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +def _prepend_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # prepend even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional trailing separator + extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value + extend}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +# generate commands for removing prepended underscores +def _remove_ending_separators(): + # do nothing if the shell extension does not implement the logic + if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None: + return [] + + global env_state + commands = [] + for name in env_state: + # skip variables that already had values before this script started prepending + if name in os.environ: + continue + commands += [ + FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}), + FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})] + return commands + + +def _set(name, value): + global env_state + env_state[name] = value + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + return [line] + + +def _set_if_unset(name, value): + global env_state + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + if env_state.get(name, os.environ.get(name)): + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +if __name__ == '__main__': # pragma: no cover + try: + rc = main() + except RuntimeError as e: + print(str(e), file=sys.stderr) + rc = 1 + sys.exit(rc) diff --git a/workspace/install/local_setup.bash b/workspace/install/local_setup.bash new file mode 100644 index 0000000..03f0025 --- /dev/null +++ b/workspace/install/local_setup.bash @@ -0,0 +1,121 @@ +# generated from colcon_bash/shell/template/prefix.bash.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# a bash script is able to determine its own path if necessary +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)" +else + _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +_colcon_prefix_bash_prepend_unique_value() { + # arguments + _listname="$1" + _value="$2" + + # get values from variable + eval _values=\"\$$_listname\" + # backup the field separator + _colcon_prefix_bash_prepend_unique_value_IFS="$IFS" + IFS=":" + # start with the new value + _all_values="$_value" + _contained_value="" + # iterate over existing values in the variable + for _item in $_values; do + # ignore empty strings + if [ -z "$_item" ]; then + continue + fi + # ignore duplicates of _value + if [ "$_item" = "$_value" ]; then + _contained_value=1 + continue + fi + # keep non-duplicate values + _all_values="$_all_values:$_item" + done + unset _item + if [ -z "$_contained_value" ]; then + if [ -n "$COLCON_TRACE" ]; then + if [ "$_all_values" = "$_value" ]; then + echo "export $_listname=$_value" + else + echo "export $_listname=$_value:\$$_listname" + fi + fi + fi + unset _contained_value + # restore the field separator + IFS="$_colcon_prefix_bash_prepend_unique_value_IFS" + unset _colcon_prefix_bash_prepend_unique_value_IFS + # export the updated variable + eval export $_listname=\"$_all_values\" + unset _all_values + unset _values + + unset _value + unset _listname +} + +# add this prefix to the COLCON_PREFIX_PATH +_colcon_prefix_bash_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX" +unset _colcon_prefix_bash_prepend_unique_value + +# check environment variable for custom Python executable +if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then + if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then + echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" + return 1 + fi + _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" +else + # try the Python executable known at configure time + _colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if [ ! -f "$_colcon_python_executable" ]; then + if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then + echo "error: unable to find python3 executable" + return 1 + fi + _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` + fi +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# get all commands in topological order +_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh bash)" +unset _colcon_python_executable +if [ -n "$COLCON_TRACE" ]; then + echo "$(declare -f _colcon_prefix_sh_source_script)" + echo "# Execute generated script:" + echo "# <<<" + echo "${_colcon_ordered_commands}" + echo "# >>>" + echo "unset _colcon_prefix_sh_source_script" +fi +eval "${_colcon_ordered_commands}" +unset _colcon_ordered_commands + +unset _colcon_prefix_sh_source_script + +unset _colcon_prefix_bash_COLCON_CURRENT_PREFIX diff --git a/workspace/install/local_setup.ps1 b/workspace/install/local_setup.ps1 new file mode 100644 index 0000000..6f68c8d --- /dev/null +++ b/workspace/install/local_setup.ps1 @@ -0,0 +1,55 @@ +# generated from colcon_powershell/shell/template/prefix.ps1.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# check environment variable for custom Python executable +if ($env:COLCON_PYTHON_EXECUTABLE) { + if (!(Test-Path "$env:COLCON_PYTHON_EXECUTABLE" -PathType Leaf)) { + echo "error: COLCON_PYTHON_EXECUTABLE '$env:COLCON_PYTHON_EXECUTABLE' doesn't exist" + exit 1 + } + $_colcon_python_executable="$env:COLCON_PYTHON_EXECUTABLE" +} else { + # use the Python executable known at configure time + $_colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if (!(Test-Path "$_colcon_python_executable" -PathType Leaf)) { + if (!(Get-Command "python3" -ErrorAction SilentlyContinue)) { + echo "error: unable to find python3 executable" + exit 1 + } + $_colcon_python_executable="python3" + } +} + +# function to source another script with conditional trace output +# first argument: the path of the script +function _colcon_prefix_powershell_source_script { + param ( + $_colcon_prefix_powershell_source_script_param + ) + # source script with conditional trace output + if (Test-Path $_colcon_prefix_powershell_source_script_param) { + if ($env:COLCON_TRACE) { + echo ". '$_colcon_prefix_powershell_source_script_param'" + } + . "$_colcon_prefix_powershell_source_script_param" + } else { + Write-Error "not found: '$_colcon_prefix_powershell_source_script_param'" + } +} + +# get all commands in topological order +$_colcon_ordered_commands = & "$_colcon_python_executable" "$(Split-Path $PSCommandPath -Parent)/_local_setup_util_ps1.py" ps1 + +# execute all commands in topological order +if ($env:COLCON_TRACE) { + echo "Execute generated script:" + echo "<<<" + $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Write-Output + echo ">>>" +} +if ($_colcon_ordered_commands) { + $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Invoke-Expression +} diff --git a/workspace/install/local_setup.sh b/workspace/install/local_setup.sh new file mode 100644 index 0000000..24bb54f --- /dev/null +++ b/workspace/install/local_setup.sh @@ -0,0 +1,137 @@ +# generated from colcon_core/shell/template/prefix.sh.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# since a plain shell script can't determine its own path when being sourced +# either use the provided COLCON_CURRENT_PREFIX +# or fall back to the build time prefix (if it exists) +_colcon_prefix_sh_COLCON_CURRENT_PREFIX="/workspace/install" +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + if [ ! -d "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" ]; then + echo "The build time path \"$_colcon_prefix_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 + unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX + return 1 + fi +else + _colcon_prefix_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +_colcon_prefix_sh_prepend_unique_value() { + # arguments + _listname="$1" + _value="$2" + + # get values from variable + eval _values=\"\$$_listname\" + # backup the field separator + _colcon_prefix_sh_prepend_unique_value_IFS="$IFS" + IFS=":" + # start with the new value + _all_values="$_value" + _contained_value="" + # iterate over existing values in the variable + for _item in $_values; do + # ignore empty strings + if [ -z "$_item" ]; then + continue + fi + # ignore duplicates of _value + if [ "$_item" = "$_value" ]; then + _contained_value=1 + continue + fi + # keep non-duplicate values + _all_values="$_all_values:$_item" + done + unset _item + if [ -z "$_contained_value" ]; then + if [ -n "$COLCON_TRACE" ]; then + if [ "$_all_values" = "$_value" ]; then + echo "export $_listname=$_value" + else + echo "export $_listname=$_value:\$$_listname" + fi + fi + fi + unset _contained_value + # restore the field separator + IFS="$_colcon_prefix_sh_prepend_unique_value_IFS" + unset _colcon_prefix_sh_prepend_unique_value_IFS + # export the updated variable + eval export $_listname=\"$_all_values\" + unset _all_values + unset _values + + unset _value + unset _listname +} + +# add this prefix to the COLCON_PREFIX_PATH +_colcon_prefix_sh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" +unset _colcon_prefix_sh_prepend_unique_value + +# check environment variable for custom Python executable +if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then + if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then + echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" + return 1 + fi + _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" +else + # try the Python executable known at configure time + _colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if [ ! -f "$_colcon_python_executable" ]; then + if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then + echo "error: unable to find python3 executable" + return 1 + fi + _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` + fi +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# get all commands in topological order +_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh)" +unset _colcon_python_executable +if [ -n "$COLCON_TRACE" ]; then + echo "_colcon_prefix_sh_source_script() { + if [ -f \"\$1\" ]; then + if [ -n \"\$COLCON_TRACE\" ]; then + echo \"# . \\\"\$1\\\"\" + fi + . \"\$1\" + else + echo \"not found: \\\"\$1\\\"\" 1>&2 + fi + }" + echo "# Execute generated script:" + echo "# <<<" + echo "${_colcon_ordered_commands}" + echo "# >>>" + echo "unset _colcon_prefix_sh_source_script" +fi +eval "${_colcon_ordered_commands}" +unset _colcon_ordered_commands + +unset _colcon_prefix_sh_source_script + +unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX diff --git a/workspace/install/local_setup.zsh b/workspace/install/local_setup.zsh new file mode 100644 index 0000000..b648710 --- /dev/null +++ b/workspace/install/local_setup.zsh @@ -0,0 +1,134 @@ +# generated from colcon_zsh/shell/template/prefix.zsh.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# a zsh script is able to determine its own path if necessary +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)" +else + _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to convert array-like strings into arrays +# to workaround SH_WORD_SPLIT not being set +_colcon_prefix_zsh_convert_to_array() { + local _listname=$1 + local _dollar="$" + local _split="{=" + local _to_array="(\"$_dollar$_split$_listname}\")" + eval $_listname=$_to_array +} + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +_colcon_prefix_zsh_prepend_unique_value() { + # arguments + _listname="$1" + _value="$2" + + # get values from variable + eval _values=\"\$$_listname\" + # backup the field separator + _colcon_prefix_zsh_prepend_unique_value_IFS="$IFS" + IFS=":" + # start with the new value + _all_values="$_value" + _contained_value="" + # workaround SH_WORD_SPLIT not being set + _colcon_prefix_zsh_convert_to_array _values + # iterate over existing values in the variable + for _item in $_values; do + # ignore empty strings + if [ -z "$_item" ]; then + continue + fi + # ignore duplicates of _value + if [ "$_item" = "$_value" ]; then + _contained_value=1 + continue + fi + # keep non-duplicate values + _all_values="$_all_values:$_item" + done + unset _item + if [ -z "$_contained_value" ]; then + if [ -n "$COLCON_TRACE" ]; then + if [ "$_all_values" = "$_value" ]; then + echo "export $_listname=$_value" + else + echo "export $_listname=$_value:\$$_listname" + fi + fi + fi + unset _contained_value + # restore the field separator + IFS="$_colcon_prefix_zsh_prepend_unique_value_IFS" + unset _colcon_prefix_zsh_prepend_unique_value_IFS + # export the updated variable + eval export $_listname=\"$_all_values\" + unset _all_values + unset _values + + unset _value + unset _listname +} + +# add this prefix to the COLCON_PREFIX_PATH +_colcon_prefix_zsh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX" +unset _colcon_prefix_zsh_prepend_unique_value +unset _colcon_prefix_zsh_convert_to_array + +# check environment variable for custom Python executable +if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then + if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then + echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" + return 1 + fi + _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" +else + # try the Python executable known at configure time + _colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if [ ! -f "$_colcon_python_executable" ]; then + if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then + echo "error: unable to find python3 executable" + return 1 + fi + _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` + fi +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# get all commands in topological order +_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh zsh)" +unset _colcon_python_executable +if [ -n "$COLCON_TRACE" ]; then + echo "$(declare -f _colcon_prefix_sh_source_script)" + echo "# Execute generated script:" + echo "# <<<" + echo "${_colcon_ordered_commands}" + echo "# >>>" + echo "unset _colcon_prefix_sh_source_script" +fi +eval "${_colcon_ordered_commands}" +unset _colcon_ordered_commands + +unset _colcon_prefix_sh_source_script + +unset _colcon_prefix_zsh_COLCON_CURRENT_PREFIX diff --git a/workspace/install/osc_ros2/lib/osc_ros2/interface b/workspace/install/osc_ros2/lib/osc_ros2/interface new file mode 100755 index 0000000..61d20a1 --- /dev/null +++ b/workspace/install/osc_ros2/lib/osc_ros2/interface @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +# EASY-INSTALL-ENTRY-SCRIPT: 'osc-ros2==1.0.0','console_scripts','interface' +import re +import sys + +# for compatibility with easy_install; see #2198 +__requires__ = 'osc-ros2==1.0.0' + +try: + from importlib.metadata import distribution +except ImportError: + try: + from importlib_metadata import distribution + except ImportError: + from pkg_resources import load_entry_point + + +def importlib_load_entry_point(spec, group, name): + dist_name, _, _ = spec.partition('==') + matches = ( + entry_point + for entry_point in distribution(dist_name).entry_points + if entry_point.group == group and entry_point.name == name + ) + return next(matches).load() + + +globals().setdefault('load_entry_point', importlib_load_entry_point) + + +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) + sys.exit(load_entry_point('osc-ros2==1.0.0', 'console_scripts', 'interface')()) diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO new file mode 100644 index 0000000..275623c --- /dev/null +++ b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO @@ -0,0 +1,12 @@ +Metadata-Version: 2.1 +Name: osc-ros2 +Version: 1.0.0 +Summary: Creates an interface for communication between OSC and Ros2 +Home-page: UNKNOWN +Maintainer: Alexander Schaefer +Maintainer-email: a.schaefer@tuhh.de +License: Apache-2.0 +Platform: UNKNOWN + +UNKNOWN + diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt new file mode 100644 index 0000000..650a016 --- /dev/null +++ b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt @@ -0,0 +1,16 @@ +package.xml +setup.cfg +setup.py +../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt +../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +../../build/osc_ros2/osc_ros2.egg-info/requires.txt +../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +../../build/osc_ros2/osc_ros2.egg-info/zip-safe +osc_ros2/__init__.py +osc_ros2/osc_ros2.py +resource/osc_ros2 +test/test_copyright.py +test/test_flake8.py +test/test_pep257.py \ No newline at end of file diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt new file mode 100644 index 0000000..008581c --- /dev/null +++ b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt @@ -0,0 +1,3 @@ +[console_scripts] +interface = osc_ros2.osc_ros2:main + diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt new file mode 100644 index 0000000..3c8c415 --- /dev/null +++ b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt @@ -0,0 +1,6 @@ +numpy==1.22.4 +osc4py3 +roboticstoolbox-python +scipy==1.7.3 +setuptools +spatialmath-python diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt new file mode 100644 index 0000000..99ee4eb --- /dev/null +++ b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt @@ -0,0 +1 @@ +osc_ros2 diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe @@ -0,0 +1 @@ + diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..849cee7393dfe4b5b3249ac78afddf80e135fac6 GIT binary patch literal 170 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 self.x_limits[1]) or \ + (self.y_limits[0] is not None and self.y_limits[1] is not None and self.y_limits[0] >= self.y_limits[1]) or \ + (self.z_limits[0] is not None and self.z_limits[1] is not None and self.z_limits[0] >= self.z_limits[1]): + print("Invalid input. Lower limit must be less than upper limit for each axis.") + continue + + print(f"Current limits:") + print(f"x: {self.x_limits}") + print(f"y: {self.y_limits}") + print(f"z: {self.z_limits}") + con = True + while con: + confirm = input("Do you want your TCP to move in this range? (y/n): ").strip().lower() + if confirm == 'y': + break + elif confirm == 'n': + print("Please re-enter the limits.") + con = False + else: + print("Invalid input. Please enter 'y' or 'n'.") + if con: break + except ValueError: + print("Invalid input. Please enter numeric values only.") + break + elif set_limits == 'n': + self.x_limits = [None, None] + self.y_limits = [None, None] + self.z_limits = [None, None] + break + print("Invalid input. Please enter 'y' or 'n'.") + + while True: + print('+-' * 50) + set_limits = input("Do you want to set workspace limits in x, y and z direction? (y/n): ").strip().lower() + if set_limits == 'y': + while True: + try: + self.x_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for x (space-separated, enter 'x' for no limit): ").split()] + self.y_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for y (space-separated, enter 'x' for no limit): ").split()] + self.z_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for z (space-separated, enter 'x' for no limit): ").split()] + + if len(self.x_limits_workspace) != 2 or len(self.y_limits_workspace) != 2 or len(self.z_limits_workspace) != 2: + print("Invalid input. Please enter exactly two values (or leave blank) for each limit.") + continue + + if (self.x_limits_workspace[0] is not None and self.x_limits_workspace[1] is not None and self.x_limits_workspace[0] >= self.x_limits_workspace[1]) or \ + (self.y_limits_workspace[0] is not None and self.y_limits_workspace[1] is not None and self.y_limits_workspace[0] >= self.y_limits_workspace[1]) or \ + (self.z_limits_workspace[0] is not None and self.z_limits_workspace[1] is not None and self.z_limits_workspace[0] >= self.z_limits_workspace[1]): + print("Invalid input. Lower limit must be less than upper limit for each axis.") + continue + + print(f"Current limits:") + print(f"x: {self.x_limits_workspace}") + print(f"y: {self.y_limits_workspace}") + print(f"z: {self.z_limits_workspace}") + con = True + while con: + confirm = input("Do you want your robot to move in this range? (y/n): ").strip().lower() + if confirm == 'y': + break + elif confirm == 'n': + print("Please re-enter the limits.") + con = False + else: + print("Invalid input. Please enter 'y' or 'n'.") + if con: break + except ValueError: + print("Invalid input. Please enter numeric values only.") + break + elif set_limits == 'n': + self.x_limits_workspace = [None, None] + self.y_limits_workspace = [None, None] + self.z_limits_workspace = [None, None] + break + print("Invalid input. Please enter 'y' or 'n'.") + # Ask the user if they want to set new joint limits + + # Ask the user if they want to set new joint limits + while True: + print('+-'*50) + update_limits = input("Do you want to set new joint limits? (y/n): ").strip().lower() + if update_limits == 'y': + for i in range(len(self.joint_names)): + while True: + try: + lim = self.robot.qlim.copy() + # Find the link corresponding to the joint name + print("-" * 50) + print(f"Current position limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") + lower_limit = input(f"Enter the new lower limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() + upper_limit = input(f"Enter the new upper limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() + + if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): + print("Invalid input. Lower limit must be less than upper limit.") + continue + lower_limit = float(lower_limit) if lower_limit!="" else None + upper_limit = float(upper_limit) if upper_limit!="" else None + if lower_limit!=None: + if lower_limitlim[1][i]: + while True: + sure = input(f"Are you sure you want to set the upper limit to {upper_limit} rad which is more than the default limit {lim[1][i]} (y/n)?: ").strip().lower() + if sure == 'y': + lim[1][i] = float(upper_limit) + break + elif sure == 'n': + print("Upper limit not changed.") + break + print("Invalid input. Please enter 'y' or 'n'.") + else: lim[1][i] = float(upper_limit) + self.robot.qlim = lim + print(f"New limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") + print("-" * 50) + break + except ValueError: + print("Invalid input. Please enter numeric values or leave blank to keep current limits.") + break + if update_limits == 'n': + break + print("Invalid input. Please enter 'y' or 'n'.") + ''' + use_link_mask = input("Do you want to use a link mask? (y/n): ").strip().lower() + if use_link_mask == 'y': + while True: + try: + ''' + else: + while True: + print('+-' * 50) + update_limits = input("Do you want to set joint limits? (y/n): ").strip().lower() + if update_limits == 'y': + self.joint_lim = [[None]*self.n_joints,[None]*self.n_joints] + for i, joint in enumerate(self.joint_names): + while True: + try: + print("-" * 50) + lower_limit = input(f"Enter the new lower limit for joint '{joint}' (or press Enter for None): ").strip() + upper_limit = input(f"Enter the new upper limit for joint '{joint}' (or press Enter for None): ").strip() + + if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): + print('--' * 50) + print(" !!! Invalid input. Lower limit must be less than upper limit. !!! ") + continue + self.joint_lim[0][i] = float(lower_limit) if lower_limit!="" else None + self.joint_lim[1][i] = float(upper_limit) if upper_limit!="" else None + break + except ValueError: + print("Invalid input. Please enter numeric values or leave blank to keep current limits.") + print(f'New limits for joint:\n lower: {self.joint_lim[0]}\n upper: {self.joint_lim[1]}') + break + elif update_limits == 'n': + self.joint_lim = None + break + print("Invalid input. Please enter 'y' or 'n'.") + + + + while True: + try: + print('+-' * 50) + self.trajectory_topic_name = input("Enter the topic name to which the joint trajectory should be sent (press Enter for default: '/scaled_joint_trajectory_controller/joint_trajectory'): ").strip() + if self.trajectory_topic_name == "": + self.trajectory_topic_name = '/scaled_joint_trajectory_controller/joint_trajectory' + break + elif self.trajectory_topic_name.startswith("/"): + break + else: + print("Invalid topic name. A valid topic name should start with '/'.") + except Exception as e: + print(f"An error occurred: {e}") + + # ROS2 Publisher + self.publisher = self.create_publisher( + JointTrajectory, + self.trajectory_topic_name, + 1 + ) + + while True: + try: + print('+-' * 50) + log_ip = str(input("Enter the target IP on which you want to recieve the log as OSC Messages (or press Enter for default: '127.0.0.1'): ")) + if log_ip == "": + log_ip = "127.0.0.1" + print('--' * 50) + log_port = input("Enter the target port for the log messages (or press Enter for default: 5005): ") + if log_port == "": + log_port = 5005 + else: + log_port = int(log_port) + break + except ValueError: + print("Invalid input. Please enter a valid IP address.") + continue + while True: + try: + print('+-' * 50) + state_ip = str(input("Enter the target IP on which you want to recieve the joint states as OSC Messages (or press Enter for default: '127.0.0.1'): ")) + if state_ip == "": + state_ip = "127.0.0.1" + print('--' * 50) + state_port = input("Enter the target port for the joint state messages (or press Enter for default: 7000): ") + if state_port == "": + state_port = 7000 + else: + state_port = int(state_port) + break + except ValueError: + print("Invalid input. Please enter a valid IP address.") + continue + while True: + try: + print('+-' * 50) + commands_port = input("Enter the port you want to send your commands to (or press Enter for default: 8000): ") + if commands_port == state_port: + print("The commands port must be different from the state port.") + continue + if commands_port == "": + commands_port = 8000 + else: + commands_port = int(commands_port) + break + except ValueError: + print("Invalid input. Please enter a valid port.") + continue + + + osc_startup() + + osc_udp_client(state_ip, state_port, "osc_client") + + osc_udp_client(log_ip, log_port, "osc_log_client") + + osc_udp_server('0.0.0.0', commands_port, "osc_server") + + # Register OSC handler + osc_method("/joint_positions", self.joint_positions_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/joint_position/*", self.joint_position_handler, argscheme=osm.OSCARG_ADDRESS+osm.OSCARG_DATAUNPACK) + osc_method("/tcp_coordinates", self.tcp_coordinates_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/joint_trajectory", self.joint_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/cartesian_trajectory", self.cartesian_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) + osc_method("/speed_scaling", self.speed_scaling_handler, argscheme=osm.OSCARG_DATAUNPACK) + print('--' * 50) + while True: + try: + print('+-' * 50) + self.hz = input("Enter the desired refresh frequency (Hz) (or press Enter for default: 100): ") + if self.hz == "": + self.hz = 100 + else: + self.hz = float(self.hz) + break + except ValueError: + print("Invalid input. Please enter a valid number.") + continue + print() + print('=-=' * 50) + print() + print(f'Sending joint states to {state_ip}:{state_port}') + print() + print('=-=' * 50) + print() + print(f'Sending log messages to {log_ip}:{log_port}') + print() + print('=-=' * 50) + print() + print(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') + print() + print('=-=' * 50) + print() + + self.get_logger().info(f"Publishing joint trajectory to {self.trajectory_topic_name}") + self.get_logger().info(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') + self.get_logger().info(f'Sending joint states to {state_ip}:{state_port}') + self.get_logger().info(f'Sending log messages to {log_ip}:{log_port}') + self.create_timer(1/self.hz, self.update_position) # Timer to update the position + self.create_timer(3, self.reset_prev) # reset the previous desired position + + def reset_prev(self): self.previous_desired = None + + def speed_scaling_handler(self, *args): + """Handles incoming OSC messages for speed scaling.""" + try: + if len(args) == 1: + if args[0] < 0: + self.speed_scaling = -float(args[0]) + else: + self.speed_scaling = float(args[0]) + if self.speed_scaling > 1: + self.get_logger().warn(f"speed_scaling_handler: Attention! Speed scaling {self.speed_scaling} is greater than 1!") + self.get_logger().info(f"Speed scaling set to {self.speed_scaling}") + else: + self.get_logger().warn(f"Invalid number of arguments for speed scaling. Expected 1, but got {len(args)}.") + except Exception as e: + self.get_logger().fatal(f"speed_scaling_handler: {e}") + + def joint_trajectory_handler(self, *args): + try: + if len(args[0]) == 6: + points = [[float(j) for j in i] for i in args] + elif len(args[0]) >= 7: + points = [[float(j) for j in i[:6]] for i in args] + self.get_logger().warn(f"joint_trajectory_handler: Duration is not supported for joint trajectory yet. Ignoring duration.") + else: + self.get_logger().warn(f"joint_trajectory_handler: Invalid number of arguments for joint trajectory. Expected {self.n_joints} ([q0, q1, q2, ..., q{self.n_joints}]) or {self.n_joints+1} ([q0, q1, q2, ..., q{self.n_joints}, duration]), but got {len(args[0])}.") + return + + self.desired = ["joint_trajectory"] + points + self.new = True + except Exception as e: + self.get_logger().fatal(f"joint_trajectory_handler: {e}") + + def joint_position_handler(self, address, *args): + """Handles incoming OSC messages for joint positions.""" + try: + joint_name = address.split("/")[-1] + + if joint_name in self.joint_names: + if len(args) == 1: + position = float(args[0]) + index = self.joint_names.index(joint_name) + if self.robot: + if position < self.robot.qlim[0][index]: + position = self.robot.qlim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." + ) + elif position > self.robot.qlim[1][index]: + position = self.robot.qlim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." + ) + else: + if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: + position = self.joint_lim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." + ) + elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: + position = self.joint_lim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." + ) + desired_joint_positions = self.current_joint_positions + desired_joint_positions[index] = position + self.desired = ["joint_positions"] + desired_joint_positions + self.new = True + elif len(args) == 2: + position = float(args[0]) + duration = float(args[1]) + index = self.joint_names.index(joint_name) + if self.robot: + if position < self.robot.qlim[0][index]: + position = self.robot.qlim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." + ) + elif position > self.robot.qlim[1][index]: + position = self.robot.qlim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." + ) + else: + if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: + position = self.joint_lim[0][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." + ) + elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: + position = self.joint_lim[1][index] + self.get_logger().warn( + f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." + ) + desired_joint_positions = self.current_joint_positions + desired_joint_positions[index] = position + self.desired = ["joint_positions"] + desired_joint_positions + [duration] + self.new = True + else: + self.get_logger().warn(f"joint_position_handler: Invalid number of arguments for joint position. Expected 1, but got {len(args)}.") + else: + self.get_logger().warn(f"joint_position_handler: Joint '{joint_name}' not found in the robot model.") + except Exception as e: + self.get_logger().fatal(f"joint_position_handler: {e}") + + + def cartesian_trajectory_handler(self, *args): + """Handles incoming OSC messages for cartesian trajectory.""" + if self.robot: + try: + if len(args[0]) == 6: + points = [[float(j) for j in i] for i in args] + elif len(args[0]) >= 7: + points = [[float(j) for j in i[:6]] for i in args] + self.get_logger().warn(f"cartesian_trajectory_handler: Duration is not supported for cartesian trajectory yet. Ignoring duration.") + else: + self.get_logger().warn(f"cartesian_trajectory_handler: Invalid number of arguments for cartesian trajectory. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args[0])}.") + return + + self.desired = ["cartesian_trajectory"] + points + self.new = True + except Exception as e: + self.get_logger().fatal(f"cartesian_trajectory_handler: {e}") + else: + self.get_logger().warn("cartesian_trajectory_handler: No robot model provided. Cannot handle cartesian trajectory.") + return + + def joint_positions_handler(self, *args): + """Handles incoming OSC messages for joint positions.""" + try: + if len(args) == len(self.joint_names): + desired_joint_positions = [float(i) for i in list(args)] + elif len(args) == len(self.joint_names) + 1: + desired_joint_positions = [float(i) for i in list(args)] + else: + self.get_logger().warn(f"joint_positions_handler: Invalid number of arguments for joint positions. Expected {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]) or {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]), but got {len(args)}.") + return + + # Check if joint positions exceed limits + if self.robot: + for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): # Exclude duration if present + if position < self.robot.qlim[0][i]: + desired_joint_positions[i] = self.robot.qlim[0][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[0][i]}." + ) + elif position > self.robot.qlim[1][i]: + desired_joint_positions[i] = self.robot.qlim[1][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[1][i]}." + ) + else: + if self.joint_lim: + for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): + if self.joint_lim[0][i] is not None: + if position < self.joint_lim[0][i]: + desired_joint_positions[i] = self.joint_lim[0][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[0][i]}." + ) + elif self.joint_lim[1][i] is not None: + if position > self.joint_lim[1][i]: + desired_joint_positions[i] = self.joint_lim[1][i] + self.get_logger().warn( + f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[1][i]}." + ) + + self.desired = ["joint_positions"] + desired_joint_positions + self.new = True + except Exception as e: + self.get_logger().fatal(f"joint_positions_handler: {e}") + return + + def tcp_coordinates_handler(self, *args): + # Ensure the desired joint positions are within the specified limits + if self.robot: + try: + if len(args) == 6: + x, y, z, r, p, yaw = [float(i) for i in list(args)] + duration = None + elif len(args) >= 7: + x, y, z, r, p, yaw, duration, *_ = [float(i) for i in list(args)] + else: + self.get_logger().warn(f"tcp_coordinates_handler: Invalid number of arguments for TCP coordinates. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args)}.") + return + + if self.x_limits[0] is not None: + x = max(self.x_limits[0], x) + if self.x_limits[1] is not None: + x = min(self.x_limits[1], x) + if self.y_limits[0] is not None: + y = max(self.y_limits[0], y) + if self.y_limits[1] is not None: + y = min(self.y_limits[1], y) + if self.z_limits[0] is not None: + z = max(self.z_limits[0], z) + if self.z_limits[1] is not None: + z = min(self.z_limits[1], z) + + if x != args[0] or y != args[1] or z != args[2]: + self.get_logger().warn( + f"tcp_coordinates_handler: Desired joint positions adjusted to fit within limits: " + f"x={x}, y={y}, z={z} (original: x={args[0]}, y={args[1]}, z={args[2]})" + ) + + self.desired = ["tcp_coordinates", x, y, z, r, p, yaw, duration] + self.new = True + except Exception as e: + self.get_logger().fatal(f"tcp_coordinates_handler: {e}") + else: + self.get_logger().warn("tcp_coordinates_handler: No robot model provided. Cannot handle TCP coordinates.") + return + + + def joint_states_callback(self, msg: JointState): + """Callback function to handle incoming joint states.""" + try: + msg_time = oscbuildparse.OSCMessage(f"/time", ',s', [str(time.time())]) + osc_send(msg_time, "osc_client") + if not(self.joint_names): self.joint_names = msg.name + joint_position_dict = dict(zip(msg.name, msg.position)) + self.current_joint_positions = [float(joint_position_dict[name]) for name in self.joint_names] + joint_position_dict = dict(zip(msg.name, msg.velocity)) + self.current_joint_velocities = [float(joint_position_dict[name]) for name in self.joint_names] + + if self.robot: + tcp_position = self.robot.fkine(self.current_joint_positions).t + tcp_orientation = self.robot.fkine(self.current_joint_positions).rpy() + + msg_tcp = oscbuildparse.OSCMessage(f"/tcp_coordinates", ',ffffff', [tcp_position[0], tcp_position[1], tcp_position[2], tcp_orientation[0], tcp_orientation[1], tcp_orientation[2]]) + #msg_x = oscbuildparse.OSCMessage(f"/tcp_coordinates/x", ',f', [tcp_position[0]]) + #msg_y = oscbuildparse.OSCMessage(f"/tcp_coordinates/y", ',f', [tcp_position[1]]) + #msg_z = oscbuildparse.OSCMessage(f"/tcp_coordinates/z", ',f', [tcp_position[2]]) + #msg_roll = oscbuildparse.OSCMessage(f"/tcp_coordinates/roll", ',f', [tcp_orientation[0]]) + #msg_pitch = oscbuildparse.OSCMessage(f"/tcp_coordinates/pitch", ',f', [tcp_orientation[1]]) + #msg_yaw = oscbuildparse.OSCMessage(f"/tcp_coordinates/yaw", ',f', [tcp_orientation[2]]) + #bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_tcp, msg_x, msg_y, msg_z, msg_roll, msg_pitch, msg_yaw]) + #osc_send(bun, "osc_client") + osc_send(msg_tcp, "osc_client") + + msg_position = oscbuildparse.OSCMessage(f"/joint_state/position", f',{"f"*self.n_joints}', [i for i in msg.position]) + msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity", f',{"f"*self.n_joints}', [i for i in msg.velocity]) + msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort", f',{"f"*self.n_joints}', [i for i in msg.effort]) + msg_name = oscbuildparse.OSCMessage(f"/joint_state/name", f',{"s"*self.n_joints}', [i for i in msg.name]) + bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_name, msg_position, msg_velocity, msg_effort]) + osc_send(bun, "osc_client") + + #for i, name in enumerate(msg.name): + # msg_position = oscbuildparse.OSCMessage(f"/joint_state/position/{name}", ',f', [msg.position[i]]) + # msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity/{name}", ',f', [msg.velocity[i]]) + # msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort/{name}", ',f', [msg.effort[i]]) + # bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_position, msg_velocity, msg_effort]) + # osc_send(bun, "osc_client") + + except Exception as e: + self.get_logger().fatal(f"joint_states_callback: {e}") + + def send_joint_positions(self): + self.previous_desired = None + self.new = False + try: + if len(self.desired) == len(self.joint_names) + 2: + desired_joint_positions = [float(i) for i in self.desired[1:-1]] + duration = self.desired[-1] + msg = JointTrajectory() + msg.joint_names = self.joint_names + point = JointTrajectoryPoint() + point.positions = desired_joint_positions + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + self.publisher.publish(msg) + elif len(self.desired) == len(self.joint_names) + 1: + desired_joint_positions = [float(i) for i in self.desired[1:]] + msg = JointTrajectory() + msg.joint_names = self.joint_names + point = JointTrajectoryPoint() + point.positions = desired_joint_positions + duration = 0 + for p1, p2, max_vel in zip(desired_joint_positions, self.current_joint_positions, self.joint_velocity_limits.values()): + duration = max(duration, abs(p1 - p2) / max_vel) + duration = duration + min(2, 0.2*duration) + duration /= self.speed_scaling + if duration == 0: + self.get_logger().warn("send_joint_positions: Duration is 0.") + return + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + self.publisher.publish(msg) + else: + self.get_logger().warn(f"send_joint_positions: Invalid number of arguments for joint positions. Expected {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]) or {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]), but got {len(self.desired)}.") + return + except Exception as e: + self.get_logger().fatal(f"send_joint_positions: {e}") + return + + def trapezoidal_timestamps(self, num_points,total_duration, flat_ratio = 0.3): + + if num_points == 2: + return [0, total_duration] + n = int(num_points*(1-flat_ratio)/2) + start = np.cos(np.linspace(0, np.pi, n))+2 + end = np.cos(np.linspace(-np.pi, 0, n))+2 + flat = np.ones(num_points-2*n) + + timestamps = np.concatenate((start, flat, end)) + timestamps *= total_duration / timestamps.sum() + timestamps = np.cumsum(timestamps) + + return timestamps.tolist() + + + def send_tcp_coordinates(self): + """Send the desired TCP coordinates to the robot.""" + try: + self.new = False + msg = JointTrajectory() + msg.joint_names = self.joint_names + steps_per_m = 100 + if self.previous_desired == None: + [x,y,z] = self.robot.fkine(self.current_joint_positions).t + [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() + else: + [x,y,z] = self.previous_desired[1:4] + [roll, pitch, yaw] = self.previous_desired[4:-1] + x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] + self.previous_desired = self.desired + steps = int(np.linalg.norm(np.array([x1, y1, z1])- self.robot.fkine(self.current_joint_positions).t) * steps_per_m) + if steps < 2: steps = 2 + cart_traj = [sm.SE3([x+(x1-x)/(steps-1)*i, y+(y1-y)/(steps-1)*i, z+(z1-z)/(steps-1)*i]) * sm.SE3.RPY([roll+(roll1-roll)/(steps-1)*i, pitch+(pitch1-pitch)/(steps-1)*i, yaw+(yaw1-yaw)/(steps-1)*i]) for i in range(steps)] + '''if self.previous_desired: + [x,y,z] = self.previous_desired[1:4] + q0 = sm.UnitQuaternion.RPY(self.previous_desired[3], self.previous_desired[4], self.previous_desired[5]) + else: + [x, y, z] = self.robot.fkine(self.current_joint_positions).t + q0 = sm.UnitQuaternion(self.robot.fkine(self.current_joint_positions).R) + + x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] + q1 = sm.UnitQuaternion.RPY(roll1, pitch1, yaw1) + + steps = int(np.linalg.norm(np.array([x1, y1, z1]) - self.robot.fkine(self.current_joint_positions).t) * steps_per_m) + if steps < 2: + steps = 2 + + cart_traj = [] + for i in range(steps): + alpha = i / (steps - 1) + + # Convert to arrays for robust interpolation if needed + q0_array = q0.vec + q1_array = q1.vec + dot = np.dot(q0_array, q1_array) + dot = np.clip(dot, -1.0, 1.0) + + if abs(dot) > 0.9995: + # Linear interpolation + normalization + q_interp_array = (1 - alpha) * q0_array + alpha * q1_array + q_interp_array = q_interp_array / np.linalg.norm(q_interp_array) + q_interp = sm.UnitQuaternion(q_interp_array) + else: + q_interp = q0.interp(q1, alpha) + + # Interpolate translation + pos_interp = [ + x + (x1 - x) * alpha, + y + (y1 - y) * alpha, + z + (z1 - z) * alpha + ] + + # Compose SE3 transform + cart_traj.append(sm.SE3(pos_interp) * q_interp.SE3())''' + + + + if self.desired[-1]: + timestamps = self.trapezoidal_timestamps(steps, self.desired[-1], 0.8) + for j in range(steps): + sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') + if sol[1] == 1: + fowards = self.robot.fkine_all(sol[0]) + out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) + if np.any(out_of_bounds): + #print(fowards.t) + #indices = np.where(out_of_bounds)[0] + #print(f"indices: {indices}") + self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") + ''' + for i in indices: + try: + print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") + except IndexError: + print(f"index {i} is out of bounds, but no corresponding joint found.") + self.previous_desired_tcp_position = self.desired_tcp_position + ''' + break + duration = timestamps[j] + if duration == 0: + prev_sol = list(sol[0]) + continue + point = JointTrajectoryPoint() + point.positions = list(sol[0]) + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + prev_sol = list(sol[0]) + else: + self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") + prev_sol = self.current_joint_positions + if len(msg.points) == 0: + self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") + self.previous_desired = self.desired + return + msg.header.stamp = self.get_clock().now().to_msg() + self.publisher.publish(msg) + self.previous_desired = self.desired + + + + else: + prev_duration = 0 + ''' + if self.previous_desired == None: + [x,y,z] = self.robot.fkine(self.current_joint_positions).t + [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() + else: + [x,y,z] = self.previous_desired[:3] + [roll, pitch, yaw] = self.previous_desired[3:] + ''' + for j in range(steps): + sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') + if sol[1] == 1: + fowards = self.robot.fkine_all(sol[0]) + out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) + if np.any(out_of_bounds): + #print(fowards.t) + #indices = np.where(out_of_bounds)[0] + #print(f"indices: {indices}") + self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") + ''' + for i in indices: + try: + print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") + except IndexError: + print(f"index {i} is out of bounds, but no corresponding joint found.") + self.previous_desired_tcp_position = self.desired_tcp_position + ''' + break + duration = 0 + prev = self.current_joint_positions if j == 0 else prev_sol + for p1, p2, max_vel in zip(sol[0], prev, self.joint_velocity_limits.values()): + duration = max(duration, abs(p1 - p2) / max_vel)#, 1/self.hz) # as minimun + prev_sol = list(sol[0]) + if duration == 0: + continue + point = JointTrajectoryPoint() + point.positions = list(sol[0]) + duration *= 1.2 + duration /= self.speed_scaling + duration += prev_duration + prev_duration = duration + point.time_from_start.sec = int(duration) + point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) + msg.points.append(point) + else: + self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") + prev_sol = self.current_joint_positions + if len(msg.points) == 0: + self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") + self.previous_desired = self.desired + return + msg.header.stamp = self.get_clock().now().to_msg() + self.publisher.publish(msg) + self.previous_desired = self.desired + except Exception as e: + self.get_logger().fatal(f"send_tcp_coordinates: {e}") + + def send_joint_trajectory(self): + + try: + self.new = False + viapoints = np.array([i for i in self.desired[1:]]) + msg = JointTrajectory() + msg.joint_names = self.joint_names + traj = rtb.mstraj(viapoints, q0 = self.current_joint_positions ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=[self.speed_scaling*i for i in self.joint_velocity_limits.values()]) + msg.points = [] + for i in range(len(traj.q)): + point = JointTrajectoryPoint() + point.positions = list(traj.q[i]) + point.time_from_start.sec = int(traj.t[i]) + point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) + msg.points.append(point) + msg.header.stamp = self.get_clock().now().to_msg() + self.publisher.publish(msg) + self.previous_desired = None + except Exception as e: + print(f'Error in joint_angles_handler: {e}') + + def send_cartesian_trajectory(self): + + try: + self.new = False + viapoints = np.array([i[:6] for i in self.desired[1:]]) + msg = JointTrajectory() + msg.joint_names = self.joint_names + x,y,z = self.robot.fkine(self.current_joint_positions).t + r,p,yaw = self.robot.fkine(self.current_joint_positions).rpy() + q0 = [x, y, z, r, p, yaw] + traj = rtb.mstraj(viapoints, q0 = q0 ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=2*self.speed_scaling) + msg.points = [] + prev_sol = self.current_joint_positions + n = max(int(len(traj.q)/200), 1) + for i in range(len(traj.q)): + T = sm.SE3(traj.q[i][:3]) * sm.SE3.RPY(traj.q[i][3:], order='xyz') + sol = self.robot.ik_LM(T, q0=prev_sol, mask = self.cost_mask, joint_limits = True) + if sol[1] == 1: + point = JointTrajectoryPoint() + point.positions = list(sol[0]) + point.time_from_start.sec = int(traj.t[i]) + if traj.t[i] == 0: + continue + point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) + msg.points.append(point) + prev_sol = list(sol[0]) + else: self.get_logger().warn(f"send_cartesian_trajectory: IK could not find a solution for (x,y,z) = {traj.q[i][:3]} and (r,p,y) = {traj.q[i][3:]}!") + msg.header.stamp = self.get_clock().now().to_msg() + msg.points = msg.points[::n] + self.publisher.publish(msg) + self.previous_desired = None + except Exception as e: + print(f'Error in joint_angles_handler: {e}') + + self.previous_desired = None + + def update_position(self): + """Calls the appropriate function to update the robot's position.""" + try: + if self.desired is None or not(self.new): + return + + if self.desired[0] == "joint_positions": + self.new = False + self.send_joint_positions() + return + elif self.desired[0] == "tcp_coordinates": + self.new = False + self.send_tcp_coordinates() + return + elif self.desired[0] == "joint_trajectory": + self.new = False + self.send_joint_trajectory() + return + elif self.desired[0] == "cartesian_trajectory": + self.new = False + self.send_cartesian_trajectory() + return + else: + self.get_logger().warn(f"update_position: Unknown desired type '{self.desired[0]}'.") + return + + + except Exception as e: + self.get_logger().fatal(f'update_position: {e}') + + + def clean_log_string(self, s): + + s = str(s) + + # Remove ANSI escape sequences (e.g., \x1b[31m) + ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') + s = ansi_escape.sub('', s) + + # Replace tabs/newlines with spaces + s = s.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ').replace("'", ' '). replace('"', ' ').replace('`', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ') + + # Strip leading/trailing whitespace + s = s.strip() + + # Optionally enforce ASCII only (replace non-ASCII chars with '?') + s = s.encode('ascii', 'replace').decode('ascii') + + return s + + + def log_callback(self, msg: Log): + """Callback function to handle incoming log messages.""" + + # Send the log message as an OSC message + msg_log = oscbuildparse.OSCMessage(f"/log/{self.log_dict.get(msg.level, 'UNKNOWN')}", ',isss', [int(msg.level), str(msg.stamp.sec+msg.stamp.nanosec*1e-9) , str(msg.name), self.clean_log_string(msg.msg)]) + osc_send(msg_log, "osc_log_client") + + +def main(): + """Main function to get joint names and start the ROS 2 & OSC system.""" + rclpy.init() + while True: + use_urdf = input("Do you have a URDF file you want to use? (y/n): ").strip().lower() + if use_urdf == 'y': + while True: + robot_urdf = input("Enter the absolute path to the URDF file: ") + if os.path.isfile(robot_urdf): + if not robot_urdf.endswith('.urdf'): + print("The file is not a URDF file. Please enter a valid URDF file.") + continue + break + else: + print("Invalid path. Please enter a valid path to the URDF file.") + tree = ET.parse(robot_urdf) + root = tree.getroot() + robot = rtb.ERobot.URDF(robot_urdf) + joint_names = [joint.get('name') for joint in root.findall('joint') if joint.get('type') == 'revolute' or joint.get('type') == 'continuous' or joint.get('type') == 'prismatic'] + print(robot) + joint_velocity_limits = {} + + # Iterate over all joints in the URDF + for joint in root.findall('.//joint'): + joint_name = joint.get('name') # Get the name of the joint + + # Look for the tag under each joint + limit = joint.find('limit') + + if limit is not None: + # Extract the velocity limit (if it exists) + velocity_limit = limit.get('velocity') + + if velocity_limit is not None: + joint_velocity_limits[joint_name] = float(velocity_limit) + + while True: + try: + print('-+'*50) + print("The cost mask determines which coordinates are used for the IK.\nEach element of the cost mask corresponds to a Cartesian coordinate [x, y, z, roll, pitch, yaw].") + print("The cost mask 111000 means that the IK will only consider translation and no rotaion.") + cost_mask = [int(i) for i in input(f"Enter the cost mask (6 integers (1 or 0), of which <= {robot.n} are 1): ")] + if sum(cost_mask) <= robot.n and len(cost_mask) == 6: + break + else: + print(f"Invalid input. Expected 6 integers of which {robot.n if robot.n < 6 else 6} or less are 1.") + except ValueError: + print("Invalid input. Please enter integers only.") + print(f"The following coordinates will be used for the IK: {[j for i,j in enumerate(['x','y','z','roll','pitch','yaw']) if cost_mask[i]==1]}") + break + elif use_urdf == 'n': + node = JointNameListener() + print("Wainting 10 sec for JointState messages to extract joint names...") + rclpy.spin_once(node) + counter = 0 + while not(node.joint_names): + if counter > 100: + joint_names = None + break + counter+=1 + time.sleep(0.1) + rclpy.spin_once(node) + joint_names = node.joint_names + node.destroy_node() + if joint_names: + correct_names = input("The following joint names were found:\n" + "\n".join(joint_names) + "\nAre these correct? (y/n): ").strip().lower() + while True: + if correct_names == 'y': + break + elif correct_names == 'n': + joint_names = None + break + correct_names = input("Invalid input. Please enter 'y' or 'n'.") + if not(joint_names): + print("Please enter the joint names manually.") + while True: + joint_names = [] + print('-+'*50) + print("Enter the joint names manually one by one. Type 'done' when you are finished:") + print("Attention: The order of the joints is important. It should be the same in which you want to send the joint positions.") + while True: + print('-'*50) + joint_name = input("Enter joint name (or 'done' to finish): ").strip() + if joint_name.lower() == 'done': + break + if joint_name: + joint_names.append(joint_name) + print('-+'*50) + correct_names = input(f"Are those the joint names as defined in your JointTrajectroy recieving Node?: {joint_names}. (y/n)?: ").strip() + if correct_names.lower() == 'y': + break + else: + print("Please re-enter the joint names.") + while True: + try: + joint_velocity_limits = {} + for name in joint_names: + while True: + try: + print('--'*50) + limit = input(f"Enter the velocity limit for joint '{name}': ").strip() + if limit == "": + continue + else: + joint_velocity_limits[name] = float(limit) + break + except ValueError: + print("Invalid input. Please enter a numeric value or press Enter to skip.") + break + except ValueError: + print("Invalid input. Please enter numeric values or leave blank to skip.") + robot = None + cost_mask = None + break + print("Invalid input. Please enter 'y' or 'n'.") + + + node = OSC_ROS2_interface(joint_names, joint_velocity_limits, robot, cost_mask) + + # Run ROS 2 spin, and osc_process will be handled by the timer + try: + rclpy.spin(node) + except KeyboardInterrupt: + print("") + finally: + node.destroy_node() + osc_terminate() + +if __name__ == '__main__': + main() diff --git a/workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 b/workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 new file mode 100644 index 0000000..e69de29 diff --git a/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 b/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 new file mode 100644 index 0000000..aff3120 --- /dev/null +++ b/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 @@ -0,0 +1 @@ +rclpy \ No newline at end of file diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv new file mode 100644 index 0000000..79d4c95 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv @@ -0,0 +1 @@ +prepend-non-duplicate;AMENT_PREFIX_PATH; diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 new file mode 100644 index 0000000..26b9997 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 @@ -0,0 +1,3 @@ +# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em + +colcon_prepend_unique_value AMENT_PREFIX_PATH "$env:COLCON_CURRENT_PREFIX" diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh new file mode 100644 index 0000000..f3041f6 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh @@ -0,0 +1,3 @@ +# generated from colcon_core/shell/template/hook_prepend_value.sh.em + +_colcon_prepend_unique_value AMENT_PREFIX_PATH "$COLCON_CURRENT_PREFIX" diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv new file mode 100644 index 0000000..257067d --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv @@ -0,0 +1 @@ +prepend-non-duplicate;PYTHONPATH;lib/python3.10/site-packages diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 new file mode 100644 index 0000000..caffe83 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 @@ -0,0 +1,3 @@ +# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em + +colcon_prepend_unique_value PYTHONPATH "$env:COLCON_CURRENT_PREFIX\lib/python3.10/site-packages" diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh new file mode 100644 index 0000000..660c348 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh @@ -0,0 +1,3 @@ +# generated from colcon_core/shell/template/hook_prepend_value.sh.em + +_colcon_prepend_unique_value PYTHONPATH "$COLCON_CURRENT_PREFIX/lib/python3.10/site-packages" diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.bash b/workspace/install/osc_ros2/share/osc_ros2/package.bash new file mode 100644 index 0000000..92f5b25 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/package.bash @@ -0,0 +1,31 @@ +# generated from colcon_bash/shell/template/package.bash.em + +# This script extends the environment for this package. + +# a bash script is able to determine its own path if necessary +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + # the prefix is two levels up from the package specific share directory + _colcon_package_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`/../.." > /dev/null && pwd)" +else + _colcon_package_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +# additional arguments: arguments to the script +_colcon_package_bash_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$@" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source sh script of this package +_colcon_package_bash_source_script "$_colcon_package_bash_COLCON_CURRENT_PREFIX/share/osc_ros2/package.sh" + +unset _colcon_package_bash_source_script +unset _colcon_package_bash_COLCON_CURRENT_PREFIX diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.dsv b/workspace/install/osc_ros2/share/osc_ros2/package.dsv new file mode 100644 index 0000000..ece85b1 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/package.dsv @@ -0,0 +1,6 @@ +source;share/osc_ros2/hook/pythonpath.ps1 +source;share/osc_ros2/hook/pythonpath.dsv +source;share/osc_ros2/hook/pythonpath.sh +source;share/osc_ros2/hook/ament_prefix_path.ps1 +source;share/osc_ros2/hook/ament_prefix_path.dsv +source;share/osc_ros2/hook/ament_prefix_path.sh diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.ps1 b/workspace/install/osc_ros2/share/osc_ros2/package.ps1 new file mode 100644 index 0000000..ed891bc --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/package.ps1 @@ -0,0 +1,116 @@ +# generated from colcon_powershell/shell/template/package.ps1.em + +# function to append a value to a variable +# which uses colons as separators +# duplicates as well as leading separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +function colcon_append_unique_value { + param ( + $_listname, + $_value + ) + + # get values from variable + if (Test-Path Env:$_listname) { + $_values=(Get-Item env:$_listname).Value + } else { + $_values="" + } + $_duplicate="" + # start with no values + $_all_values="" + # iterate over existing values in the variable + if ($_values) { + $_values.Split(";") | ForEach { + # not an empty string + if ($_) { + # not a duplicate of _value + if ($_ -eq $_value) { + $_duplicate="1" + } + if ($_all_values) { + $_all_values="${_all_values};$_" + } else { + $_all_values="$_" + } + } + } + } + # append only non-duplicates + if (!$_duplicate) { + # avoid leading separator + if ($_all_values) { + $_all_values="${_all_values};${_value}" + } else { + $_all_values="${_value}" + } + } + + # export the updated variable + Set-Item env:\$_listname -Value "$_all_values" +} + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +function colcon_prepend_unique_value { + param ( + $_listname, + $_value + ) + + # get values from variable + if (Test-Path Env:$_listname) { + $_values=(Get-Item env:$_listname).Value + } else { + $_values="" + } + # start with the new value + $_all_values="$_value" + # iterate over existing values in the variable + if ($_values) { + $_values.Split(";") | ForEach { + # not an empty string + if ($_) { + # not a duplicate of _value + if ($_ -ne $_value) { + # keep non-duplicate values + $_all_values="${_all_values};$_" + } + } + } + } + # export the updated variable + Set-Item env:\$_listname -Value "$_all_values" +} + +# function to source another script with conditional trace output +# first argument: the path of the script +# additional arguments: arguments to the script +function colcon_package_source_powershell_script { + param ( + $_colcon_package_source_powershell_script + ) + # source script with conditional trace output + if (Test-Path $_colcon_package_source_powershell_script) { + if ($env:COLCON_TRACE) { + echo ". '$_colcon_package_source_powershell_script'" + } + . "$_colcon_package_source_powershell_script" + } else { + Write-Error "not found: '$_colcon_package_source_powershell_script'" + } +} + + +# a powershell script is able to determine its own path +# the prefix is two levels up from the package specific share directory +$env:COLCON_CURRENT_PREFIX=(Get-Item $PSCommandPath).Directory.Parent.Parent.FullName + +colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/osc_ros2/hook/pythonpath.ps1" +colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/osc_ros2/hook/ament_prefix_path.ps1" + +Remove-Item Env:\COLCON_CURRENT_PREFIX diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.sh b/workspace/install/osc_ros2/share/osc_ros2/package.sh new file mode 100644 index 0000000..c4c25c5 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/package.sh @@ -0,0 +1,87 @@ +# generated from colcon_core/shell/template/package.sh.em + +# This script extends the environment for this package. + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +_colcon_prepend_unique_value() { + # arguments + _listname="$1" + _value="$2" + + # get values from variable + eval _values=\"\$$_listname\" + # backup the field separator + _colcon_prepend_unique_value_IFS=$IFS + IFS=":" + # start with the new value + _all_values="$_value" + # workaround SH_WORD_SPLIT not being set in zsh + if [ "$(command -v colcon_zsh_convert_to_array)" ]; then + colcon_zsh_convert_to_array _values + fi + # iterate over existing values in the variable + for _item in $_values; do + # ignore empty strings + if [ -z "$_item" ]; then + continue + fi + # ignore duplicates of _value + if [ "$_item" = "$_value" ]; then + continue + fi + # keep non-duplicate values + _all_values="$_all_values:$_item" + done + unset _item + # restore the field separator + IFS=$_colcon_prepend_unique_value_IFS + unset _colcon_prepend_unique_value_IFS + # export the updated variable + eval export $_listname=\"$_all_values\" + unset _all_values + unset _values + + unset _value + unset _listname +} + +# since a plain shell script can't determine its own path when being sourced +# either use the provided COLCON_CURRENT_PREFIX +# or fall back to the build time prefix (if it exists) +_colcon_package_sh_COLCON_CURRENT_PREFIX="/workspace/install/osc_ros2" +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + if [ ! -d "$_colcon_package_sh_COLCON_CURRENT_PREFIX" ]; then + echo "The build time path \"$_colcon_package_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 + unset _colcon_package_sh_COLCON_CURRENT_PREFIX + return 1 + fi + COLCON_CURRENT_PREFIX="$_colcon_package_sh_COLCON_CURRENT_PREFIX" +fi +unset _colcon_package_sh_COLCON_CURRENT_PREFIX + +# function to source another script with conditional trace output +# first argument: the path of the script +# additional arguments: arguments to the script +_colcon_package_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$@" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source sh hooks +_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/osc_ros2/hook/pythonpath.sh" +_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/osc_ros2/hook/ament_prefix_path.sh" + +unset _colcon_package_sh_source_script +unset COLCON_CURRENT_PREFIX + +# do not unset _colcon_prepend_unique_value since it might be used by non-primary shell hooks diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.xml b/workspace/install/osc_ros2/share/osc_ros2/package.xml new file mode 100644 index 0000000..086e035 --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/package.xml @@ -0,0 +1,20 @@ + + + + osc_ros2 + 1.0.0 + Creates an interface for communication between OSC and ROS2 + Alexander Schaefer + Apache-2.0 + + rclpy + + ament_copyright + ament_flake8 + ament_pep257 + python3-pytest + + + ament_python + + diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.zsh b/workspace/install/osc_ros2/share/osc_ros2/package.zsh new file mode 100644 index 0000000..b8ae59f --- /dev/null +++ b/workspace/install/osc_ros2/share/osc_ros2/package.zsh @@ -0,0 +1,42 @@ +# generated from colcon_zsh/shell/template/package.zsh.em + +# This script extends the environment for this package. + +# a zsh script is able to determine its own path if necessary +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + # the prefix is two levels up from the package specific share directory + _colcon_package_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`/../.." > /dev/null && pwd)" +else + _colcon_package_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +# additional arguments: arguments to the script +_colcon_package_zsh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$@" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# function to convert array-like strings into arrays +# to workaround SH_WORD_SPLIT not being set +colcon_zsh_convert_to_array() { + local _listname=$1 + local _dollar="$" + local _split="{=" + local _to_array="(\"$_dollar$_split$_listname}\")" + eval $_listname=$_to_array +} + +# source sh script of this package +_colcon_package_zsh_source_script "$_colcon_package_zsh_COLCON_CURRENT_PREFIX/share/osc_ros2/package.sh" +unset convert_zsh_to_array + +unset _colcon_package_zsh_source_script +unset _colcon_package_zsh_COLCON_CURRENT_PREFIX diff --git a/workspace/install/setup.bash b/workspace/install/setup.bash new file mode 100644 index 0000000..10ea0f7 --- /dev/null +++ b/workspace/install/setup.bash @@ -0,0 +1,31 @@ +# generated from colcon_bash/shell/template/prefix_chain.bash.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_chain_bash_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source chained prefixes +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="/opt/ros/humble" +_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash" + +# source this prefix +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)" +_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash" + +unset COLCON_CURRENT_PREFIX +unset _colcon_prefix_chain_bash_source_script diff --git a/workspace/install/setup.ps1 b/workspace/install/setup.ps1 new file mode 100644 index 0000000..558e9b9 --- /dev/null +++ b/workspace/install/setup.ps1 @@ -0,0 +1,29 @@ +# generated from colcon_powershell/shell/template/prefix_chain.ps1.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# function to source another script with conditional trace output +# first argument: the path of the script +function _colcon_prefix_chain_powershell_source_script { + param ( + $_colcon_prefix_chain_powershell_source_script_param + ) + # source script with conditional trace output + if (Test-Path $_colcon_prefix_chain_powershell_source_script_param) { + if ($env:COLCON_TRACE) { + echo ". '$_colcon_prefix_chain_powershell_source_script_param'" + } + . "$_colcon_prefix_chain_powershell_source_script_param" + } else { + Write-Error "not found: '$_colcon_prefix_chain_powershell_source_script_param'" + } +} + +# source chained prefixes +_colcon_prefix_chain_powershell_source_script "/opt/ros/humble\local_setup.ps1" + +# source this prefix +$env:COLCON_CURRENT_PREFIX=(Split-Path $PSCommandPath -Parent) +_colcon_prefix_chain_powershell_source_script "$env:COLCON_CURRENT_PREFIX\local_setup.ps1" diff --git a/workspace/install/setup.sh b/workspace/install/setup.sh new file mode 100644 index 0000000..70a84aa --- /dev/null +++ b/workspace/install/setup.sh @@ -0,0 +1,45 @@ +# generated from colcon_core/shell/template/prefix_chain.sh.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# since a plain shell script can't determine its own path when being sourced +# either use the provided COLCON_CURRENT_PREFIX +# or fall back to the build time prefix (if it exists) +_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX=/workspace/install +if [ ! -z "$COLCON_CURRENT_PREFIX" ]; then + _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +elif [ ! -d "$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX" ]; then + echo "The build time path \"$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 + unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX + return 1 +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_chain_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source chained prefixes +# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script +COLCON_CURRENT_PREFIX="/opt/ros/humble" +_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh" + + +# source this prefix +# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script +COLCON_CURRENT_PREFIX="$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX" +_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh" + +unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX +unset _colcon_prefix_chain_sh_source_script +unset COLCON_CURRENT_PREFIX diff --git a/workspace/install/setup.zsh b/workspace/install/setup.zsh new file mode 100644 index 0000000..54799fd --- /dev/null +++ b/workspace/install/setup.zsh @@ -0,0 +1,31 @@ +# generated from colcon_zsh/shell/template/prefix_chain.zsh.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_chain_zsh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source chained prefixes +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="/opt/ros/humble" +_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh" + +# source this prefix +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)" +_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh" + +unset COLCON_CURRENT_PREFIX +unset _colcon_prefix_chain_zsh_source_script diff --git a/workspace/log/COLCON_IGNORE b/workspace/log/COLCON_IGNORE new file mode 100644 index 0000000..e69de29 diff --git a/workspace/log/build_2025-05-28_04-13-20/events.log b/workspace/log/build_2025-05-28_04-13-20/events.log new file mode 100644 index 0000000..90db505 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-13-20/events.log @@ -0,0 +1,46 @@ +[0.000000] (-) TimerEvent: {} +[0.000225] (osc_ros2) JobQueued: {'identifier': 'osc_ros2', 'dependencies': OrderedDict()} +[0.000348] (osc_ros2) JobStarted: {'identifier': 'osc_ros2'} +[0.099483] (-) TimerEvent: {} +[0.199628] (-) TimerEvent: {} +[0.299775] (-) TimerEvent: {} +[0.305620] (osc_ros2) Command: {'cmd': ['/usr/bin/python3', '-W', 'ignore:setup.py install is deprecated', '-W', 'ignore:easy_install command is deprecated', 'setup.py', 'egg_info', '--egg-base', '../../build/osc_ros2', 'build', '--build-base', '/workspace/build/osc_ros2/build', 'install', '--record', '/workspace/build/osc_ros2/install.log', '--single-version-externally-managed', 'install_data'], 'cwd': '/workspace/src/osc_ros2', 'env': {'HOSTNAME': 'ad72f3440b4e', 'SHLVL': '1', 'LD_LIBRARY_PATH': '/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib', 'HOME': '/root', 'OLDPWD': '/', 'ROS_PYTHON_VERSION': '3', 'ROS_DISTRO': 'humble', '_': '/usr/bin/colcon', 'ROS_VERSION': '2', 'TERM': 'xterm', 'ROS_LOCALHOST_ONLY': '0', 'PATH': '/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', 'LANG': 'C.UTF-8', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'AMENT_PREFIX_PATH': '/opt/ros/humble', 'PWD': '/workspace/build/osc_ros2', 'LC_ALL': 'C.UTF-8', 'PYTHONPATH': '/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages', 'COLCON': '1'}, 'shell': False} +[0.399853] (-) TimerEvent: {} +[0.419376] (osc_ros2) StdoutLine: {'line': b'running egg_info\n'} +[0.419581] (osc_ros2) StdoutLine: {'line': b'creating ../../build/osc_ros2/osc_ros2.egg-info\n'} +[0.419665] (osc_ros2) StdoutLine: {'line': b'writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO\n'} +[0.419773] (osc_ros2) StdoutLine: {'line': b'writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt\n'} +[0.419835] (osc_ros2) StdoutLine: {'line': b'writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt\n'} +[0.419888] (osc_ros2) StdoutLine: {'line': b'writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt\n'} +[0.419941] (osc_ros2) StdoutLine: {'line': b'writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt\n'} +[0.420009] (osc_ros2) StdoutLine: {'line': b"writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} +[0.420756] (osc_ros2) StdoutLine: {'line': b"reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} +[0.421180] (osc_ros2) StdoutLine: {'line': b"writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} +[0.421245] (osc_ros2) StdoutLine: {'line': b'running build\n'} +[0.421312] (osc_ros2) StdoutLine: {'line': b'running build_py\n'} +[0.421406] (osc_ros2) StdoutLine: {'line': b'creating /workspace/build/osc_ros2/build\n'} +[0.421504] (osc_ros2) StdoutLine: {'line': b'creating /workspace/build/osc_ros2/build/lib\n'} +[0.421594] (osc_ros2) StdoutLine: {'line': b'creating /workspace/build/osc_ros2/build/lib/osc_ros2\n'} +[0.421645] (osc_ros2) StdoutLine: {'line': b'copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2\n'} +[0.421689] (osc_ros2) StdoutLine: {'line': b'copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2\n'} +[0.421741] (osc_ros2) StdoutLine: {'line': b'running install\n'} +[0.421782] (osc_ros2) StdoutLine: {'line': b'running install_lib\n'} +[0.422031] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2\n'} +[0.422093] (osc_ros2) StdoutLine: {'line': b'copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2\n'} +[0.422151] (osc_ros2) StdoutLine: {'line': b'copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2\n'} +[0.422417] (osc_ros2) StdoutLine: {'line': b'byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc\n'} +[0.422543] (osc_ros2) StdoutLine: {'line': b'byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc\n'} +[0.427108] (osc_ros2) StdoutLine: {'line': b'running install_data\n'} +[0.427204] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/share/ament_index\n'} +[0.427261] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/share/ament_index/resource_index\n'} +[0.427316] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages\n'} +[0.427366] (osc_ros2) StdoutLine: {'line': b'copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages\n'} +[0.427407] (osc_ros2) StdoutLine: {'line': b'copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2\n'} +[0.427447] (osc_ros2) StdoutLine: {'line': b'running install_egg_info\n'} +[0.428124] (osc_ros2) StdoutLine: {'line': b'Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info\n'} +[0.428731] (osc_ros2) StdoutLine: {'line': b'running install_scripts\n'} +[0.438155] (osc_ros2) StdoutLine: {'line': b'Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2\n'} +[0.438306] (osc_ros2) StdoutLine: {'line': b"writing list of installed files to '/workspace/build/osc_ros2/install.log'\n"} +[0.447607] (osc_ros2) CommandEnded: {'returncode': 0} +[0.452862] (osc_ros2) JobEnded: {'identifier': 'osc_ros2', 'rc': 0} +[0.453237] (-) EventReactorShutdown: {} diff --git a/workspace/log/build_2025-05-28_04-13-20/logger_all.log b/workspace/log/build_2025-05-28_04-13-20/logger_all.log new file mode 100644 index 0000000..d49b047 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-13-20/logger_all.log @@ -0,0 +1,126 @@ +[0.070s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build'] +[0.070s] DEBUG:colcon:Parsed command line arguments: Namespace(log_base=None, log_level=None, verb_name='build', build_base='build', install_base='install', merge_install=False, symlink_install=False, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=16, event_handlers=None, ignore_user_meta=False, metas=['./colcon.meta'], base_paths=['.'], packages_ignore=None, packages_ignore_regex=None, paths=None, packages_up_to=None, packages_up_to_regex=None, packages_above=None, packages_above_and_dependencies=None, packages_above_depth=None, packages_select_by_dep=None, packages_skip_by_dep=None, packages_skip_up_to=None, packages_select_build_failed=False, packages_skip_build_finished=False, packages_select_test_failures=False, packages_skip_test_passed=False, packages_select=None, packages_skip=None, packages_select_regex=None, packages_skip_regex=None, packages_start=None, packages_end=None, cmake_args=None, cmake_target=None, cmake_target_skip_unavailable=False, cmake_clean_cache=False, cmake_clean_first=False, cmake_force_configure=False, ament_cmake_args=None, catkin_cmake_args=None, catkin_skip_building_tests=False, mixin_files=None, mixin=None, verb_parser=, verb_extension=, main=>, mixin_verb=('build',)) +[0.150s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters +[0.150s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/Gazebo.meta' +[0.151s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/fastrtps.meta' +[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters +[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters +[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters +[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover +[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover +[0.151s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/workspace' +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install'] +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore' +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install' +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg'] +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg' +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta'] +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta' +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros'] +[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros' +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python'] +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake' +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python' +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py'] +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py' +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install'] +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore' +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install'] +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore' +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install'] +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore' +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored +[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ignore', 'ignore_ament_install'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore_ament_install' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_pkg'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_pkg' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_meta'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_meta' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ros'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ros' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['cmake', 'python'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'cmake' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['python_setup_py'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python_setup_py' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ignore', 'ignore_ament_install'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore_ament_install' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_pkg'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_pkg' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_meta'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_meta' +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ros'] +[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ros' +[0.159s] DEBUG:colcon.colcon_core.package_identification:Package 'src/osc_ros2' with type 'ros.ament_python' and name 'osc_ros2' +[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults +[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover +[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults +[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover +[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_args' from command line to 'None' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target' from command line to 'None' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target_skip_unavailable' from command line to 'False' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_cache' from command line to 'False' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_first' from command line to 'False' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_force_configure' from command line to 'False' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'ament_cmake_args' from command line to 'None' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_cmake_args' from command line to 'None' +[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_skip_building_tests' from command line to 'False' +[0.170s] DEBUG:colcon.colcon_core.verb:Building package 'osc_ros2' with the following arguments: {'ament_cmake_args': None, 'build_base': '/workspace/build/osc_ros2', 'catkin_cmake_args': None, 'catkin_skip_building_tests': False, 'cmake_args': None, 'cmake_clean_cache': False, 'cmake_clean_first': False, 'cmake_force_configure': False, 'cmake_target': None, 'cmake_target_skip_unavailable': False, 'install_base': '/workspace/install/osc_ros2', 'merge_install': False, 'path': '/workspace/src/osc_ros2', 'symlink_install': False, 'test_result_base': None} +[0.170s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor +[0.171s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete +[0.171s] INFO:colcon.colcon_ros.task.ament_python.build:Building ROS package in '/workspace/src/osc_ros2' with build type 'ament_python' +[0.171s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'ament_prefix_path') +[0.172s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems +[0.172s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1' +[0.173s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv' +[0.173s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh' +[0.173s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell +[0.173s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment +[0.299s] INFO:colcon.colcon_core.task.python.build:Building Python package in '/workspace/src/osc_ros2' +[0.299s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell +[0.299s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment +[0.477s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +[0.618s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake module files +[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake config files +[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib' +[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' +[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/pkgconfig/osc_ros2.pc' +[0.621s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/python3.10/site-packages' +[0.621s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'pythonpath') +[0.621s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1' +[0.621s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv' +[0.621s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh' +[0.621s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' +[0.621s] Level 1:colcon.colcon_core.environment:create_environment_scripts_only(osc_ros2) +[0.622s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.ps1' +[0.622s] INFO:colcon.colcon_core.shell:Creating package descriptor '/workspace/install/osc_ros2/share/osc_ros2/package.dsv' +[0.622s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.sh' +[0.623s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.bash' +[0.623s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.zsh' +[0.623s] Level 1:colcon.colcon_core.environment:create_file_with_runtime_dependencies(/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2) +[0.624s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop +[0.624s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed +[0.624s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0' +[0.624s] DEBUG:colcon.colcon_core.event_reactor:joining thread +[0.628s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.notify_send': Could not find 'notify-send' +[0.628s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems +[0.628s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems +[0.628s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2' +[0.628s] DEBUG:colcon.colcon_notification.desktop_notification.notify2:Failed to initialize notify2: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11 +[0.628s] DEBUG:colcon.colcon_core.event_reactor:joined thread +[0.628s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.ps1' +[0.629s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_ps1.py' +[0.629s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.ps1' +[0.630s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.sh' +[0.630s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_sh.py' +[0.630s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.sh' +[0.631s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.bash' +[0.631s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.bash' +[0.632s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.zsh' +[0.632s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.zsh' diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log new file mode 100644 index 0000000..d2728af --- /dev/null +++ b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log @@ -0,0 +1,2 @@ +Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stderr.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stderr.log new file mode 100644 index 0000000..e69de29 diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log new file mode 100644 index 0000000..5f28670 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log @@ -0,0 +1,35 @@ +running egg_info +creating ../../build/osc_ros2/osc_ros2.egg-info +writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt +writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +running build +running build_py +creating /workspace/build/osc_ros2/build +creating /workspace/build/osc_ros2/build/lib +creating /workspace/build/osc_ros2/build/lib/osc_ros2 +copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 +copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 +running install +running install_lib +creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc +byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc +running install_data +creating /workspace/install/osc_ros2/share/ament_index +creating /workspace/install/osc_ros2/share/ament_index/resource_index +creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages +copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages +copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2 +running install_egg_info +Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info +running install_scripts +Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 +writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log new file mode 100644 index 0000000..5f28670 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log @@ -0,0 +1,35 @@ +running egg_info +creating ../../build/osc_ros2/osc_ros2.egg-info +writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt +writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +running build +running build_py +creating /workspace/build/osc_ros2/build +creating /workspace/build/osc_ros2/build/lib +creating /workspace/build/osc_ros2/build/lib/osc_ros2 +copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 +copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 +running install +running install_lib +creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc +byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc +running install_data +creating /workspace/install/osc_ros2/share/ament_index +creating /workspace/install/osc_ros2/share/ament_index/resource_index +creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages +copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages +copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2 +running install_egg_info +Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info +running install_scripts +Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 +writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log new file mode 100644 index 0000000..45d9ff9 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log @@ -0,0 +1,37 @@ +[0.306s] Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +[0.419s] running egg_info +[0.419s] creating ../../build/osc_ros2/osc_ros2.egg-info +[0.419s] writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +[0.419s] writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +[0.420s] writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +[0.420s] writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt +[0.420s] writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +[0.420s] writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +[0.420s] reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +[0.421s] writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +[0.421s] running build +[0.421s] running build_py +[0.421s] creating /workspace/build/osc_ros2/build +[0.421s] creating /workspace/build/osc_ros2/build/lib +[0.421s] creating /workspace/build/osc_ros2/build/lib/osc_ros2 +[0.421s] copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 +[0.421s] copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 +[0.421s] running install +[0.421s] running install_lib +[0.422s] creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +[0.422s] copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +[0.422s] copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 +[0.422s] byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc +[0.422s] byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc +[0.427s] running install_data +[0.427s] creating /workspace/install/osc_ros2/share/ament_index +[0.427s] creating /workspace/install/osc_ros2/share/ament_index/resource_index +[0.427s] creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages +[0.427s] copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages +[0.427s] copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2 +[0.427s] running install_egg_info +[0.428s] Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info +[0.428s] running install_scripts +[0.438s] Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 +[0.438s] writing list of installed files to '/workspace/build/osc_ros2/install.log' +[0.447s] Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/build_2025-05-28_04-16-52/events.log b/workspace/log/build_2025-05-28_04-16-52/events.log new file mode 100644 index 0000000..0498981 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-16-52/events.log @@ -0,0 +1,30 @@ +[0.000000] (-) TimerEvent: {} +[0.000210] (osc_ros2) JobQueued: {'identifier': 'osc_ros2', 'dependencies': OrderedDict()} +[0.000283] (osc_ros2) JobStarted: {'identifier': 'osc_ros2'} +[0.099571] (-) TimerEvent: {} +[0.199703] (-) TimerEvent: {} +[0.299829] (-) TimerEvent: {} +[0.305183] (osc_ros2) Command: {'cmd': ['/usr/bin/python3', '-W', 'ignore:setup.py install is deprecated', '-W', 'ignore:easy_install command is deprecated', 'setup.py', 'egg_info', '--egg-base', '../../build/osc_ros2', 'build', '--build-base', '/workspace/build/osc_ros2/build', 'install', '--record', '/workspace/build/osc_ros2/install.log', '--single-version-externally-managed', 'install_data'], 'cwd': '/workspace/src/osc_ros2', 'env': {'HOSTNAME': 'ad72f3440b4e', 'SHLVL': '1', 'LD_LIBRARY_PATH': '/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib', 'HOME': '/root', 'OLDPWD': '/', 'ROS_PYTHON_VERSION': '3', 'COLCON_PREFIX_PATH': '/workspace/install', 'ROS_DISTRO': 'humble', '_': '/usr/bin/colcon', 'ROS_VERSION': '2', 'TERM': 'xterm', 'ROS_LOCALHOST_ONLY': '0', 'PATH': '/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', 'LANG': 'C.UTF-8', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'AMENT_PREFIX_PATH': '/workspace/install/osc_ros2:/opt/ros/humble', 'PWD': '/workspace/build/osc_ros2', 'LC_ALL': 'C.UTF-8', 'PYTHONPATH': '/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:/workspace/install/osc_ros2/lib/python3.10/site-packages:/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages', 'COLCON': '1'}, 'shell': False} +[0.399896] (-) TimerEvent: {} +[0.423494] (osc_ros2) StdoutLine: {'line': b'running egg_info\n'} +[0.423758] (osc_ros2) StdoutLine: {'line': b'writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO\n'} +[0.423871] (osc_ros2) StdoutLine: {'line': b'writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt\n'} +[0.423940] (osc_ros2) StdoutLine: {'line': b'writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt\n'} +[0.423995] (osc_ros2) StdoutLine: {'line': b'writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt\n'} +[0.424050] (osc_ros2) StdoutLine: {'line': b'writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt\n'} +[0.424816] (osc_ros2) StdoutLine: {'line': b"reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} +[0.425191] (osc_ros2) StdoutLine: {'line': b"writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} +[0.425256] (osc_ros2) StdoutLine: {'line': b'running build\n'} +[0.425303] (osc_ros2) StdoutLine: {'line': b'running build_py\n'} +[0.425468] (osc_ros2) StdoutLine: {'line': b'running install\n'} +[0.425604] (osc_ros2) StdoutLine: {'line': b'running install_lib\n'} +[0.426145] (osc_ros2) StdoutLine: {'line': b'running install_data\n'} +[0.426206] (osc_ros2) StdoutLine: {'line': b'running install_egg_info\n'} +[0.427040] (osc_ros2) StdoutLine: {'line': b"removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it)\n"} +[0.427275] (osc_ros2) StdoutLine: {'line': b'Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info\n'} +[0.427875] (osc_ros2) StdoutLine: {'line': b'running install_scripts\n'} +[0.437908] (osc_ros2) StdoutLine: {'line': b'Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2\n'} +[0.438055] (osc_ros2) StdoutLine: {'line': b"writing list of installed files to '/workspace/build/osc_ros2/install.log'\n"} +[0.447364] (osc_ros2) CommandEnded: {'returncode': 0} +[0.452905] (osc_ros2) JobEnded: {'identifier': 'osc_ros2', 'rc': 0} +[0.453236] (-) EventReactorShutdown: {} diff --git a/workspace/log/build_2025-05-28_04-16-52/logger_all.log b/workspace/log/build_2025-05-28_04-16-52/logger_all.log new file mode 100644 index 0000000..25c5e99 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-16-52/logger_all.log @@ -0,0 +1,126 @@ +[0.061s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build'] +[0.061s] DEBUG:colcon:Parsed command line arguments: Namespace(log_base=None, log_level=None, verb_name='build', build_base='build', install_base='install', merge_install=False, symlink_install=False, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=16, event_handlers=None, ignore_user_meta=False, metas=['./colcon.meta'], base_paths=['.'], packages_ignore=None, packages_ignore_regex=None, paths=None, packages_up_to=None, packages_up_to_regex=None, packages_above=None, packages_above_and_dependencies=None, packages_above_depth=None, packages_select_by_dep=None, packages_skip_by_dep=None, packages_skip_up_to=None, packages_select_build_failed=False, packages_skip_build_finished=False, packages_select_test_failures=False, packages_skip_test_passed=False, packages_select=None, packages_skip=None, packages_select_regex=None, packages_skip_regex=None, packages_start=None, packages_end=None, cmake_args=None, cmake_target=None, cmake_target_skip_unavailable=False, cmake_clean_cache=False, cmake_clean_first=False, cmake_force_configure=False, ament_cmake_args=None, catkin_cmake_args=None, catkin_skip_building_tests=False, mixin_files=None, mixin=None, verb_parser=, verb_extension=, main=>, mixin_verb=('build',)) +[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters +[0.138s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/Gazebo.meta' +[0.138s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/fastrtps.meta' +[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters +[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters +[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters +[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover +[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover +[0.138s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/workspace' +[0.138s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install'] +[0.138s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore' +[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install' +[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg'] +[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg' +[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta'] +[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta' +[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros'] +[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ignore', 'ignore_ament_install'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore_ament_install' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_pkg'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_pkg' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_meta'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_meta' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ros'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ros' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['cmake', 'python'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'cmake' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['python_setup_py'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python_setup_py' +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ignore', 'ignore_ament_install'] +[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore' +[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore_ament_install' +[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_pkg'] +[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_pkg' +[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_meta'] +[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_meta' +[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ros'] +[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ros' +[0.147s] DEBUG:colcon.colcon_core.package_identification:Package 'src/osc_ros2' with type 'ros.ament_python' and name 'osc_ros2' +[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults +[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover +[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults +[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover +[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_args' from command line to 'None' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target' from command line to 'None' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target_skip_unavailable' from command line to 'False' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_cache' from command line to 'False' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_first' from command line to 'False' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_force_configure' from command line to 'False' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'ament_cmake_args' from command line to 'None' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_cmake_args' from command line to 'None' +[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_skip_building_tests' from command line to 'False' +[0.157s] DEBUG:colcon.colcon_core.verb:Building package 'osc_ros2' with the following arguments: {'ament_cmake_args': None, 'build_base': '/workspace/build/osc_ros2', 'catkin_cmake_args': None, 'catkin_skip_building_tests': False, 'cmake_args': None, 'cmake_clean_cache': False, 'cmake_clean_first': False, 'cmake_force_configure': False, 'cmake_target': None, 'cmake_target_skip_unavailable': False, 'install_base': '/workspace/install/osc_ros2', 'merge_install': False, 'path': '/workspace/src/osc_ros2', 'symlink_install': False, 'test_result_base': None} +[0.157s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor +[0.158s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete +[0.158s] INFO:colcon.colcon_ros.task.ament_python.build:Building ROS package in '/workspace/src/osc_ros2' with build type 'ament_python' +[0.158s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'ament_prefix_path') +[0.160s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems +[0.160s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1' +[0.160s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv' +[0.160s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh' +[0.161s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell +[0.161s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment +[0.288s] INFO:colcon.colcon_core.task.python.build:Building Python package in '/workspace/src/osc_ros2' +[0.288s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell +[0.288s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment +[0.465s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +[0.605s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +[0.607s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake module files +[0.607s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake config files +[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib' +[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' +[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/pkgconfig/osc_ros2.pc' +[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/python3.10/site-packages' +[0.608s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'pythonpath') +[0.608s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1' +[0.608s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv' +[0.608s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh' +[0.609s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' +[0.609s] Level 1:colcon.colcon_core.environment:create_environment_scripts_only(osc_ros2) +[0.609s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.ps1' +[0.609s] INFO:colcon.colcon_core.shell:Creating package descriptor '/workspace/install/osc_ros2/share/osc_ros2/package.dsv' +[0.610s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.sh' +[0.610s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.bash' +[0.610s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.zsh' +[0.611s] Level 1:colcon.colcon_core.environment:create_file_with_runtime_dependencies(/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2) +[0.611s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop +[0.611s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed +[0.611s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0' +[0.611s] DEBUG:colcon.colcon_core.event_reactor:joining thread +[0.614s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.notify_send': Could not find 'notify-send' +[0.614s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems +[0.614s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems +[0.614s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2' +[0.614s] DEBUG:colcon.colcon_notification.desktop_notification.notify2:Failed to initialize notify2: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11 +[0.614s] DEBUG:colcon.colcon_core.event_reactor:joined thread +[0.615s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.ps1' +[0.615s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_ps1.py' +[0.616s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.ps1' +[0.617s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.sh' +[0.617s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_sh.py' +[0.617s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.sh' +[0.618s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.bash' +[0.618s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.bash' +[0.619s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.zsh' +[0.619s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.zsh' diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log new file mode 100644 index 0000000..d2728af --- /dev/null +++ b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log @@ -0,0 +1,2 @@ +Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stderr.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stderr.log new file mode 100644 index 0000000..e69de29 diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log new file mode 100644 index 0000000..c53ed50 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log @@ -0,0 +1,19 @@ +running egg_info +writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt +writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +running build +running build_py +running install +running install_lib +running install_data +running install_egg_info +removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it) +Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info +running install_scripts +Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 +writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log new file mode 100644 index 0000000..c53ed50 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log @@ -0,0 +1,19 @@ +running egg_info +writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt +writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +running build +running build_py +running install +running install_lib +running install_data +running install_egg_info +removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it) +Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info +running install_scripts +Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 +writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log new file mode 100644 index 0000000..68e1362 --- /dev/null +++ b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log @@ -0,0 +1,21 @@ +[0.306s] Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data +[0.423s] running egg_info +[0.423s] writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO +[0.424s] writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +[0.424s] writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt +[0.424s] writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt +[0.424s] writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt +[0.425s] reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +[0.425s] writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' +[0.425s] running build +[0.425s] running build_py +[0.425s] running install +[0.425s] running install_lib +[0.426s] running install_data +[0.426s] running install_egg_info +[0.427s] removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it) +[0.427s] Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info +[0.428s] running install_scripts +[0.438s] Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 +[0.438s] writing list of installed files to '/workspace/build/osc_ros2/install.log' +[0.447s] Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/latest b/workspace/log/latest new file mode 120000 index 0000000..b57d247 --- /dev/null +++ b/workspace/log/latest @@ -0,0 +1 @@ +latest_build \ No newline at end of file diff --git a/workspace/log/latest_build b/workspace/log/latest_build new file mode 120000 index 0000000..77bb7f9 --- /dev/null +++ b/workspace/log/latest_build @@ -0,0 +1 @@ +build_2025-05-28_04-16-52 \ No newline at end of file diff --git a/workspace/src/osc_ros2/setup.py b/workspace/src/osc_ros2/setup.py index 1e398fb..ae08f66 100644 --- a/workspace/src/osc_ros2/setup.py +++ b/workspace/src/osc_ros2/setup.py @@ -14,10 +14,10 @@ setup( install_requires=[ 'setuptools', 'osc4py3', - 'roboticstoolbox-python==1.1.1', + 'roboticstoolbox-python', 'numpy==1.22.4', 'scipy==1.7.3', - 'spatialmath-python==1.1.14'], + 'spatialmath-python'], zip_safe=True, maintainer='Alexander Schaefer', maintainer_email='a.schaefer@tuhh.de', From 2d5b63d7e55e6c27affd9dc457e58de41b3ac3c0 Mon Sep 17 00:00:00 2001 From: Ali Date: Wed, 28 May 2025 06:23:20 +0200 Subject: [PATCH 03/22] [AN] (fix) clean workspace --- workspace/.gitignore | 6 + workspace/build/.built_by | 1 - workspace/build/COLCON_IGNORE | 0 .../osc_ros2/build/lib/osc_ros2/__init__.py | 0 .../osc_ros2/build/lib/osc_ros2/osc_ros2.py | 1099 ----------------- workspace/build/osc_ros2/colcon_build.rc | 1 - .../colcon_command_prefix_setup_py.sh | 1 - .../colcon_command_prefix_setup_py.sh.env | 20 - workspace/build/osc_ros2/install.log | 14 - .../build/osc_ros2/osc_ros2.egg-info/PKG-INFO | 12 - .../osc_ros2/osc_ros2.egg-info/SOURCES.txt | 16 - .../osc_ros2.egg-info/dependency_links.txt | 1 - .../osc_ros2.egg-info/entry_points.txt | 3 - .../osc_ros2/osc_ros2.egg-info/requires.txt | 6 - .../osc_ros2/osc_ros2.egg-info/top_level.txt | 1 - .../build/osc_ros2/osc_ros2.egg-info/zip-safe | 1 - .../__pycache__/sitecustomize.cpython-310.pyc | Bin 277 -> 0 bytes .../osc_ros2/prefix_override/sitecustomize.py | 4 - workspace/install/.colcon_install_layout | 1 - workspace/install/COLCON_IGNORE | 0 workspace/install/_local_setup_util_ps1.py | 407 ------ workspace/install/_local_setup_util_sh.py | 407 ------ workspace/install/local_setup.bash | 121 -- workspace/install/local_setup.ps1 | 55 - workspace/install/local_setup.sh | 137 -- workspace/install/local_setup.zsh | 134 -- .../install/osc_ros2/lib/osc_ros2/interface | 33 - .../osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO | 12 - .../SOURCES.txt | 16 - .../dependency_links.txt | 1 - .../entry_points.txt | 3 - .../requires.txt | 6 - .../top_level.txt | 1 - .../osc_ros2-1.0.0-py3.10.egg-info/zip-safe | 1 - .../site-packages/osc_ros2/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 170 -> 0 bytes .../__pycache__/osc_ros2.cpython-310.pyc | Bin 34258 -> 0 bytes .../site-packages/osc_ros2/osc_ros2.py | 1099 ----------------- .../resource_index/packages/osc_ros2 | 0 .../share/colcon-core/packages/osc_ros2 | 1 - .../share/osc_ros2/hook/ament_prefix_path.dsv | 1 - .../share/osc_ros2/hook/ament_prefix_path.ps1 | 3 - .../share/osc_ros2/hook/ament_prefix_path.sh | 3 - .../share/osc_ros2/hook/pythonpath.dsv | 1 - .../share/osc_ros2/hook/pythonpath.ps1 | 3 - .../share/osc_ros2/hook/pythonpath.sh | 3 - .../osc_ros2/share/osc_ros2/package.bash | 31 - .../osc_ros2/share/osc_ros2/package.dsv | 6 - .../osc_ros2/share/osc_ros2/package.ps1 | 116 -- .../osc_ros2/share/osc_ros2/package.sh | 87 -- .../osc_ros2/share/osc_ros2/package.xml | 20 - .../osc_ros2/share/osc_ros2/package.zsh | 42 - workspace/install/setup.bash | 31 - workspace/install/setup.ps1 | 29 - workspace/install/setup.sh | 45 - workspace/install/setup.zsh | 31 - workspace/log/COLCON_IGNORE | 0 .../log/build_2025-05-28_04-13-20/events.log | 46 - .../build_2025-05-28_04-13-20/logger_all.log | 126 -- .../osc_ros2/command.log | 2 - .../osc_ros2/stderr.log | 0 .../osc_ros2/stdout.log | 35 - .../osc_ros2/stdout_stderr.log | 35 - .../osc_ros2/streams.log | 37 - .../log/build_2025-05-28_04-16-52/events.log | 30 - .../build_2025-05-28_04-16-52/logger_all.log | 126 -- .../osc_ros2/command.log | 2 - .../osc_ros2/stderr.log | 0 .../osc_ros2/stdout.log | 19 - .../osc_ros2/stdout_stderr.log | 19 - .../osc_ros2/streams.log | 21 - workspace/log/latest | 1 - workspace/log/latest_build | 1 - 73 files changed, 6 insertions(+), 4567 deletions(-) create mode 100644 workspace/.gitignore delete mode 100644 workspace/build/.built_by delete mode 100644 workspace/build/COLCON_IGNORE delete mode 100644 workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py delete mode 100644 workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py delete mode 100644 workspace/build/osc_ros2/colcon_build.rc delete mode 100644 workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh delete mode 100644 workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env delete mode 100644 workspace/build/osc_ros2/install.log delete mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO delete mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt delete mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt delete mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt delete mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt delete mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt delete mode 100644 workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe delete mode 100644 workspace/build/osc_ros2/prefix_override/__pycache__/sitecustomize.cpython-310.pyc delete mode 100644 workspace/build/osc_ros2/prefix_override/sitecustomize.py delete mode 100644 workspace/install/.colcon_install_layout delete mode 100644 workspace/install/COLCON_IGNORE delete mode 100644 workspace/install/_local_setup_util_ps1.py delete mode 100644 workspace/install/_local_setup_util_sh.py delete mode 100644 workspace/install/local_setup.bash delete mode 100644 workspace/install/local_setup.ps1 delete mode 100644 workspace/install/local_setup.sh delete mode 100644 workspace/install/local_setup.zsh delete mode 100755 workspace/install/osc_ros2/lib/osc_ros2/interface delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/osc_ros2.cpython-310.pyc delete mode 100644 workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py delete mode 100644 workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 delete mode 100644 workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.bash delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.dsv delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.ps1 delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.sh delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.xml delete mode 100644 workspace/install/osc_ros2/share/osc_ros2/package.zsh delete mode 100644 workspace/install/setup.bash delete mode 100644 workspace/install/setup.ps1 delete mode 100644 workspace/install/setup.sh delete mode 100644 workspace/install/setup.zsh delete mode 100644 workspace/log/COLCON_IGNORE delete mode 100644 workspace/log/build_2025-05-28_04-13-20/events.log delete mode 100644 workspace/log/build_2025-05-28_04-13-20/logger_all.log delete mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log delete mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/stderr.log delete mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log delete mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log delete mode 100644 workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log delete mode 100644 workspace/log/build_2025-05-28_04-16-52/events.log delete mode 100644 workspace/log/build_2025-05-28_04-16-52/logger_all.log delete mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log delete mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/stderr.log delete mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log delete mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log delete mode 100644 workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log delete mode 120000 workspace/log/latest delete mode 120000 workspace/log/latest_build diff --git a/workspace/.gitignore b/workspace/.gitignore new file mode 100644 index 0000000..f93cda8 --- /dev/null +++ b/workspace/.gitignore @@ -0,0 +1,6 @@ +build/* +build/** +install/* +install/** +log/* +log/** diff --git a/workspace/build/.built_by b/workspace/build/.built_by deleted file mode 100644 index 06e74ac..0000000 --- a/workspace/build/.built_by +++ /dev/null @@ -1 +0,0 @@ -colcon diff --git a/workspace/build/COLCON_IGNORE b/workspace/build/COLCON_IGNORE deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py b/workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py b/workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py deleted file mode 100644 index 0b28d5b..0000000 --- a/workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py +++ /dev/null @@ -1,1099 +0,0 @@ -import rclpy -from rclpy.node import Node -from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint -from sensor_msgs.msg import JointState -from rcl_interfaces.msg import Log -from osc4py3.as_allthreads import * -from osc4py3 import oscmethod as osm -import xml.etree.ElementTree as ET -import numpy as np -import spatialmath as sm -import roboticstoolbox as rtb -from osc4py3 import oscbuildparse -import time -import os -import re -import socket - -class JointNameListener(Node): - def __init__(self): - super().__init__('joint_name_listener') - self.subscription = self.create_subscription( - JointState, - '/joint_states', - self.joint_state_callback, - 1 - ) - self.joint_names = None - - def joint_state_callback(self, msg: JointState): - self.joint_names = list(msg.name) - -class OSC_ROS2_interface(Node): - """Node to publish joint trajectories based on OSC messages.""" - - def __init__(self, joint_names, joint_velocity_limits, robot, cost_mask): - super().__init__('scaled_joint_trajectory_publisher') - - - self.subscription = self.create_subscription( - JointState, - '/joint_states', - self.joint_states_callback, - 1 - ) - - self.subscription = self.create_subscription( - Log, - '/rosout', - self.log_callback, - 100 - ) - - # Store received joint positions - self.current_joint_positions = None - self.joint_names = joint_names - self.joint_velocity_limits = joint_velocity_limits - self.cost_mask = cost_mask - self.robot = robot - self.desired = None - self.previous_desired = None - self.log_dict = { - 10: "DEBUG", - 20: "INFO", - 30: "WARN", - 40: "ERROR", - 50: "FATAL", - } - self.speed_scaling = 0.2 - self.new = False - self.n_joints = len(joint_names) - - if robot: - while True: - print('+-' * 50) - set_limits = input("Do you want to set limits for x, y and z? (y/n): ").strip().lower() - if set_limits == 'y': - while True: - try: - self.x_limits = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for x (space-separated, enter 'x' for no limit): ").split()] - self.y_limits = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for y (space-separated, enter 'x' for no limit): ").split()] - self.z_limits = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for z (space-separated, enter 'x' for no limit): ").split()] - - if len(self.x_limits) != 2 or len(self.y_limits) != 2 or len(self.z_limits) != 2: - print("Invalid input. Please enter exactly two values (or leave blank) for each limit.") - continue - - if (self.x_limits[0] is not None and self.x_limits[1] is not None and self.x_limits[0] >= self.x_limits[1]) or \ - (self.y_limits[0] is not None and self.y_limits[1] is not None and self.y_limits[0] >= self.y_limits[1]) or \ - (self.z_limits[0] is not None and self.z_limits[1] is not None and self.z_limits[0] >= self.z_limits[1]): - print("Invalid input. Lower limit must be less than upper limit for each axis.") - continue - - print(f"Current limits:") - print(f"x: {self.x_limits}") - print(f"y: {self.y_limits}") - print(f"z: {self.z_limits}") - con = True - while con: - confirm = input("Do you want your TCP to move in this range? (y/n): ").strip().lower() - if confirm == 'y': - break - elif confirm == 'n': - print("Please re-enter the limits.") - con = False - else: - print("Invalid input. Please enter 'y' or 'n'.") - if con: break - except ValueError: - print("Invalid input. Please enter numeric values only.") - break - elif set_limits == 'n': - self.x_limits = [None, None] - self.y_limits = [None, None] - self.z_limits = [None, None] - break - print("Invalid input. Please enter 'y' or 'n'.") - - while True: - print('+-' * 50) - set_limits = input("Do you want to set workspace limits in x, y and z direction? (y/n): ").strip().lower() - if set_limits == 'y': - while True: - try: - self.x_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for x (space-separated, enter 'x' for no limit): ").split()] - self.y_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for y (space-separated, enter 'x' for no limit): ").split()] - self.z_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for z (space-separated, enter 'x' for no limit): ").split()] - - if len(self.x_limits_workspace) != 2 or len(self.y_limits_workspace) != 2 or len(self.z_limits_workspace) != 2: - print("Invalid input. Please enter exactly two values (or leave blank) for each limit.") - continue - - if (self.x_limits_workspace[0] is not None and self.x_limits_workspace[1] is not None and self.x_limits_workspace[0] >= self.x_limits_workspace[1]) or \ - (self.y_limits_workspace[0] is not None and self.y_limits_workspace[1] is not None and self.y_limits_workspace[0] >= self.y_limits_workspace[1]) or \ - (self.z_limits_workspace[0] is not None and self.z_limits_workspace[1] is not None and self.z_limits_workspace[0] >= self.z_limits_workspace[1]): - print("Invalid input. Lower limit must be less than upper limit for each axis.") - continue - - print(f"Current limits:") - print(f"x: {self.x_limits_workspace}") - print(f"y: {self.y_limits_workspace}") - print(f"z: {self.z_limits_workspace}") - con = True - while con: - confirm = input("Do you want your robot to move in this range? (y/n): ").strip().lower() - if confirm == 'y': - break - elif confirm == 'n': - print("Please re-enter the limits.") - con = False - else: - print("Invalid input. Please enter 'y' or 'n'.") - if con: break - except ValueError: - print("Invalid input. Please enter numeric values only.") - break - elif set_limits == 'n': - self.x_limits_workspace = [None, None] - self.y_limits_workspace = [None, None] - self.z_limits_workspace = [None, None] - break - print("Invalid input. Please enter 'y' or 'n'.") - # Ask the user if they want to set new joint limits - - # Ask the user if they want to set new joint limits - while True: - print('+-'*50) - update_limits = input("Do you want to set new joint limits? (y/n): ").strip().lower() - if update_limits == 'y': - for i in range(len(self.joint_names)): - while True: - try: - lim = self.robot.qlim.copy() - # Find the link corresponding to the joint name - print("-" * 50) - print(f"Current position limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") - lower_limit = input(f"Enter the new lower limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() - upper_limit = input(f"Enter the new upper limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() - - if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): - print("Invalid input. Lower limit must be less than upper limit.") - continue - lower_limit = float(lower_limit) if lower_limit!="" else None - upper_limit = float(upper_limit) if upper_limit!="" else None - if lower_limit!=None: - if lower_limitlim[1][i]: - while True: - sure = input(f"Are you sure you want to set the upper limit to {upper_limit} rad which is more than the default limit {lim[1][i]} (y/n)?: ").strip().lower() - if sure == 'y': - lim[1][i] = float(upper_limit) - break - elif sure == 'n': - print("Upper limit not changed.") - break - print("Invalid input. Please enter 'y' or 'n'.") - else: lim[1][i] = float(upper_limit) - self.robot.qlim = lim - print(f"New limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") - print("-" * 50) - break - except ValueError: - print("Invalid input. Please enter numeric values or leave blank to keep current limits.") - break - if update_limits == 'n': - break - print("Invalid input. Please enter 'y' or 'n'.") - ''' - use_link_mask = input("Do you want to use a link mask? (y/n): ").strip().lower() - if use_link_mask == 'y': - while True: - try: - ''' - else: - while True: - print('+-' * 50) - update_limits = input("Do you want to set joint limits? (y/n): ").strip().lower() - if update_limits == 'y': - self.joint_lim = [[None]*self.n_joints,[None]*self.n_joints] - for i, joint in enumerate(self.joint_names): - while True: - try: - print("-" * 50) - lower_limit = input(f"Enter the new lower limit for joint '{joint}' (or press Enter for None): ").strip() - upper_limit = input(f"Enter the new upper limit for joint '{joint}' (or press Enter for None): ").strip() - - if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): - print('--' * 50) - print(" !!! Invalid input. Lower limit must be less than upper limit. !!! ") - continue - self.joint_lim[0][i] = float(lower_limit) if lower_limit!="" else None - self.joint_lim[1][i] = float(upper_limit) if upper_limit!="" else None - break - except ValueError: - print("Invalid input. Please enter numeric values or leave blank to keep current limits.") - print(f'New limits for joint:\n lower: {self.joint_lim[0]}\n upper: {self.joint_lim[1]}') - break - elif update_limits == 'n': - self.joint_lim = None - break - print("Invalid input. Please enter 'y' or 'n'.") - - - - while True: - try: - print('+-' * 50) - self.trajectory_topic_name = input("Enter the topic name to which the joint trajectory should be sent (press Enter for default: '/scaled_joint_trajectory_controller/joint_trajectory'): ").strip() - if self.trajectory_topic_name == "": - self.trajectory_topic_name = '/scaled_joint_trajectory_controller/joint_trajectory' - break - elif self.trajectory_topic_name.startswith("/"): - break - else: - print("Invalid topic name. A valid topic name should start with '/'.") - except Exception as e: - print(f"An error occurred: {e}") - - # ROS2 Publisher - self.publisher = self.create_publisher( - JointTrajectory, - self.trajectory_topic_name, - 1 - ) - - while True: - try: - print('+-' * 50) - log_ip = str(input("Enter the target IP on which you want to recieve the log as OSC Messages (or press Enter for default: '127.0.0.1'): ")) - if log_ip == "": - log_ip = "127.0.0.1" - print('--' * 50) - log_port = input("Enter the target port for the log messages (or press Enter for default: 5005): ") - if log_port == "": - log_port = 5005 - else: - log_port = int(log_port) - break - except ValueError: - print("Invalid input. Please enter a valid IP address.") - continue - while True: - try: - print('+-' * 50) - state_ip = str(input("Enter the target IP on which you want to recieve the joint states as OSC Messages (or press Enter for default: '127.0.0.1'): ")) - if state_ip == "": - state_ip = "127.0.0.1" - print('--' * 50) - state_port = input("Enter the target port for the joint state messages (or press Enter for default: 7000): ") - if state_port == "": - state_port = 7000 - else: - state_port = int(state_port) - break - except ValueError: - print("Invalid input. Please enter a valid IP address.") - continue - while True: - try: - print('+-' * 50) - commands_port = input("Enter the port you want to send your commands to (or press Enter for default: 8000): ") - if commands_port == state_port: - print("The commands port must be different from the state port.") - continue - if commands_port == "": - commands_port = 8000 - else: - commands_port = int(commands_port) - break - except ValueError: - print("Invalid input. Please enter a valid port.") - continue - - - osc_startup() - - osc_udp_client(state_ip, state_port, "osc_client") - - osc_udp_client(log_ip, log_port, "osc_log_client") - - osc_udp_server('0.0.0.0', commands_port, "osc_server") - - # Register OSC handler - osc_method("/joint_positions", self.joint_positions_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/joint_position/*", self.joint_position_handler, argscheme=osm.OSCARG_ADDRESS+osm.OSCARG_DATAUNPACK) - osc_method("/tcp_coordinates", self.tcp_coordinates_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/joint_trajectory", self.joint_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/cartesian_trajectory", self.cartesian_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/speed_scaling", self.speed_scaling_handler, argscheme=osm.OSCARG_DATAUNPACK) - print('--' * 50) - while True: - try: - print('+-' * 50) - self.hz = input("Enter the desired refresh frequency (Hz) (or press Enter for default: 100): ") - if self.hz == "": - self.hz = 100 - else: - self.hz = float(self.hz) - break - except ValueError: - print("Invalid input. Please enter a valid number.") - continue - print() - print('=-=' * 50) - print() - print(f'Sending joint states to {state_ip}:{state_port}') - print() - print('=-=' * 50) - print() - print(f'Sending log messages to {log_ip}:{log_port}') - print() - print('=-=' * 50) - print() - print(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') - print() - print('=-=' * 50) - print() - - self.get_logger().info(f"Publishing joint trajectory to {self.trajectory_topic_name}") - self.get_logger().info(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') - self.get_logger().info(f'Sending joint states to {state_ip}:{state_port}') - self.get_logger().info(f'Sending log messages to {log_ip}:{log_port}') - self.create_timer(1/self.hz, self.update_position) # Timer to update the position - self.create_timer(3, self.reset_prev) # reset the previous desired position - - def reset_prev(self): self.previous_desired = None - - def speed_scaling_handler(self, *args): - """Handles incoming OSC messages for speed scaling.""" - try: - if len(args) == 1: - if args[0] < 0: - self.speed_scaling = -float(args[0]) - else: - self.speed_scaling = float(args[0]) - if self.speed_scaling > 1: - self.get_logger().warn(f"speed_scaling_handler: Attention! Speed scaling {self.speed_scaling} is greater than 1!") - self.get_logger().info(f"Speed scaling set to {self.speed_scaling}") - else: - self.get_logger().warn(f"Invalid number of arguments for speed scaling. Expected 1, but got {len(args)}.") - except Exception as e: - self.get_logger().fatal(f"speed_scaling_handler: {e}") - - def joint_trajectory_handler(self, *args): - try: - if len(args[0]) == 6: - points = [[float(j) for j in i] for i in args] - elif len(args[0]) >= 7: - points = [[float(j) for j in i[:6]] for i in args] - self.get_logger().warn(f"joint_trajectory_handler: Duration is not supported for joint trajectory yet. Ignoring duration.") - else: - self.get_logger().warn(f"joint_trajectory_handler: Invalid number of arguments for joint trajectory. Expected {self.n_joints} ([q0, q1, q2, ..., q{self.n_joints}]) or {self.n_joints+1} ([q0, q1, q2, ..., q{self.n_joints}, duration]), but got {len(args[0])}.") - return - - self.desired = ["joint_trajectory"] + points - self.new = True - except Exception as e: - self.get_logger().fatal(f"joint_trajectory_handler: {e}") - - def joint_position_handler(self, address, *args): - """Handles incoming OSC messages for joint positions.""" - try: - joint_name = address.split("/")[-1] - - if joint_name in self.joint_names: - if len(args) == 1: - position = float(args[0]) - index = self.joint_names.index(joint_name) - if self.robot: - if position < self.robot.qlim[0][index]: - position = self.robot.qlim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." - ) - elif position > self.robot.qlim[1][index]: - position = self.robot.qlim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." - ) - else: - if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: - position = self.joint_lim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." - ) - elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: - position = self.joint_lim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." - ) - desired_joint_positions = self.current_joint_positions - desired_joint_positions[index] = position - self.desired = ["joint_positions"] + desired_joint_positions - self.new = True - elif len(args) == 2: - position = float(args[0]) - duration = float(args[1]) - index = self.joint_names.index(joint_name) - if self.robot: - if position < self.robot.qlim[0][index]: - position = self.robot.qlim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." - ) - elif position > self.robot.qlim[1][index]: - position = self.robot.qlim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." - ) - else: - if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: - position = self.joint_lim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." - ) - elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: - position = self.joint_lim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." - ) - desired_joint_positions = self.current_joint_positions - desired_joint_positions[index] = position - self.desired = ["joint_positions"] + desired_joint_positions + [duration] - self.new = True - else: - self.get_logger().warn(f"joint_position_handler: Invalid number of arguments for joint position. Expected 1, but got {len(args)}.") - else: - self.get_logger().warn(f"joint_position_handler: Joint '{joint_name}' not found in the robot model.") - except Exception as e: - self.get_logger().fatal(f"joint_position_handler: {e}") - - - def cartesian_trajectory_handler(self, *args): - """Handles incoming OSC messages for cartesian trajectory.""" - if self.robot: - try: - if len(args[0]) == 6: - points = [[float(j) for j in i] for i in args] - elif len(args[0]) >= 7: - points = [[float(j) for j in i[:6]] for i in args] - self.get_logger().warn(f"cartesian_trajectory_handler: Duration is not supported for cartesian trajectory yet. Ignoring duration.") - else: - self.get_logger().warn(f"cartesian_trajectory_handler: Invalid number of arguments for cartesian trajectory. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args[0])}.") - return - - self.desired = ["cartesian_trajectory"] + points - self.new = True - except Exception as e: - self.get_logger().fatal(f"cartesian_trajectory_handler: {e}") - else: - self.get_logger().warn("cartesian_trajectory_handler: No robot model provided. Cannot handle cartesian trajectory.") - return - - def joint_positions_handler(self, *args): - """Handles incoming OSC messages for joint positions.""" - try: - if len(args) == len(self.joint_names): - desired_joint_positions = [float(i) for i in list(args)] - elif len(args) == len(self.joint_names) + 1: - desired_joint_positions = [float(i) for i in list(args)] - else: - self.get_logger().warn(f"joint_positions_handler: Invalid number of arguments for joint positions. Expected {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]) or {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]), but got {len(args)}.") - return - - # Check if joint positions exceed limits - if self.robot: - for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): # Exclude duration if present - if position < self.robot.qlim[0][i]: - desired_joint_positions[i] = self.robot.qlim[0][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[0][i]}." - ) - elif position > self.robot.qlim[1][i]: - desired_joint_positions[i] = self.robot.qlim[1][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[1][i]}." - ) - else: - if self.joint_lim: - for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): - if self.joint_lim[0][i] is not None: - if position < self.joint_lim[0][i]: - desired_joint_positions[i] = self.joint_lim[0][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[0][i]}." - ) - elif self.joint_lim[1][i] is not None: - if position > self.joint_lim[1][i]: - desired_joint_positions[i] = self.joint_lim[1][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[1][i]}." - ) - - self.desired = ["joint_positions"] + desired_joint_positions - self.new = True - except Exception as e: - self.get_logger().fatal(f"joint_positions_handler: {e}") - return - - def tcp_coordinates_handler(self, *args): - # Ensure the desired joint positions are within the specified limits - if self.robot: - try: - if len(args) == 6: - x, y, z, r, p, yaw = [float(i) for i in list(args)] - duration = None - elif len(args) >= 7: - x, y, z, r, p, yaw, duration, *_ = [float(i) for i in list(args)] - else: - self.get_logger().warn(f"tcp_coordinates_handler: Invalid number of arguments for TCP coordinates. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args)}.") - return - - if self.x_limits[0] is not None: - x = max(self.x_limits[0], x) - if self.x_limits[1] is not None: - x = min(self.x_limits[1], x) - if self.y_limits[0] is not None: - y = max(self.y_limits[0], y) - if self.y_limits[1] is not None: - y = min(self.y_limits[1], y) - if self.z_limits[0] is not None: - z = max(self.z_limits[0], z) - if self.z_limits[1] is not None: - z = min(self.z_limits[1], z) - - if x != args[0] or y != args[1] or z != args[2]: - self.get_logger().warn( - f"tcp_coordinates_handler: Desired joint positions adjusted to fit within limits: " - f"x={x}, y={y}, z={z} (original: x={args[0]}, y={args[1]}, z={args[2]})" - ) - - self.desired = ["tcp_coordinates", x, y, z, r, p, yaw, duration] - self.new = True - except Exception as e: - self.get_logger().fatal(f"tcp_coordinates_handler: {e}") - else: - self.get_logger().warn("tcp_coordinates_handler: No robot model provided. Cannot handle TCP coordinates.") - return - - - def joint_states_callback(self, msg: JointState): - """Callback function to handle incoming joint states.""" - try: - msg_time = oscbuildparse.OSCMessage(f"/time", ',s', [str(time.time())]) - osc_send(msg_time, "osc_client") - if not(self.joint_names): self.joint_names = msg.name - joint_position_dict = dict(zip(msg.name, msg.position)) - self.current_joint_positions = [float(joint_position_dict[name]) for name in self.joint_names] - joint_position_dict = dict(zip(msg.name, msg.velocity)) - self.current_joint_velocities = [float(joint_position_dict[name]) for name in self.joint_names] - - if self.robot: - tcp_position = self.robot.fkine(self.current_joint_positions).t - tcp_orientation = self.robot.fkine(self.current_joint_positions).rpy() - - msg_tcp = oscbuildparse.OSCMessage(f"/tcp_coordinates", ',ffffff', [tcp_position[0], tcp_position[1], tcp_position[2], tcp_orientation[0], tcp_orientation[1], tcp_orientation[2]]) - #msg_x = oscbuildparse.OSCMessage(f"/tcp_coordinates/x", ',f', [tcp_position[0]]) - #msg_y = oscbuildparse.OSCMessage(f"/tcp_coordinates/y", ',f', [tcp_position[1]]) - #msg_z = oscbuildparse.OSCMessage(f"/tcp_coordinates/z", ',f', [tcp_position[2]]) - #msg_roll = oscbuildparse.OSCMessage(f"/tcp_coordinates/roll", ',f', [tcp_orientation[0]]) - #msg_pitch = oscbuildparse.OSCMessage(f"/tcp_coordinates/pitch", ',f', [tcp_orientation[1]]) - #msg_yaw = oscbuildparse.OSCMessage(f"/tcp_coordinates/yaw", ',f', [tcp_orientation[2]]) - #bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_tcp, msg_x, msg_y, msg_z, msg_roll, msg_pitch, msg_yaw]) - #osc_send(bun, "osc_client") - osc_send(msg_tcp, "osc_client") - - msg_position = oscbuildparse.OSCMessage(f"/joint_state/position", f',{"f"*self.n_joints}', [i for i in msg.position]) - msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity", f',{"f"*self.n_joints}', [i for i in msg.velocity]) - msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort", f',{"f"*self.n_joints}', [i for i in msg.effort]) - msg_name = oscbuildparse.OSCMessage(f"/joint_state/name", f',{"s"*self.n_joints}', [i for i in msg.name]) - bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_name, msg_position, msg_velocity, msg_effort]) - osc_send(bun, "osc_client") - - #for i, name in enumerate(msg.name): - # msg_position = oscbuildparse.OSCMessage(f"/joint_state/position/{name}", ',f', [msg.position[i]]) - # msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity/{name}", ',f', [msg.velocity[i]]) - # msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort/{name}", ',f', [msg.effort[i]]) - # bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_position, msg_velocity, msg_effort]) - # osc_send(bun, "osc_client") - - except Exception as e: - self.get_logger().fatal(f"joint_states_callback: {e}") - - def send_joint_positions(self): - self.previous_desired = None - self.new = False - try: - if len(self.desired) == len(self.joint_names) + 2: - desired_joint_positions = [float(i) for i in self.desired[1:-1]] - duration = self.desired[-1] - msg = JointTrajectory() - msg.joint_names = self.joint_names - point = JointTrajectoryPoint() - point.positions = desired_joint_positions - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - self.publisher.publish(msg) - elif len(self.desired) == len(self.joint_names) + 1: - desired_joint_positions = [float(i) for i in self.desired[1:]] - msg = JointTrajectory() - msg.joint_names = self.joint_names - point = JointTrajectoryPoint() - point.positions = desired_joint_positions - duration = 0 - for p1, p2, max_vel in zip(desired_joint_positions, self.current_joint_positions, self.joint_velocity_limits.values()): - duration = max(duration, abs(p1 - p2) / max_vel) - duration = duration + min(2, 0.2*duration) - duration /= self.speed_scaling - if duration == 0: - self.get_logger().warn("send_joint_positions: Duration is 0.") - return - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - self.publisher.publish(msg) - else: - self.get_logger().warn(f"send_joint_positions: Invalid number of arguments for joint positions. Expected {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]) or {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]), but got {len(self.desired)}.") - return - except Exception as e: - self.get_logger().fatal(f"send_joint_positions: {e}") - return - - def trapezoidal_timestamps(self, num_points,total_duration, flat_ratio = 0.3): - - if num_points == 2: - return [0, total_duration] - n = int(num_points*(1-flat_ratio)/2) - start = np.cos(np.linspace(0, np.pi, n))+2 - end = np.cos(np.linspace(-np.pi, 0, n))+2 - flat = np.ones(num_points-2*n) - - timestamps = np.concatenate((start, flat, end)) - timestamps *= total_duration / timestamps.sum() - timestamps = np.cumsum(timestamps) - - return timestamps.tolist() - - - def send_tcp_coordinates(self): - """Send the desired TCP coordinates to the robot.""" - try: - self.new = False - msg = JointTrajectory() - msg.joint_names = self.joint_names - steps_per_m = 100 - if self.previous_desired == None: - [x,y,z] = self.robot.fkine(self.current_joint_positions).t - [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() - else: - [x,y,z] = self.previous_desired[1:4] - [roll, pitch, yaw] = self.previous_desired[4:-1] - x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] - self.previous_desired = self.desired - steps = int(np.linalg.norm(np.array([x1, y1, z1])- self.robot.fkine(self.current_joint_positions).t) * steps_per_m) - if steps < 2: steps = 2 - cart_traj = [sm.SE3([x+(x1-x)/(steps-1)*i, y+(y1-y)/(steps-1)*i, z+(z1-z)/(steps-1)*i]) * sm.SE3.RPY([roll+(roll1-roll)/(steps-1)*i, pitch+(pitch1-pitch)/(steps-1)*i, yaw+(yaw1-yaw)/(steps-1)*i]) for i in range(steps)] - '''if self.previous_desired: - [x,y,z] = self.previous_desired[1:4] - q0 = sm.UnitQuaternion.RPY(self.previous_desired[3], self.previous_desired[4], self.previous_desired[5]) - else: - [x, y, z] = self.robot.fkine(self.current_joint_positions).t - q0 = sm.UnitQuaternion(self.robot.fkine(self.current_joint_positions).R) - - x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] - q1 = sm.UnitQuaternion.RPY(roll1, pitch1, yaw1) - - steps = int(np.linalg.norm(np.array([x1, y1, z1]) - self.robot.fkine(self.current_joint_positions).t) * steps_per_m) - if steps < 2: - steps = 2 - - cart_traj = [] - for i in range(steps): - alpha = i / (steps - 1) - - # Convert to arrays for robust interpolation if needed - q0_array = q0.vec - q1_array = q1.vec - dot = np.dot(q0_array, q1_array) - dot = np.clip(dot, -1.0, 1.0) - - if abs(dot) > 0.9995: - # Linear interpolation + normalization - q_interp_array = (1 - alpha) * q0_array + alpha * q1_array - q_interp_array = q_interp_array / np.linalg.norm(q_interp_array) - q_interp = sm.UnitQuaternion(q_interp_array) - else: - q_interp = q0.interp(q1, alpha) - - # Interpolate translation - pos_interp = [ - x + (x1 - x) * alpha, - y + (y1 - y) * alpha, - z + (z1 - z) * alpha - ] - - # Compose SE3 transform - cart_traj.append(sm.SE3(pos_interp) * q_interp.SE3())''' - - - - if self.desired[-1]: - timestamps = self.trapezoidal_timestamps(steps, self.desired[-1], 0.8) - for j in range(steps): - sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') - if sol[1] == 1: - fowards = self.robot.fkine_all(sol[0]) - out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) - if np.any(out_of_bounds): - #print(fowards.t) - #indices = np.where(out_of_bounds)[0] - #print(f"indices: {indices}") - self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") - ''' - for i in indices: - try: - print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") - except IndexError: - print(f"index {i} is out of bounds, but no corresponding joint found.") - self.previous_desired_tcp_position = self.desired_tcp_position - ''' - break - duration = timestamps[j] - if duration == 0: - prev_sol = list(sol[0]) - continue - point = JointTrajectoryPoint() - point.positions = list(sol[0]) - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - prev_sol = list(sol[0]) - else: - self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") - prev_sol = self.current_joint_positions - if len(msg.points) == 0: - self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") - self.previous_desired = self.desired - return - msg.header.stamp = self.get_clock().now().to_msg() - self.publisher.publish(msg) - self.previous_desired = self.desired - - - - else: - prev_duration = 0 - ''' - if self.previous_desired == None: - [x,y,z] = self.robot.fkine(self.current_joint_positions).t - [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() - else: - [x,y,z] = self.previous_desired[:3] - [roll, pitch, yaw] = self.previous_desired[3:] - ''' - for j in range(steps): - sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') - if sol[1] == 1: - fowards = self.robot.fkine_all(sol[0]) - out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) - if np.any(out_of_bounds): - #print(fowards.t) - #indices = np.where(out_of_bounds)[0] - #print(f"indices: {indices}") - self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") - ''' - for i in indices: - try: - print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") - except IndexError: - print(f"index {i} is out of bounds, but no corresponding joint found.") - self.previous_desired_tcp_position = self.desired_tcp_position - ''' - break - duration = 0 - prev = self.current_joint_positions if j == 0 else prev_sol - for p1, p2, max_vel in zip(sol[0], prev, self.joint_velocity_limits.values()): - duration = max(duration, abs(p1 - p2) / max_vel)#, 1/self.hz) # as minimun - prev_sol = list(sol[0]) - if duration == 0: - continue - point = JointTrajectoryPoint() - point.positions = list(sol[0]) - duration *= 1.2 - duration /= self.speed_scaling - duration += prev_duration - prev_duration = duration - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - else: - self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") - prev_sol = self.current_joint_positions - if len(msg.points) == 0: - self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") - self.previous_desired = self.desired - return - msg.header.stamp = self.get_clock().now().to_msg() - self.publisher.publish(msg) - self.previous_desired = self.desired - except Exception as e: - self.get_logger().fatal(f"send_tcp_coordinates: {e}") - - def send_joint_trajectory(self): - - try: - self.new = False - viapoints = np.array([i for i in self.desired[1:]]) - msg = JointTrajectory() - msg.joint_names = self.joint_names - traj = rtb.mstraj(viapoints, q0 = self.current_joint_positions ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=[self.speed_scaling*i for i in self.joint_velocity_limits.values()]) - msg.points = [] - for i in range(len(traj.q)): - point = JointTrajectoryPoint() - point.positions = list(traj.q[i]) - point.time_from_start.sec = int(traj.t[i]) - point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) - msg.points.append(point) - msg.header.stamp = self.get_clock().now().to_msg() - self.publisher.publish(msg) - self.previous_desired = None - except Exception as e: - print(f'Error in joint_angles_handler: {e}') - - def send_cartesian_trajectory(self): - - try: - self.new = False - viapoints = np.array([i[:6] for i in self.desired[1:]]) - msg = JointTrajectory() - msg.joint_names = self.joint_names - x,y,z = self.robot.fkine(self.current_joint_positions).t - r,p,yaw = self.robot.fkine(self.current_joint_positions).rpy() - q0 = [x, y, z, r, p, yaw] - traj = rtb.mstraj(viapoints, q0 = q0 ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=2*self.speed_scaling) - msg.points = [] - prev_sol = self.current_joint_positions - n = max(int(len(traj.q)/200), 1) - for i in range(len(traj.q)): - T = sm.SE3(traj.q[i][:3]) * sm.SE3.RPY(traj.q[i][3:], order='xyz') - sol = self.robot.ik_LM(T, q0=prev_sol, mask = self.cost_mask, joint_limits = True) - if sol[1] == 1: - point = JointTrajectoryPoint() - point.positions = list(sol[0]) - point.time_from_start.sec = int(traj.t[i]) - if traj.t[i] == 0: - continue - point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) - msg.points.append(point) - prev_sol = list(sol[0]) - else: self.get_logger().warn(f"send_cartesian_trajectory: IK could not find a solution for (x,y,z) = {traj.q[i][:3]} and (r,p,y) = {traj.q[i][3:]}!") - msg.header.stamp = self.get_clock().now().to_msg() - msg.points = msg.points[::n] - self.publisher.publish(msg) - self.previous_desired = None - except Exception as e: - print(f'Error in joint_angles_handler: {e}') - - self.previous_desired = None - - def update_position(self): - """Calls the appropriate function to update the robot's position.""" - try: - if self.desired is None or not(self.new): - return - - if self.desired[0] == "joint_positions": - self.new = False - self.send_joint_positions() - return - elif self.desired[0] == "tcp_coordinates": - self.new = False - self.send_tcp_coordinates() - return - elif self.desired[0] == "joint_trajectory": - self.new = False - self.send_joint_trajectory() - return - elif self.desired[0] == "cartesian_trajectory": - self.new = False - self.send_cartesian_trajectory() - return - else: - self.get_logger().warn(f"update_position: Unknown desired type '{self.desired[0]}'.") - return - - - except Exception as e: - self.get_logger().fatal(f'update_position: {e}') - - - def clean_log_string(self, s): - - s = str(s) - - # Remove ANSI escape sequences (e.g., \x1b[31m) - ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') - s = ansi_escape.sub('', s) - - # Replace tabs/newlines with spaces - s = s.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ').replace("'", ' '). replace('"', ' ').replace('`', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ') - - # Strip leading/trailing whitespace - s = s.strip() - - # Optionally enforce ASCII only (replace non-ASCII chars with '?') - s = s.encode('ascii', 'replace').decode('ascii') - - return s - - - def log_callback(self, msg: Log): - """Callback function to handle incoming log messages.""" - - # Send the log message as an OSC message - msg_log = oscbuildparse.OSCMessage(f"/log/{self.log_dict.get(msg.level, 'UNKNOWN')}", ',isss', [int(msg.level), str(msg.stamp.sec+msg.stamp.nanosec*1e-9) , str(msg.name), self.clean_log_string(msg.msg)]) - osc_send(msg_log, "osc_log_client") - - -def main(): - """Main function to get joint names and start the ROS 2 & OSC system.""" - rclpy.init() - while True: - use_urdf = input("Do you have a URDF file you want to use? (y/n): ").strip().lower() - if use_urdf == 'y': - while True: - robot_urdf = input("Enter the absolute path to the URDF file: ") - if os.path.isfile(robot_urdf): - if not robot_urdf.endswith('.urdf'): - print("The file is not a URDF file. Please enter a valid URDF file.") - continue - break - else: - print("Invalid path. Please enter a valid path to the URDF file.") - tree = ET.parse(robot_urdf) - root = tree.getroot() - robot = rtb.ERobot.URDF(robot_urdf) - joint_names = [joint.get('name') for joint in root.findall('joint') if joint.get('type') == 'revolute' or joint.get('type') == 'continuous' or joint.get('type') == 'prismatic'] - print(robot) - joint_velocity_limits = {} - - # Iterate over all joints in the URDF - for joint in root.findall('.//joint'): - joint_name = joint.get('name') # Get the name of the joint - - # Look for the tag under each joint - limit = joint.find('limit') - - if limit is not None: - # Extract the velocity limit (if it exists) - velocity_limit = limit.get('velocity') - - if velocity_limit is not None: - joint_velocity_limits[joint_name] = float(velocity_limit) - - while True: - try: - print('-+'*50) - print("The cost mask determines which coordinates are used for the IK.\nEach element of the cost mask corresponds to a Cartesian coordinate [x, y, z, roll, pitch, yaw].") - print("The cost mask 111000 means that the IK will only consider translation and no rotaion.") - cost_mask = [int(i) for i in input(f"Enter the cost mask (6 integers (1 or 0), of which <= {robot.n} are 1): ")] - if sum(cost_mask) <= robot.n and len(cost_mask) == 6: - break - else: - print(f"Invalid input. Expected 6 integers of which {robot.n if robot.n < 6 else 6} or less are 1.") - except ValueError: - print("Invalid input. Please enter integers only.") - print(f"The following coordinates will be used for the IK: {[j for i,j in enumerate(['x','y','z','roll','pitch','yaw']) if cost_mask[i]==1]}") - break - elif use_urdf == 'n': - node = JointNameListener() - print("Wainting 10 sec for JointState messages to extract joint names...") - rclpy.spin_once(node) - counter = 0 - while not(node.joint_names): - if counter > 100: - joint_names = None - break - counter+=1 - time.sleep(0.1) - rclpy.spin_once(node) - joint_names = node.joint_names - node.destroy_node() - if joint_names: - correct_names = input("The following joint names were found:\n" + "\n".join(joint_names) + "\nAre these correct? (y/n): ").strip().lower() - while True: - if correct_names == 'y': - break - elif correct_names == 'n': - joint_names = None - break - correct_names = input("Invalid input. Please enter 'y' or 'n'.") - if not(joint_names): - print("Please enter the joint names manually.") - while True: - joint_names = [] - print('-+'*50) - print("Enter the joint names manually one by one. Type 'done' when you are finished:") - print("Attention: The order of the joints is important. It should be the same in which you want to send the joint positions.") - while True: - print('-'*50) - joint_name = input("Enter joint name (or 'done' to finish): ").strip() - if joint_name.lower() == 'done': - break - if joint_name: - joint_names.append(joint_name) - print('-+'*50) - correct_names = input(f"Are those the joint names as defined in your JointTrajectroy recieving Node?: {joint_names}. (y/n)?: ").strip() - if correct_names.lower() == 'y': - break - else: - print("Please re-enter the joint names.") - while True: - try: - joint_velocity_limits = {} - for name in joint_names: - while True: - try: - print('--'*50) - limit = input(f"Enter the velocity limit for joint '{name}': ").strip() - if limit == "": - continue - else: - joint_velocity_limits[name] = float(limit) - break - except ValueError: - print("Invalid input. Please enter a numeric value or press Enter to skip.") - break - except ValueError: - print("Invalid input. Please enter numeric values or leave blank to skip.") - robot = None - cost_mask = None - break - print("Invalid input. Please enter 'y' or 'n'.") - - - node = OSC_ROS2_interface(joint_names, joint_velocity_limits, robot, cost_mask) - - # Run ROS 2 spin, and osc_process will be handled by the timer - try: - rclpy.spin(node) - except KeyboardInterrupt: - print("") - finally: - node.destroy_node() - osc_terminate() - -if __name__ == '__main__': - main() diff --git a/workspace/build/osc_ros2/colcon_build.rc b/workspace/build/osc_ros2/colcon_build.rc deleted file mode 100644 index 573541a..0000000 --- a/workspace/build/osc_ros2/colcon_build.rc +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh b/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh deleted file mode 100644 index f9867d5..0000000 --- a/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh +++ /dev/null @@ -1 +0,0 @@ -# generated from colcon_core/shell/template/command_prefix.sh.em diff --git a/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env b/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env deleted file mode 100644 index 5f4a769..0000000 --- a/workspace/build/osc_ros2/colcon_command_prefix_setup_py.sh.env +++ /dev/null @@ -1,20 +0,0 @@ -AMENT_PREFIX_PATH=/workspace/install/osc_ros2:/opt/ros/humble -COLCON=1 -COLCON_PREFIX_PATH=/workspace/install -HOME=/root -HOSTNAME=ad72f3440b4e -LANG=C.UTF-8 -LC_ALL=C.UTF-8 -LD_LIBRARY_PATH=/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib -LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36: -OLDPWD=/ -PATH=/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin -PWD=/workspace/build/osc_ros2 -PYTHONPATH=/workspace/install/osc_ros2/lib/python3.10/site-packages:/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages -ROS_DISTRO=humble -ROS_LOCALHOST_ONLY=0 -ROS_PYTHON_VERSION=3 -ROS_VERSION=2 -SHLVL=1 -TERM=xterm -_=/usr/bin/colcon diff --git a/workspace/build/osc_ros2/install.log b/workspace/build/osc_ros2/install.log deleted file mode 100644 index bebe111..0000000 --- a/workspace/build/osc_ros2/install.log +++ /dev/null @@ -1,14 +0,0 @@ -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/osc_ros2.cpython-310.pyc -/workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 -/workspace/install/osc_ros2/share/osc_ros2/package.xml -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt -/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt -/workspace/install/osc_ros2/lib/osc_ros2/interface diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO b/workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO deleted file mode 100644 index 275623c..0000000 --- a/workspace/build/osc_ros2/osc_ros2.egg-info/PKG-INFO +++ /dev/null @@ -1,12 +0,0 @@ -Metadata-Version: 2.1 -Name: osc-ros2 -Version: 1.0.0 -Summary: Creates an interface for communication between OSC and Ros2 -Home-page: UNKNOWN -Maintainer: Alexander Schaefer -Maintainer-email: a.schaefer@tuhh.de -License: Apache-2.0 -Platform: UNKNOWN - -UNKNOWN - diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt deleted file mode 100644 index 650a016..0000000 --- a/workspace/build/osc_ros2/osc_ros2.egg-info/SOURCES.txt +++ /dev/null @@ -1,16 +0,0 @@ -package.xml -setup.cfg -setup.py -../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt -../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -../../build/osc_ros2/osc_ros2.egg-info/requires.txt -../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -../../build/osc_ros2/osc_ros2.egg-info/zip-safe -osc_ros2/__init__.py -osc_ros2/osc_ros2.py -resource/osc_ros2 -test/test_copyright.py -test/test_flake8.py -test/test_pep257.py \ No newline at end of file diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/workspace/build/osc_ros2/osc_ros2.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt deleted file mode 100644 index 008581c..0000000 --- a/workspace/build/osc_ros2/osc_ros2.egg-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -interface = osc_ros2.osc_ros2:main - diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt deleted file mode 100644 index 3c8c415..0000000 --- a/workspace/build/osc_ros2/osc_ros2.egg-info/requires.txt +++ /dev/null @@ -1,6 +0,0 @@ -numpy==1.22.4 -osc4py3 -roboticstoolbox-python -scipy==1.7.3 -setuptools -spatialmath-python diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt b/workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt deleted file mode 100644 index 99ee4eb..0000000 --- a/workspace/build/osc_ros2/osc_ros2.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -osc_ros2 diff --git a/workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe b/workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/workspace/build/osc_ros2/osc_ros2.egg-info/zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/workspace/build/osc_ros2/prefix_override/__pycache__/sitecustomize.cpython-310.pyc b/workspace/build/osc_ros2/prefix_override/__pycache__/sitecustomize.cpython-310.pyc deleted file mode 100644 index 5cfe64334ee70c5f964f01a77093a23dd61fcae0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 277 zcmd1j<>g`k0+T+oj5Z+s7{oya%s`F<5EttKi4=wu#vFzyhE#?u#uTP(rXo=gE0rOh zDTSE@C>jr9Gp8^H1JwmHXtKNn>S6G!V$m-xE~=8&FV8Q^E-pw+PSwxMD=taQ$PO2Rv(70ky7;rFf MF>){pFtYpu06PUsga7~l diff --git a/workspace/build/osc_ros2/prefix_override/sitecustomize.py b/workspace/build/osc_ros2/prefix_override/sitecustomize.py deleted file mode 100644 index f14fb81..0000000 --- a/workspace/build/osc_ros2/prefix_override/sitecustomize.py +++ /dev/null @@ -1,4 +0,0 @@ -import sys -if sys.prefix == '/usr': - sys.real_prefix = sys.prefix - sys.prefix = sys.exec_prefix = '/workspace/install/osc_ros2' diff --git a/workspace/install/.colcon_install_layout b/workspace/install/.colcon_install_layout deleted file mode 100644 index 3aad533..0000000 --- a/workspace/install/.colcon_install_layout +++ /dev/null @@ -1 +0,0 @@ -isolated diff --git a/workspace/install/COLCON_IGNORE b/workspace/install/COLCON_IGNORE deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/install/_local_setup_util_ps1.py b/workspace/install/_local_setup_util_ps1.py deleted file mode 100644 index 3c6d9e8..0000000 --- a/workspace/install/_local_setup_util_ps1.py +++ /dev/null @@ -1,407 +0,0 @@ -# Copyright 2016-2019 Dirk Thomas -# Licensed under the Apache License, Version 2.0 - -import argparse -from collections import OrderedDict -import os -from pathlib import Path -import sys - - -FORMAT_STR_COMMENT_LINE = '# {comment}' -FORMAT_STR_SET_ENV_VAR = 'Set-Item -Path "Env:{name}" -Value "{value}"' -FORMAT_STR_USE_ENV_VAR = '$env:{name}' -FORMAT_STR_INVOKE_SCRIPT = '_colcon_prefix_powershell_source_script "{script_path}"' # noqa: E501 -FORMAT_STR_REMOVE_LEADING_SEPARATOR = '' # noqa: E501 -FORMAT_STR_REMOVE_TRAILING_SEPARATOR = '' # noqa: E501 - -DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate' -DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate' -DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists' -DSV_TYPE_SET = 'set' -DSV_TYPE_SET_IF_UNSET = 'set-if-unset' -DSV_TYPE_SOURCE = 'source' - - -def main(argv=sys.argv[1:]): # noqa: D103 - parser = argparse.ArgumentParser( - description='Output shell commands for the packages in topological ' - 'order') - parser.add_argument( - 'primary_extension', - help='The file extension of the primary shell') - parser.add_argument( - 'additional_extension', nargs='?', - help='The additional file extension to be considered') - parser.add_argument( - '--merged-install', action='store_true', - help='All install prefixes are merged into a single location') - args = parser.parse_args(argv) - - packages = get_packages(Path(__file__).parent, args.merged_install) - - ordered_packages = order_packages(packages) - for pkg_name in ordered_packages: - if _include_comments(): - print( - FORMAT_STR_COMMENT_LINE.format_map( - {'comment': 'Package: ' + pkg_name})) - prefix = os.path.abspath(os.path.dirname(__file__)) - if not args.merged_install: - prefix = os.path.join(prefix, pkg_name) - for line in get_commands( - pkg_name, prefix, args.primary_extension, - args.additional_extension - ): - print(line) - - for line in _remove_ending_separators(): - print(line) - - -def get_packages(prefix_path, merged_install): - """ - Find packages based on colcon-specific files created during installation. - - :param Path prefix_path: The install prefix path of all packages - :param bool merged_install: The flag if the packages are all installed - directly in the prefix or if each package is installed in a subdirectory - named after the package - :returns: A mapping from the package name to the set of runtime - dependencies - :rtype: dict - """ - packages = {} - # since importing colcon_core isn't feasible here the following constant - # must match colcon_core.location.get_relative_package_index_path() - subdirectory = 'share/colcon-core/packages' - if merged_install: - # return if workspace is empty - if not (prefix_path / subdirectory).is_dir(): - return packages - # find all files in the subdirectory - for p in (prefix_path / subdirectory).iterdir(): - if not p.is_file(): - continue - if p.name.startswith('.'): - continue - add_package_runtime_dependencies(p, packages) - else: - # for each subdirectory look for the package specific file - for p in prefix_path.iterdir(): - if not p.is_dir(): - continue - if p.name.startswith('.'): - continue - p = p / subdirectory / p.name - if p.is_file(): - add_package_runtime_dependencies(p, packages) - - # remove unknown dependencies - pkg_names = set(packages.keys()) - for k in packages.keys(): - packages[k] = {d for d in packages[k] if d in pkg_names} - - return packages - - -def add_package_runtime_dependencies(path, packages): - """ - Check the path and if it exists extract the packages runtime dependencies. - - :param Path path: The resource file containing the runtime dependencies - :param dict packages: A mapping from package names to the sets of runtime - dependencies to add to - """ - content = path.read_text() - dependencies = set(content.split(os.pathsep) if content else []) - packages[path.name] = dependencies - - -def order_packages(packages): - """ - Order packages topologically. - - :param dict packages: A mapping from package name to the set of runtime - dependencies - :returns: The package names - :rtype: list - """ - # select packages with no dependencies in alphabetical order - to_be_ordered = list(packages.keys()) - ordered = [] - while to_be_ordered: - pkg_names_without_deps = [ - name for name in to_be_ordered if not packages[name]] - if not pkg_names_without_deps: - reduce_cycle_set(packages) - raise RuntimeError( - 'Circular dependency between: ' + ', '.join(sorted(packages))) - pkg_names_without_deps.sort() - pkg_name = pkg_names_without_deps[0] - to_be_ordered.remove(pkg_name) - ordered.append(pkg_name) - # remove item from dependency lists - for k in list(packages.keys()): - if pkg_name in packages[k]: - packages[k].remove(pkg_name) - return ordered - - -def reduce_cycle_set(packages): - """ - Reduce the set of packages to the ones part of the circular dependency. - - :param dict packages: A mapping from package name to the set of runtime - dependencies which is modified in place - """ - last_depended = None - while len(packages) > 0: - # get all remaining dependencies - depended = set() - for pkg_name, dependencies in packages.items(): - depended = depended.union(dependencies) - # remove all packages which are not dependent on - for name in list(packages.keys()): - if name not in depended: - del packages[name] - if last_depended: - # if remaining packages haven't changed return them - if last_depended == depended: - return packages.keys() - # otherwise reduce again - last_depended = depended - - -def _include_comments(): - # skipping comment lines when COLCON_TRACE is not set speeds up the - # processing especially on Windows - return bool(os.environ.get('COLCON_TRACE')) - - -def get_commands(pkg_name, prefix, primary_extension, additional_extension): - commands = [] - package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv') - if os.path.exists(package_dsv_path): - commands += process_dsv_file( - package_dsv_path, prefix, primary_extension, additional_extension) - return commands - - -def process_dsv_file( - dsv_path, prefix, primary_extension=None, additional_extension=None -): - commands = [] - if _include_comments(): - commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path})) - with open(dsv_path, 'r') as h: - content = h.read() - lines = content.splitlines() - - basenames = OrderedDict() - for i, line in enumerate(lines): - # skip over empty or whitespace-only lines - if not line.strip(): - continue - # skip over comments - if line.startswith('#'): - continue - try: - type_, remainder = line.split(';', 1) - except ValueError: - raise RuntimeError( - "Line %d in '%s' doesn't contain a semicolon separating the " - 'type from the arguments' % (i + 1, dsv_path)) - if type_ != DSV_TYPE_SOURCE: - # handle non-source lines - try: - commands += handle_dsv_types_except_source( - type_, remainder, prefix) - except RuntimeError as e: - raise RuntimeError( - "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e - else: - # group remaining source lines by basename - path_without_ext, ext = os.path.splitext(remainder) - if path_without_ext not in basenames: - basenames[path_without_ext] = set() - assert ext.startswith('.') - ext = ext[1:] - if ext in (primary_extension, additional_extension): - basenames[path_without_ext].add(ext) - - # add the dsv extension to each basename if the file exists - for basename, extensions in basenames.items(): - if not os.path.isabs(basename): - basename = os.path.join(prefix, basename) - if os.path.exists(basename + '.dsv'): - extensions.add('dsv') - - for basename, extensions in basenames.items(): - if not os.path.isabs(basename): - basename = os.path.join(prefix, basename) - if 'dsv' in extensions: - # process dsv files recursively - commands += process_dsv_file( - basename + '.dsv', prefix, primary_extension=primary_extension, - additional_extension=additional_extension) - elif primary_extension in extensions and len(extensions) == 1: - # source primary-only files - commands += [ - FORMAT_STR_INVOKE_SCRIPT.format_map({ - 'prefix': prefix, - 'script_path': basename + '.' + primary_extension})] - elif additional_extension in extensions: - # source non-primary files - commands += [ - FORMAT_STR_INVOKE_SCRIPT.format_map({ - 'prefix': prefix, - 'script_path': basename + '.' + additional_extension})] - - return commands - - -def handle_dsv_types_except_source(type_, remainder, prefix): - commands = [] - if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET): - try: - env_name, value = remainder.split(';', 1) - except ValueError: - raise RuntimeError( - "doesn't contain a semicolon separating the environment name " - 'from the value') - try_prefixed_value = os.path.join(prefix, value) if value else prefix - if os.path.exists(try_prefixed_value): - value = try_prefixed_value - if type_ == DSV_TYPE_SET: - commands += _set(env_name, value) - elif type_ == DSV_TYPE_SET_IF_UNSET: - commands += _set_if_unset(env_name, value) - else: - assert False - elif type_ in ( - DSV_TYPE_APPEND_NON_DUPLICATE, - DSV_TYPE_PREPEND_NON_DUPLICATE, - DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS - ): - try: - env_name_and_values = remainder.split(';') - except ValueError: - raise RuntimeError( - "doesn't contain a semicolon separating the environment name " - 'from the values') - env_name = env_name_and_values[0] - values = env_name_and_values[1:] - for value in values: - if not value: - value = prefix - elif not os.path.isabs(value): - value = os.path.join(prefix, value) - if ( - type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and - not os.path.exists(value) - ): - comment = f'skip extending {env_name} with not existing ' \ - f'path: {value}' - if _include_comments(): - commands.append( - FORMAT_STR_COMMENT_LINE.format_map({'comment': comment})) - elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE: - commands += _append_unique_value(env_name, value) - else: - commands += _prepend_unique_value(env_name, value) - else: - raise RuntimeError( - 'contains an unknown environment hook type: ' + type_) - return commands - - -env_state = {} - - -def _append_unique_value(name, value): - global env_state - if name not in env_state: - if os.environ.get(name): - env_state[name] = set(os.environ[name].split(os.pathsep)) - else: - env_state[name] = set() - # append even if the variable has not been set yet, in case a shell script sets the - # same variable without the knowledge of this Python script. - # later _remove_ending_separators() will cleanup any unintentional leading separator - extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': extend + value}) - if value not in env_state[name]: - env_state[name].add(value) - else: - if not _include_comments(): - return [] - line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) - return [line] - - -def _prepend_unique_value(name, value): - global env_state - if name not in env_state: - if os.environ.get(name): - env_state[name] = set(os.environ[name].split(os.pathsep)) - else: - env_state[name] = set() - # prepend even if the variable has not been set yet, in case a shell script sets the - # same variable without the knowledge of this Python script. - # later _remove_ending_separators() will cleanup any unintentional trailing separator - extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': value + extend}) - if value not in env_state[name]: - env_state[name].add(value) - else: - if not _include_comments(): - return [] - line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) - return [line] - - -# generate commands for removing prepended underscores -def _remove_ending_separators(): - # do nothing if the shell extension does not implement the logic - if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None: - return [] - - global env_state - commands = [] - for name in env_state: - # skip variables that already had values before this script started prepending - if name in os.environ: - continue - commands += [ - FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}), - FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})] - return commands - - -def _set(name, value): - global env_state - env_state[name] = value - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': value}) - return [line] - - -def _set_if_unset(name, value): - global env_state - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': value}) - if env_state.get(name, os.environ.get(name)): - line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) - return [line] - - -if __name__ == '__main__': # pragma: no cover - try: - rc = main() - except RuntimeError as e: - print(str(e), file=sys.stderr) - rc = 1 - sys.exit(rc) diff --git a/workspace/install/_local_setup_util_sh.py b/workspace/install/_local_setup_util_sh.py deleted file mode 100644 index f67eaa9..0000000 --- a/workspace/install/_local_setup_util_sh.py +++ /dev/null @@ -1,407 +0,0 @@ -# Copyright 2016-2019 Dirk Thomas -# Licensed under the Apache License, Version 2.0 - -import argparse -from collections import OrderedDict -import os -from pathlib import Path -import sys - - -FORMAT_STR_COMMENT_LINE = '# {comment}' -FORMAT_STR_SET_ENV_VAR = 'export {name}="{value}"' -FORMAT_STR_USE_ENV_VAR = '${name}' -FORMAT_STR_INVOKE_SCRIPT = 'COLCON_CURRENT_PREFIX="{prefix}" _colcon_prefix_sh_source_script "{script_path}"' # noqa: E501 -FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi' # noqa: E501 -FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi' # noqa: E501 - -DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate' -DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate' -DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists' -DSV_TYPE_SET = 'set' -DSV_TYPE_SET_IF_UNSET = 'set-if-unset' -DSV_TYPE_SOURCE = 'source' - - -def main(argv=sys.argv[1:]): # noqa: D103 - parser = argparse.ArgumentParser( - description='Output shell commands for the packages in topological ' - 'order') - parser.add_argument( - 'primary_extension', - help='The file extension of the primary shell') - parser.add_argument( - 'additional_extension', nargs='?', - help='The additional file extension to be considered') - parser.add_argument( - '--merged-install', action='store_true', - help='All install prefixes are merged into a single location') - args = parser.parse_args(argv) - - packages = get_packages(Path(__file__).parent, args.merged_install) - - ordered_packages = order_packages(packages) - for pkg_name in ordered_packages: - if _include_comments(): - print( - FORMAT_STR_COMMENT_LINE.format_map( - {'comment': 'Package: ' + pkg_name})) - prefix = os.path.abspath(os.path.dirname(__file__)) - if not args.merged_install: - prefix = os.path.join(prefix, pkg_name) - for line in get_commands( - pkg_name, prefix, args.primary_extension, - args.additional_extension - ): - print(line) - - for line in _remove_ending_separators(): - print(line) - - -def get_packages(prefix_path, merged_install): - """ - Find packages based on colcon-specific files created during installation. - - :param Path prefix_path: The install prefix path of all packages - :param bool merged_install: The flag if the packages are all installed - directly in the prefix or if each package is installed in a subdirectory - named after the package - :returns: A mapping from the package name to the set of runtime - dependencies - :rtype: dict - """ - packages = {} - # since importing colcon_core isn't feasible here the following constant - # must match colcon_core.location.get_relative_package_index_path() - subdirectory = 'share/colcon-core/packages' - if merged_install: - # return if workspace is empty - if not (prefix_path / subdirectory).is_dir(): - return packages - # find all files in the subdirectory - for p in (prefix_path / subdirectory).iterdir(): - if not p.is_file(): - continue - if p.name.startswith('.'): - continue - add_package_runtime_dependencies(p, packages) - else: - # for each subdirectory look for the package specific file - for p in prefix_path.iterdir(): - if not p.is_dir(): - continue - if p.name.startswith('.'): - continue - p = p / subdirectory / p.name - if p.is_file(): - add_package_runtime_dependencies(p, packages) - - # remove unknown dependencies - pkg_names = set(packages.keys()) - for k in packages.keys(): - packages[k] = {d for d in packages[k] if d in pkg_names} - - return packages - - -def add_package_runtime_dependencies(path, packages): - """ - Check the path and if it exists extract the packages runtime dependencies. - - :param Path path: The resource file containing the runtime dependencies - :param dict packages: A mapping from package names to the sets of runtime - dependencies to add to - """ - content = path.read_text() - dependencies = set(content.split(os.pathsep) if content else []) - packages[path.name] = dependencies - - -def order_packages(packages): - """ - Order packages topologically. - - :param dict packages: A mapping from package name to the set of runtime - dependencies - :returns: The package names - :rtype: list - """ - # select packages with no dependencies in alphabetical order - to_be_ordered = list(packages.keys()) - ordered = [] - while to_be_ordered: - pkg_names_without_deps = [ - name for name in to_be_ordered if not packages[name]] - if not pkg_names_without_deps: - reduce_cycle_set(packages) - raise RuntimeError( - 'Circular dependency between: ' + ', '.join(sorted(packages))) - pkg_names_without_deps.sort() - pkg_name = pkg_names_without_deps[0] - to_be_ordered.remove(pkg_name) - ordered.append(pkg_name) - # remove item from dependency lists - for k in list(packages.keys()): - if pkg_name in packages[k]: - packages[k].remove(pkg_name) - return ordered - - -def reduce_cycle_set(packages): - """ - Reduce the set of packages to the ones part of the circular dependency. - - :param dict packages: A mapping from package name to the set of runtime - dependencies which is modified in place - """ - last_depended = None - while len(packages) > 0: - # get all remaining dependencies - depended = set() - for pkg_name, dependencies in packages.items(): - depended = depended.union(dependencies) - # remove all packages which are not dependent on - for name in list(packages.keys()): - if name not in depended: - del packages[name] - if last_depended: - # if remaining packages haven't changed return them - if last_depended == depended: - return packages.keys() - # otherwise reduce again - last_depended = depended - - -def _include_comments(): - # skipping comment lines when COLCON_TRACE is not set speeds up the - # processing especially on Windows - return bool(os.environ.get('COLCON_TRACE')) - - -def get_commands(pkg_name, prefix, primary_extension, additional_extension): - commands = [] - package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv') - if os.path.exists(package_dsv_path): - commands += process_dsv_file( - package_dsv_path, prefix, primary_extension, additional_extension) - return commands - - -def process_dsv_file( - dsv_path, prefix, primary_extension=None, additional_extension=None -): - commands = [] - if _include_comments(): - commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path})) - with open(dsv_path, 'r') as h: - content = h.read() - lines = content.splitlines() - - basenames = OrderedDict() - for i, line in enumerate(lines): - # skip over empty or whitespace-only lines - if not line.strip(): - continue - # skip over comments - if line.startswith('#'): - continue - try: - type_, remainder = line.split(';', 1) - except ValueError: - raise RuntimeError( - "Line %d in '%s' doesn't contain a semicolon separating the " - 'type from the arguments' % (i + 1, dsv_path)) - if type_ != DSV_TYPE_SOURCE: - # handle non-source lines - try: - commands += handle_dsv_types_except_source( - type_, remainder, prefix) - except RuntimeError as e: - raise RuntimeError( - "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e - else: - # group remaining source lines by basename - path_without_ext, ext = os.path.splitext(remainder) - if path_without_ext not in basenames: - basenames[path_without_ext] = set() - assert ext.startswith('.') - ext = ext[1:] - if ext in (primary_extension, additional_extension): - basenames[path_without_ext].add(ext) - - # add the dsv extension to each basename if the file exists - for basename, extensions in basenames.items(): - if not os.path.isabs(basename): - basename = os.path.join(prefix, basename) - if os.path.exists(basename + '.dsv'): - extensions.add('dsv') - - for basename, extensions in basenames.items(): - if not os.path.isabs(basename): - basename = os.path.join(prefix, basename) - if 'dsv' in extensions: - # process dsv files recursively - commands += process_dsv_file( - basename + '.dsv', prefix, primary_extension=primary_extension, - additional_extension=additional_extension) - elif primary_extension in extensions and len(extensions) == 1: - # source primary-only files - commands += [ - FORMAT_STR_INVOKE_SCRIPT.format_map({ - 'prefix': prefix, - 'script_path': basename + '.' + primary_extension})] - elif additional_extension in extensions: - # source non-primary files - commands += [ - FORMAT_STR_INVOKE_SCRIPT.format_map({ - 'prefix': prefix, - 'script_path': basename + '.' + additional_extension})] - - return commands - - -def handle_dsv_types_except_source(type_, remainder, prefix): - commands = [] - if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET): - try: - env_name, value = remainder.split(';', 1) - except ValueError: - raise RuntimeError( - "doesn't contain a semicolon separating the environment name " - 'from the value') - try_prefixed_value = os.path.join(prefix, value) if value else prefix - if os.path.exists(try_prefixed_value): - value = try_prefixed_value - if type_ == DSV_TYPE_SET: - commands += _set(env_name, value) - elif type_ == DSV_TYPE_SET_IF_UNSET: - commands += _set_if_unset(env_name, value) - else: - assert False - elif type_ in ( - DSV_TYPE_APPEND_NON_DUPLICATE, - DSV_TYPE_PREPEND_NON_DUPLICATE, - DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS - ): - try: - env_name_and_values = remainder.split(';') - except ValueError: - raise RuntimeError( - "doesn't contain a semicolon separating the environment name " - 'from the values') - env_name = env_name_and_values[0] - values = env_name_and_values[1:] - for value in values: - if not value: - value = prefix - elif not os.path.isabs(value): - value = os.path.join(prefix, value) - if ( - type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and - not os.path.exists(value) - ): - comment = f'skip extending {env_name} with not existing ' \ - f'path: {value}' - if _include_comments(): - commands.append( - FORMAT_STR_COMMENT_LINE.format_map({'comment': comment})) - elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE: - commands += _append_unique_value(env_name, value) - else: - commands += _prepend_unique_value(env_name, value) - else: - raise RuntimeError( - 'contains an unknown environment hook type: ' + type_) - return commands - - -env_state = {} - - -def _append_unique_value(name, value): - global env_state - if name not in env_state: - if os.environ.get(name): - env_state[name] = set(os.environ[name].split(os.pathsep)) - else: - env_state[name] = set() - # append even if the variable has not been set yet, in case a shell script sets the - # same variable without the knowledge of this Python script. - # later _remove_ending_separators() will cleanup any unintentional leading separator - extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': extend + value}) - if value not in env_state[name]: - env_state[name].add(value) - else: - if not _include_comments(): - return [] - line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) - return [line] - - -def _prepend_unique_value(name, value): - global env_state - if name not in env_state: - if os.environ.get(name): - env_state[name] = set(os.environ[name].split(os.pathsep)) - else: - env_state[name] = set() - # prepend even if the variable has not been set yet, in case a shell script sets the - # same variable without the knowledge of this Python script. - # later _remove_ending_separators() will cleanup any unintentional trailing separator - extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': value + extend}) - if value not in env_state[name]: - env_state[name].add(value) - else: - if not _include_comments(): - return [] - line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) - return [line] - - -# generate commands for removing prepended underscores -def _remove_ending_separators(): - # do nothing if the shell extension does not implement the logic - if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None: - return [] - - global env_state - commands = [] - for name in env_state: - # skip variables that already had values before this script started prepending - if name in os.environ: - continue - commands += [ - FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}), - FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})] - return commands - - -def _set(name, value): - global env_state - env_state[name] = value - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': value}) - return [line] - - -def _set_if_unset(name, value): - global env_state - line = FORMAT_STR_SET_ENV_VAR.format_map( - {'name': name, 'value': value}) - if env_state.get(name, os.environ.get(name)): - line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) - return [line] - - -if __name__ == '__main__': # pragma: no cover - try: - rc = main() - except RuntimeError as e: - print(str(e), file=sys.stderr) - rc = 1 - sys.exit(rc) diff --git a/workspace/install/local_setup.bash b/workspace/install/local_setup.bash deleted file mode 100644 index 03f0025..0000000 --- a/workspace/install/local_setup.bash +++ /dev/null @@ -1,121 +0,0 @@ -# generated from colcon_bash/shell/template/prefix.bash.em - -# This script extends the environment with all packages contained in this -# prefix path. - -# a bash script is able to determine its own path if necessary -if [ -z "$COLCON_CURRENT_PREFIX" ]; then - _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)" -else - _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" -fi - -# function to prepend a value to a variable -# which uses colons as separators -# duplicates as well as trailing separators are avoided -# first argument: the name of the result variable -# second argument: the value to be prepended -_colcon_prefix_bash_prepend_unique_value() { - # arguments - _listname="$1" - _value="$2" - - # get values from variable - eval _values=\"\$$_listname\" - # backup the field separator - _colcon_prefix_bash_prepend_unique_value_IFS="$IFS" - IFS=":" - # start with the new value - _all_values="$_value" - _contained_value="" - # iterate over existing values in the variable - for _item in $_values; do - # ignore empty strings - if [ -z "$_item" ]; then - continue - fi - # ignore duplicates of _value - if [ "$_item" = "$_value" ]; then - _contained_value=1 - continue - fi - # keep non-duplicate values - _all_values="$_all_values:$_item" - done - unset _item - if [ -z "$_contained_value" ]; then - if [ -n "$COLCON_TRACE" ]; then - if [ "$_all_values" = "$_value" ]; then - echo "export $_listname=$_value" - else - echo "export $_listname=$_value:\$$_listname" - fi - fi - fi - unset _contained_value - # restore the field separator - IFS="$_colcon_prefix_bash_prepend_unique_value_IFS" - unset _colcon_prefix_bash_prepend_unique_value_IFS - # export the updated variable - eval export $_listname=\"$_all_values\" - unset _all_values - unset _values - - unset _value - unset _listname -} - -# add this prefix to the COLCON_PREFIX_PATH -_colcon_prefix_bash_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX" -unset _colcon_prefix_bash_prepend_unique_value - -# check environment variable for custom Python executable -if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then - if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then - echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" - return 1 - fi - _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" -else - # try the Python executable known at configure time - _colcon_python_executable="/usr/bin/python3" - # if it doesn't exist try a fall back - if [ ! -f "$_colcon_python_executable" ]; then - if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then - echo "error: unable to find python3 executable" - return 1 - fi - _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` - fi -fi - -# function to source another script with conditional trace output -# first argument: the path of the script -_colcon_prefix_sh_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$1" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# get all commands in topological order -_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh bash)" -unset _colcon_python_executable -if [ -n "$COLCON_TRACE" ]; then - echo "$(declare -f _colcon_prefix_sh_source_script)" - echo "# Execute generated script:" - echo "# <<<" - echo "${_colcon_ordered_commands}" - echo "# >>>" - echo "unset _colcon_prefix_sh_source_script" -fi -eval "${_colcon_ordered_commands}" -unset _colcon_ordered_commands - -unset _colcon_prefix_sh_source_script - -unset _colcon_prefix_bash_COLCON_CURRENT_PREFIX diff --git a/workspace/install/local_setup.ps1 b/workspace/install/local_setup.ps1 deleted file mode 100644 index 6f68c8d..0000000 --- a/workspace/install/local_setup.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -# generated from colcon_powershell/shell/template/prefix.ps1.em - -# This script extends the environment with all packages contained in this -# prefix path. - -# check environment variable for custom Python executable -if ($env:COLCON_PYTHON_EXECUTABLE) { - if (!(Test-Path "$env:COLCON_PYTHON_EXECUTABLE" -PathType Leaf)) { - echo "error: COLCON_PYTHON_EXECUTABLE '$env:COLCON_PYTHON_EXECUTABLE' doesn't exist" - exit 1 - } - $_colcon_python_executable="$env:COLCON_PYTHON_EXECUTABLE" -} else { - # use the Python executable known at configure time - $_colcon_python_executable="/usr/bin/python3" - # if it doesn't exist try a fall back - if (!(Test-Path "$_colcon_python_executable" -PathType Leaf)) { - if (!(Get-Command "python3" -ErrorAction SilentlyContinue)) { - echo "error: unable to find python3 executable" - exit 1 - } - $_colcon_python_executable="python3" - } -} - -# function to source another script with conditional trace output -# first argument: the path of the script -function _colcon_prefix_powershell_source_script { - param ( - $_colcon_prefix_powershell_source_script_param - ) - # source script with conditional trace output - if (Test-Path $_colcon_prefix_powershell_source_script_param) { - if ($env:COLCON_TRACE) { - echo ". '$_colcon_prefix_powershell_source_script_param'" - } - . "$_colcon_prefix_powershell_source_script_param" - } else { - Write-Error "not found: '$_colcon_prefix_powershell_source_script_param'" - } -} - -# get all commands in topological order -$_colcon_ordered_commands = & "$_colcon_python_executable" "$(Split-Path $PSCommandPath -Parent)/_local_setup_util_ps1.py" ps1 - -# execute all commands in topological order -if ($env:COLCON_TRACE) { - echo "Execute generated script:" - echo "<<<" - $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Write-Output - echo ">>>" -} -if ($_colcon_ordered_commands) { - $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Invoke-Expression -} diff --git a/workspace/install/local_setup.sh b/workspace/install/local_setup.sh deleted file mode 100644 index 24bb54f..0000000 --- a/workspace/install/local_setup.sh +++ /dev/null @@ -1,137 +0,0 @@ -# generated from colcon_core/shell/template/prefix.sh.em - -# This script extends the environment with all packages contained in this -# prefix path. - -# since a plain shell script can't determine its own path when being sourced -# either use the provided COLCON_CURRENT_PREFIX -# or fall back to the build time prefix (if it exists) -_colcon_prefix_sh_COLCON_CURRENT_PREFIX="/workspace/install" -if [ -z "$COLCON_CURRENT_PREFIX" ]; then - if [ ! -d "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" ]; then - echo "The build time path \"$_colcon_prefix_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 - unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX - return 1 - fi -else - _colcon_prefix_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" -fi - -# function to prepend a value to a variable -# which uses colons as separators -# duplicates as well as trailing separators are avoided -# first argument: the name of the result variable -# second argument: the value to be prepended -_colcon_prefix_sh_prepend_unique_value() { - # arguments - _listname="$1" - _value="$2" - - # get values from variable - eval _values=\"\$$_listname\" - # backup the field separator - _colcon_prefix_sh_prepend_unique_value_IFS="$IFS" - IFS=":" - # start with the new value - _all_values="$_value" - _contained_value="" - # iterate over existing values in the variable - for _item in $_values; do - # ignore empty strings - if [ -z "$_item" ]; then - continue - fi - # ignore duplicates of _value - if [ "$_item" = "$_value" ]; then - _contained_value=1 - continue - fi - # keep non-duplicate values - _all_values="$_all_values:$_item" - done - unset _item - if [ -z "$_contained_value" ]; then - if [ -n "$COLCON_TRACE" ]; then - if [ "$_all_values" = "$_value" ]; then - echo "export $_listname=$_value" - else - echo "export $_listname=$_value:\$$_listname" - fi - fi - fi - unset _contained_value - # restore the field separator - IFS="$_colcon_prefix_sh_prepend_unique_value_IFS" - unset _colcon_prefix_sh_prepend_unique_value_IFS - # export the updated variable - eval export $_listname=\"$_all_values\" - unset _all_values - unset _values - - unset _value - unset _listname -} - -# add this prefix to the COLCON_PREFIX_PATH -_colcon_prefix_sh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" -unset _colcon_prefix_sh_prepend_unique_value - -# check environment variable for custom Python executable -if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then - if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then - echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" - return 1 - fi - _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" -else - # try the Python executable known at configure time - _colcon_python_executable="/usr/bin/python3" - # if it doesn't exist try a fall back - if [ ! -f "$_colcon_python_executable" ]; then - if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then - echo "error: unable to find python3 executable" - return 1 - fi - _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` - fi -fi - -# function to source another script with conditional trace output -# first argument: the path of the script -_colcon_prefix_sh_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$1" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# get all commands in topological order -_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh)" -unset _colcon_python_executable -if [ -n "$COLCON_TRACE" ]; then - echo "_colcon_prefix_sh_source_script() { - if [ -f \"\$1\" ]; then - if [ -n \"\$COLCON_TRACE\" ]; then - echo \"# . \\\"\$1\\\"\" - fi - . \"\$1\" - else - echo \"not found: \\\"\$1\\\"\" 1>&2 - fi - }" - echo "# Execute generated script:" - echo "# <<<" - echo "${_colcon_ordered_commands}" - echo "# >>>" - echo "unset _colcon_prefix_sh_source_script" -fi -eval "${_colcon_ordered_commands}" -unset _colcon_ordered_commands - -unset _colcon_prefix_sh_source_script - -unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX diff --git a/workspace/install/local_setup.zsh b/workspace/install/local_setup.zsh deleted file mode 100644 index b648710..0000000 --- a/workspace/install/local_setup.zsh +++ /dev/null @@ -1,134 +0,0 @@ -# generated from colcon_zsh/shell/template/prefix.zsh.em - -# This script extends the environment with all packages contained in this -# prefix path. - -# a zsh script is able to determine its own path if necessary -if [ -z "$COLCON_CURRENT_PREFIX" ]; then - _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)" -else - _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" -fi - -# function to convert array-like strings into arrays -# to workaround SH_WORD_SPLIT not being set -_colcon_prefix_zsh_convert_to_array() { - local _listname=$1 - local _dollar="$" - local _split="{=" - local _to_array="(\"$_dollar$_split$_listname}\")" - eval $_listname=$_to_array -} - -# function to prepend a value to a variable -# which uses colons as separators -# duplicates as well as trailing separators are avoided -# first argument: the name of the result variable -# second argument: the value to be prepended -_colcon_prefix_zsh_prepend_unique_value() { - # arguments - _listname="$1" - _value="$2" - - # get values from variable - eval _values=\"\$$_listname\" - # backup the field separator - _colcon_prefix_zsh_prepend_unique_value_IFS="$IFS" - IFS=":" - # start with the new value - _all_values="$_value" - _contained_value="" - # workaround SH_WORD_SPLIT not being set - _colcon_prefix_zsh_convert_to_array _values - # iterate over existing values in the variable - for _item in $_values; do - # ignore empty strings - if [ -z "$_item" ]; then - continue - fi - # ignore duplicates of _value - if [ "$_item" = "$_value" ]; then - _contained_value=1 - continue - fi - # keep non-duplicate values - _all_values="$_all_values:$_item" - done - unset _item - if [ -z "$_contained_value" ]; then - if [ -n "$COLCON_TRACE" ]; then - if [ "$_all_values" = "$_value" ]; then - echo "export $_listname=$_value" - else - echo "export $_listname=$_value:\$$_listname" - fi - fi - fi - unset _contained_value - # restore the field separator - IFS="$_colcon_prefix_zsh_prepend_unique_value_IFS" - unset _colcon_prefix_zsh_prepend_unique_value_IFS - # export the updated variable - eval export $_listname=\"$_all_values\" - unset _all_values - unset _values - - unset _value - unset _listname -} - -# add this prefix to the COLCON_PREFIX_PATH -_colcon_prefix_zsh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX" -unset _colcon_prefix_zsh_prepend_unique_value -unset _colcon_prefix_zsh_convert_to_array - -# check environment variable for custom Python executable -if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then - if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then - echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" - return 1 - fi - _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" -else - # try the Python executable known at configure time - _colcon_python_executable="/usr/bin/python3" - # if it doesn't exist try a fall back - if [ ! -f "$_colcon_python_executable" ]; then - if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then - echo "error: unable to find python3 executable" - return 1 - fi - _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` - fi -fi - -# function to source another script with conditional trace output -# first argument: the path of the script -_colcon_prefix_sh_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$1" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# get all commands in topological order -_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh zsh)" -unset _colcon_python_executable -if [ -n "$COLCON_TRACE" ]; then - echo "$(declare -f _colcon_prefix_sh_source_script)" - echo "# Execute generated script:" - echo "# <<<" - echo "${_colcon_ordered_commands}" - echo "# >>>" - echo "unset _colcon_prefix_sh_source_script" -fi -eval "${_colcon_ordered_commands}" -unset _colcon_ordered_commands - -unset _colcon_prefix_sh_source_script - -unset _colcon_prefix_zsh_COLCON_CURRENT_PREFIX diff --git a/workspace/install/osc_ros2/lib/osc_ros2/interface b/workspace/install/osc_ros2/lib/osc_ros2/interface deleted file mode 100755 index 61d20a1..0000000 --- a/workspace/install/osc_ros2/lib/osc_ros2/interface +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/python3 -# EASY-INSTALL-ENTRY-SCRIPT: 'osc-ros2==1.0.0','console_scripts','interface' -import re -import sys - -# for compatibility with easy_install; see #2198 -__requires__ = 'osc-ros2==1.0.0' - -try: - from importlib.metadata import distribution -except ImportError: - try: - from importlib_metadata import distribution - except ImportError: - from pkg_resources import load_entry_point - - -def importlib_load_entry_point(spec, group, name): - dist_name, _, _ = spec.partition('==') - matches = ( - entry_point - for entry_point in distribution(dist_name).entry_points - if entry_point.group == group and entry_point.name == name - ) - return next(matches).load() - - -globals().setdefault('load_entry_point', importlib_load_entry_point) - - -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) - sys.exit(load_entry_point('osc-ros2==1.0.0', 'console_scripts', 'interface')()) diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO deleted file mode 100644 index 275623c..0000000 --- a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/PKG-INFO +++ /dev/null @@ -1,12 +0,0 @@ -Metadata-Version: 2.1 -Name: osc-ros2 -Version: 1.0.0 -Summary: Creates an interface for communication between OSC and Ros2 -Home-page: UNKNOWN -Maintainer: Alexander Schaefer -Maintainer-email: a.schaefer@tuhh.de -License: Apache-2.0 -Platform: UNKNOWN - -UNKNOWN - diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt deleted file mode 100644 index 650a016..0000000 --- a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/SOURCES.txt +++ /dev/null @@ -1,16 +0,0 @@ -package.xml -setup.cfg -setup.py -../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt -../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -../../build/osc_ros2/osc_ros2.egg-info/requires.txt -../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -../../build/osc_ros2/osc_ros2.egg-info/zip-safe -osc_ros2/__init__.py -osc_ros2/osc_ros2.py -resource/osc_ros2 -test/test_copyright.py -test/test_flake8.py -test/test_pep257.py \ No newline at end of file diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt deleted file mode 100644 index 8b13789..0000000 --- a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt deleted file mode 100644 index 008581c..0000000 --- a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/entry_points.txt +++ /dev/null @@ -1,3 +0,0 @@ -[console_scripts] -interface = osc_ros2.osc_ros2:main - diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt deleted file mode 100644 index 3c8c415..0000000 --- a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/requires.txt +++ /dev/null @@ -1,6 +0,0 @@ -numpy==1.22.4 -osc4py3 -roboticstoolbox-python -scipy==1.7.3 -setuptools -spatialmath-python diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt deleted file mode 100644 index 99ee4eb..0000000 --- a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -osc_ros2 diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe deleted file mode 100644 index 8b13789..0000000 --- a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info/zip-safe +++ /dev/null @@ -1 +0,0 @@ - diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc b/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 849cee7393dfe4b5b3249ac78afddf80e135fac6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170 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 self.x_limits[1]) or \ - (self.y_limits[0] is not None and self.y_limits[1] is not None and self.y_limits[0] >= self.y_limits[1]) or \ - (self.z_limits[0] is not None and self.z_limits[1] is not None and self.z_limits[0] >= self.z_limits[1]): - print("Invalid input. Lower limit must be less than upper limit for each axis.") - continue - - print(f"Current limits:") - print(f"x: {self.x_limits}") - print(f"y: {self.y_limits}") - print(f"z: {self.z_limits}") - con = True - while con: - confirm = input("Do you want your TCP to move in this range? (y/n): ").strip().lower() - if confirm == 'y': - break - elif confirm == 'n': - print("Please re-enter the limits.") - con = False - else: - print("Invalid input. Please enter 'y' or 'n'.") - if con: break - except ValueError: - print("Invalid input. Please enter numeric values only.") - break - elif set_limits == 'n': - self.x_limits = [None, None] - self.y_limits = [None, None] - self.z_limits = [None, None] - break - print("Invalid input. Please enter 'y' or 'n'.") - - while True: - print('+-' * 50) - set_limits = input("Do you want to set workspace limits in x, y and z direction? (y/n): ").strip().lower() - if set_limits == 'y': - while True: - try: - self.x_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for x (space-separated, enter 'x' for no limit): ").split()] - self.y_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for y (space-separated, enter 'x' for no limit): ").split()] - self.z_limits_workspace = [float(i) if i != 'x' else None for i in input("Enter the lower and upper limits for z (space-separated, enter 'x' for no limit): ").split()] - - if len(self.x_limits_workspace) != 2 or len(self.y_limits_workspace) != 2 or len(self.z_limits_workspace) != 2: - print("Invalid input. Please enter exactly two values (or leave blank) for each limit.") - continue - - if (self.x_limits_workspace[0] is not None and self.x_limits_workspace[1] is not None and self.x_limits_workspace[0] >= self.x_limits_workspace[1]) or \ - (self.y_limits_workspace[0] is not None and self.y_limits_workspace[1] is not None and self.y_limits_workspace[0] >= self.y_limits_workspace[1]) or \ - (self.z_limits_workspace[0] is not None and self.z_limits_workspace[1] is not None and self.z_limits_workspace[0] >= self.z_limits_workspace[1]): - print("Invalid input. Lower limit must be less than upper limit for each axis.") - continue - - print(f"Current limits:") - print(f"x: {self.x_limits_workspace}") - print(f"y: {self.y_limits_workspace}") - print(f"z: {self.z_limits_workspace}") - con = True - while con: - confirm = input("Do you want your robot to move in this range? (y/n): ").strip().lower() - if confirm == 'y': - break - elif confirm == 'n': - print("Please re-enter the limits.") - con = False - else: - print("Invalid input. Please enter 'y' or 'n'.") - if con: break - except ValueError: - print("Invalid input. Please enter numeric values only.") - break - elif set_limits == 'n': - self.x_limits_workspace = [None, None] - self.y_limits_workspace = [None, None] - self.z_limits_workspace = [None, None] - break - print("Invalid input. Please enter 'y' or 'n'.") - # Ask the user if they want to set new joint limits - - # Ask the user if they want to set new joint limits - while True: - print('+-'*50) - update_limits = input("Do you want to set new joint limits? (y/n): ").strip().lower() - if update_limits == 'y': - for i in range(len(self.joint_names)): - while True: - try: - lim = self.robot.qlim.copy() - # Find the link corresponding to the joint name - print("-" * 50) - print(f"Current position limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") - lower_limit = input(f"Enter the new lower limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() - upper_limit = input(f"Enter the new upper limit for joint '{self.joint_names[i]}' (or press Enter to keep current): ").strip() - - if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): - print("Invalid input. Lower limit must be less than upper limit.") - continue - lower_limit = float(lower_limit) if lower_limit!="" else None - upper_limit = float(upper_limit) if upper_limit!="" else None - if lower_limit!=None: - if lower_limitlim[1][i]: - while True: - sure = input(f"Are you sure you want to set the upper limit to {upper_limit} rad which is more than the default limit {lim[1][i]} (y/n)?: ").strip().lower() - if sure == 'y': - lim[1][i] = float(upper_limit) - break - elif sure == 'n': - print("Upper limit not changed.") - break - print("Invalid input. Please enter 'y' or 'n'.") - else: lim[1][i] = float(upper_limit) - self.robot.qlim = lim - print(f"New limits for joint '{self.joint_names[i]}': [{self.robot.qlim[0][i]} {self.robot.qlim[1][i]}] rad") - print("-" * 50) - break - except ValueError: - print("Invalid input. Please enter numeric values or leave blank to keep current limits.") - break - if update_limits == 'n': - break - print("Invalid input. Please enter 'y' or 'n'.") - ''' - use_link_mask = input("Do you want to use a link mask? (y/n): ").strip().lower() - if use_link_mask == 'y': - while True: - try: - ''' - else: - while True: - print('+-' * 50) - update_limits = input("Do you want to set joint limits? (y/n): ").strip().lower() - if update_limits == 'y': - self.joint_lim = [[None]*self.n_joints,[None]*self.n_joints] - for i, joint in enumerate(self.joint_names): - while True: - try: - print("-" * 50) - lower_limit = input(f"Enter the new lower limit for joint '{joint}' (or press Enter for None): ").strip() - upper_limit = input(f"Enter the new upper limit for joint '{joint}' (or press Enter for None): ").strip() - - if lower_limit and upper_limit and float(lower_limit) >= float(upper_limit): - print('--' * 50) - print(" !!! Invalid input. Lower limit must be less than upper limit. !!! ") - continue - self.joint_lim[0][i] = float(lower_limit) if lower_limit!="" else None - self.joint_lim[1][i] = float(upper_limit) if upper_limit!="" else None - break - except ValueError: - print("Invalid input. Please enter numeric values or leave blank to keep current limits.") - print(f'New limits for joint:\n lower: {self.joint_lim[0]}\n upper: {self.joint_lim[1]}') - break - elif update_limits == 'n': - self.joint_lim = None - break - print("Invalid input. Please enter 'y' or 'n'.") - - - - while True: - try: - print('+-' * 50) - self.trajectory_topic_name = input("Enter the topic name to which the joint trajectory should be sent (press Enter for default: '/scaled_joint_trajectory_controller/joint_trajectory'): ").strip() - if self.trajectory_topic_name == "": - self.trajectory_topic_name = '/scaled_joint_trajectory_controller/joint_trajectory' - break - elif self.trajectory_topic_name.startswith("/"): - break - else: - print("Invalid topic name. A valid topic name should start with '/'.") - except Exception as e: - print(f"An error occurred: {e}") - - # ROS2 Publisher - self.publisher = self.create_publisher( - JointTrajectory, - self.trajectory_topic_name, - 1 - ) - - while True: - try: - print('+-' * 50) - log_ip = str(input("Enter the target IP on which you want to recieve the log as OSC Messages (or press Enter for default: '127.0.0.1'): ")) - if log_ip == "": - log_ip = "127.0.0.1" - print('--' * 50) - log_port = input("Enter the target port for the log messages (or press Enter for default: 5005): ") - if log_port == "": - log_port = 5005 - else: - log_port = int(log_port) - break - except ValueError: - print("Invalid input. Please enter a valid IP address.") - continue - while True: - try: - print('+-' * 50) - state_ip = str(input("Enter the target IP on which you want to recieve the joint states as OSC Messages (or press Enter for default: '127.0.0.1'): ")) - if state_ip == "": - state_ip = "127.0.0.1" - print('--' * 50) - state_port = input("Enter the target port for the joint state messages (or press Enter for default: 7000): ") - if state_port == "": - state_port = 7000 - else: - state_port = int(state_port) - break - except ValueError: - print("Invalid input. Please enter a valid IP address.") - continue - while True: - try: - print('+-' * 50) - commands_port = input("Enter the port you want to send your commands to (or press Enter for default: 8000): ") - if commands_port == state_port: - print("The commands port must be different from the state port.") - continue - if commands_port == "": - commands_port = 8000 - else: - commands_port = int(commands_port) - break - except ValueError: - print("Invalid input. Please enter a valid port.") - continue - - - osc_startup() - - osc_udp_client(state_ip, state_port, "osc_client") - - osc_udp_client(log_ip, log_port, "osc_log_client") - - osc_udp_server('0.0.0.0', commands_port, "osc_server") - - # Register OSC handler - osc_method("/joint_positions", self.joint_positions_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/joint_position/*", self.joint_position_handler, argscheme=osm.OSCARG_ADDRESS+osm.OSCARG_DATAUNPACK) - osc_method("/tcp_coordinates", self.tcp_coordinates_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/joint_trajectory", self.joint_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/cartesian_trajectory", self.cartesian_trajectory_handler, argscheme=osm.OSCARG_DATAUNPACK) - osc_method("/speed_scaling", self.speed_scaling_handler, argscheme=osm.OSCARG_DATAUNPACK) - print('--' * 50) - while True: - try: - print('+-' * 50) - self.hz = input("Enter the desired refresh frequency (Hz) (or press Enter for default: 100): ") - if self.hz == "": - self.hz = 100 - else: - self.hz = float(self.hz) - break - except ValueError: - print("Invalid input. Please enter a valid number.") - continue - print() - print('=-=' * 50) - print() - print(f'Sending joint states to {state_ip}:{state_port}') - print() - print('=-=' * 50) - print() - print(f'Sending log messages to {log_ip}:{log_port}') - print() - print('=-=' * 50) - print() - print(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') - print() - print('=-=' * 50) - print() - - self.get_logger().info(f"Publishing joint trajectory to {self.trajectory_topic_name}") - self.get_logger().info(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{commands_port}') - self.get_logger().info(f'Sending joint states to {state_ip}:{state_port}') - self.get_logger().info(f'Sending log messages to {log_ip}:{log_port}') - self.create_timer(1/self.hz, self.update_position) # Timer to update the position - self.create_timer(3, self.reset_prev) # reset the previous desired position - - def reset_prev(self): self.previous_desired = None - - def speed_scaling_handler(self, *args): - """Handles incoming OSC messages for speed scaling.""" - try: - if len(args) == 1: - if args[0] < 0: - self.speed_scaling = -float(args[0]) - else: - self.speed_scaling = float(args[0]) - if self.speed_scaling > 1: - self.get_logger().warn(f"speed_scaling_handler: Attention! Speed scaling {self.speed_scaling} is greater than 1!") - self.get_logger().info(f"Speed scaling set to {self.speed_scaling}") - else: - self.get_logger().warn(f"Invalid number of arguments for speed scaling. Expected 1, but got {len(args)}.") - except Exception as e: - self.get_logger().fatal(f"speed_scaling_handler: {e}") - - def joint_trajectory_handler(self, *args): - try: - if len(args[0]) == 6: - points = [[float(j) for j in i] for i in args] - elif len(args[0]) >= 7: - points = [[float(j) for j in i[:6]] for i in args] - self.get_logger().warn(f"joint_trajectory_handler: Duration is not supported for joint trajectory yet. Ignoring duration.") - else: - self.get_logger().warn(f"joint_trajectory_handler: Invalid number of arguments for joint trajectory. Expected {self.n_joints} ([q0, q1, q2, ..., q{self.n_joints}]) or {self.n_joints+1} ([q0, q1, q2, ..., q{self.n_joints}, duration]), but got {len(args[0])}.") - return - - self.desired = ["joint_trajectory"] + points - self.new = True - except Exception as e: - self.get_logger().fatal(f"joint_trajectory_handler: {e}") - - def joint_position_handler(self, address, *args): - """Handles incoming OSC messages for joint positions.""" - try: - joint_name = address.split("/")[-1] - - if joint_name in self.joint_names: - if len(args) == 1: - position = float(args[0]) - index = self.joint_names.index(joint_name) - if self.robot: - if position < self.robot.qlim[0][index]: - position = self.robot.qlim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." - ) - elif position > self.robot.qlim[1][index]: - position = self.robot.qlim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." - ) - else: - if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: - position = self.joint_lim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." - ) - elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: - position = self.joint_lim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." - ) - desired_joint_positions = self.current_joint_positions - desired_joint_positions[index] = position - self.desired = ["joint_positions"] + desired_joint_positions - self.new = True - elif len(args) == 2: - position = float(args[0]) - duration = float(args[1]) - index = self.joint_names.index(joint_name) - if self.robot: - if position < self.robot.qlim[0][index]: - position = self.robot.qlim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[0][index]}." - ) - elif position > self.robot.qlim[1][index]: - position = self.robot.qlim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.robot.qlim[1][index]}." - ) - else: - if self.joint_lim[0][index] is not None and position < self.joint_lim[0][index]: - position = self.joint_lim[0][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[0][index]}." - ) - elif self.joint_lim[1][index] is not None and position > self.joint_lim[1][index]: - position = self.joint_lim[1][index] - self.get_logger().warn( - f"joint_position_handler: Joint '{joint_name}' position {position} is out of bounds. Using {self.joint_lim[1][index]}." - ) - desired_joint_positions = self.current_joint_positions - desired_joint_positions[index] = position - self.desired = ["joint_positions"] + desired_joint_positions + [duration] - self.new = True - else: - self.get_logger().warn(f"joint_position_handler: Invalid number of arguments for joint position. Expected 1, but got {len(args)}.") - else: - self.get_logger().warn(f"joint_position_handler: Joint '{joint_name}' not found in the robot model.") - except Exception as e: - self.get_logger().fatal(f"joint_position_handler: {e}") - - - def cartesian_trajectory_handler(self, *args): - """Handles incoming OSC messages for cartesian trajectory.""" - if self.robot: - try: - if len(args[0]) == 6: - points = [[float(j) for j in i] for i in args] - elif len(args[0]) >= 7: - points = [[float(j) for j in i[:6]] for i in args] - self.get_logger().warn(f"cartesian_trajectory_handler: Duration is not supported for cartesian trajectory yet. Ignoring duration.") - else: - self.get_logger().warn(f"cartesian_trajectory_handler: Invalid number of arguments for cartesian trajectory. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args[0])}.") - return - - self.desired = ["cartesian_trajectory"] + points - self.new = True - except Exception as e: - self.get_logger().fatal(f"cartesian_trajectory_handler: {e}") - else: - self.get_logger().warn("cartesian_trajectory_handler: No robot model provided. Cannot handle cartesian trajectory.") - return - - def joint_positions_handler(self, *args): - """Handles incoming OSC messages for joint positions.""" - try: - if len(args) == len(self.joint_names): - desired_joint_positions = [float(i) for i in list(args)] - elif len(args) == len(self.joint_names) + 1: - desired_joint_positions = [float(i) for i in list(args)] - else: - self.get_logger().warn(f"joint_positions_handler: Invalid number of arguments for joint positions. Expected {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]) or {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]), but got {len(args)}.") - return - - # Check if joint positions exceed limits - if self.robot: - for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): # Exclude duration if present - if position < self.robot.qlim[0][i]: - desired_joint_positions[i] = self.robot.qlim[0][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[0][i]}." - ) - elif position > self.robot.qlim[1][i]: - desired_joint_positions[i] = self.robot.qlim[1][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[1][i]}." - ) - else: - if self.joint_lim: - for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]): - if self.joint_lim[0][i] is not None: - if position < self.joint_lim[0][i]: - desired_joint_positions[i] = self.joint_lim[0][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[0][i]}." - ) - elif self.joint_lim[1][i] is not None: - if position > self.joint_lim[1][i]: - desired_joint_positions[i] = self.joint_lim[1][i] - self.get_logger().warn( - f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.joint_lim[1][i]}." - ) - - self.desired = ["joint_positions"] + desired_joint_positions - self.new = True - except Exception as e: - self.get_logger().fatal(f"joint_positions_handler: {e}") - return - - def tcp_coordinates_handler(self, *args): - # Ensure the desired joint positions are within the specified limits - if self.robot: - try: - if len(args) == 6: - x, y, z, r, p, yaw = [float(i) for i in list(args)] - duration = None - elif len(args) >= 7: - x, y, z, r, p, yaw, duration, *_ = [float(i) for i in list(args)] - else: - self.get_logger().warn(f"tcp_coordinates_handler: Invalid number of arguments for TCP coordinates. Expected 6 ([x, y, z, roll, pitch, yaw]) or 7 ([x, y, z, roll, pitch, yaw, duration]), but got {len(args)}.") - return - - if self.x_limits[0] is not None: - x = max(self.x_limits[0], x) - if self.x_limits[1] is not None: - x = min(self.x_limits[1], x) - if self.y_limits[0] is not None: - y = max(self.y_limits[0], y) - if self.y_limits[1] is not None: - y = min(self.y_limits[1], y) - if self.z_limits[0] is not None: - z = max(self.z_limits[0], z) - if self.z_limits[1] is not None: - z = min(self.z_limits[1], z) - - if x != args[0] or y != args[1] or z != args[2]: - self.get_logger().warn( - f"tcp_coordinates_handler: Desired joint positions adjusted to fit within limits: " - f"x={x}, y={y}, z={z} (original: x={args[0]}, y={args[1]}, z={args[2]})" - ) - - self.desired = ["tcp_coordinates", x, y, z, r, p, yaw, duration] - self.new = True - except Exception as e: - self.get_logger().fatal(f"tcp_coordinates_handler: {e}") - else: - self.get_logger().warn("tcp_coordinates_handler: No robot model provided. Cannot handle TCP coordinates.") - return - - - def joint_states_callback(self, msg: JointState): - """Callback function to handle incoming joint states.""" - try: - msg_time = oscbuildparse.OSCMessage(f"/time", ',s', [str(time.time())]) - osc_send(msg_time, "osc_client") - if not(self.joint_names): self.joint_names = msg.name - joint_position_dict = dict(zip(msg.name, msg.position)) - self.current_joint_positions = [float(joint_position_dict[name]) for name in self.joint_names] - joint_position_dict = dict(zip(msg.name, msg.velocity)) - self.current_joint_velocities = [float(joint_position_dict[name]) for name in self.joint_names] - - if self.robot: - tcp_position = self.robot.fkine(self.current_joint_positions).t - tcp_orientation = self.robot.fkine(self.current_joint_positions).rpy() - - msg_tcp = oscbuildparse.OSCMessage(f"/tcp_coordinates", ',ffffff', [tcp_position[0], tcp_position[1], tcp_position[2], tcp_orientation[0], tcp_orientation[1], tcp_orientation[2]]) - #msg_x = oscbuildparse.OSCMessage(f"/tcp_coordinates/x", ',f', [tcp_position[0]]) - #msg_y = oscbuildparse.OSCMessage(f"/tcp_coordinates/y", ',f', [tcp_position[1]]) - #msg_z = oscbuildparse.OSCMessage(f"/tcp_coordinates/z", ',f', [tcp_position[2]]) - #msg_roll = oscbuildparse.OSCMessage(f"/tcp_coordinates/roll", ',f', [tcp_orientation[0]]) - #msg_pitch = oscbuildparse.OSCMessage(f"/tcp_coordinates/pitch", ',f', [tcp_orientation[1]]) - #msg_yaw = oscbuildparse.OSCMessage(f"/tcp_coordinates/yaw", ',f', [tcp_orientation[2]]) - #bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_tcp, msg_x, msg_y, msg_z, msg_roll, msg_pitch, msg_yaw]) - #osc_send(bun, "osc_client") - osc_send(msg_tcp, "osc_client") - - msg_position = oscbuildparse.OSCMessage(f"/joint_state/position", f',{"f"*self.n_joints}', [i for i in msg.position]) - msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity", f',{"f"*self.n_joints}', [i for i in msg.velocity]) - msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort", f',{"f"*self.n_joints}', [i for i in msg.effort]) - msg_name = oscbuildparse.OSCMessage(f"/joint_state/name", f',{"s"*self.n_joints}', [i for i in msg.name]) - bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_name, msg_position, msg_velocity, msg_effort]) - osc_send(bun, "osc_client") - - #for i, name in enumerate(msg.name): - # msg_position = oscbuildparse.OSCMessage(f"/joint_state/position/{name}", ',f', [msg.position[i]]) - # msg_velocity = oscbuildparse.OSCMessage(f"/joint_state/velocity/{name}", ',f', [msg.velocity[i]]) - # msg_effort = oscbuildparse.OSCMessage(f"/joint_state/effort/{name}", ',f', [msg.effort[i]]) - # bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_position, msg_velocity, msg_effort]) - # osc_send(bun, "osc_client") - - except Exception as e: - self.get_logger().fatal(f"joint_states_callback: {e}") - - def send_joint_positions(self): - self.previous_desired = None - self.new = False - try: - if len(self.desired) == len(self.joint_names) + 2: - desired_joint_positions = [float(i) for i in self.desired[1:-1]] - duration = self.desired[-1] - msg = JointTrajectory() - msg.joint_names = self.joint_names - point = JointTrajectoryPoint() - point.positions = desired_joint_positions - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - self.publisher.publish(msg) - elif len(self.desired) == len(self.joint_names) + 1: - desired_joint_positions = [float(i) for i in self.desired[1:]] - msg = JointTrajectory() - msg.joint_names = self.joint_names - point = JointTrajectoryPoint() - point.positions = desired_joint_positions - duration = 0 - for p1, p2, max_vel in zip(desired_joint_positions, self.current_joint_positions, self.joint_velocity_limits.values()): - duration = max(duration, abs(p1 - p2) / max_vel) - duration = duration + min(2, 0.2*duration) - duration /= self.speed_scaling - if duration == 0: - self.get_logger().warn("send_joint_positions: Duration is 0.") - return - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - self.publisher.publish(msg) - else: - self.get_logger().warn(f"send_joint_positions: Invalid number of arguments for joint positions. Expected {len(self.joint_names)+1} ([q0, q1, q2, ... q{len(self.joint_names)}, duration]) or {len(self.joint_names)} ([q0, q1, q2, ... q{len(self.joint_names)}]), but got {len(self.desired)}.") - return - except Exception as e: - self.get_logger().fatal(f"send_joint_positions: {e}") - return - - def trapezoidal_timestamps(self, num_points,total_duration, flat_ratio = 0.3): - - if num_points == 2: - return [0, total_duration] - n = int(num_points*(1-flat_ratio)/2) - start = np.cos(np.linspace(0, np.pi, n))+2 - end = np.cos(np.linspace(-np.pi, 0, n))+2 - flat = np.ones(num_points-2*n) - - timestamps = np.concatenate((start, flat, end)) - timestamps *= total_duration / timestamps.sum() - timestamps = np.cumsum(timestamps) - - return timestamps.tolist() - - - def send_tcp_coordinates(self): - """Send the desired TCP coordinates to the robot.""" - try: - self.new = False - msg = JointTrajectory() - msg.joint_names = self.joint_names - steps_per_m = 100 - if self.previous_desired == None: - [x,y,z] = self.robot.fkine(self.current_joint_positions).t - [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() - else: - [x,y,z] = self.previous_desired[1:4] - [roll, pitch, yaw] = self.previous_desired[4:-1] - x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] - self.previous_desired = self.desired - steps = int(np.linalg.norm(np.array([x1, y1, z1])- self.robot.fkine(self.current_joint_positions).t) * steps_per_m) - if steps < 2: steps = 2 - cart_traj = [sm.SE3([x+(x1-x)/(steps-1)*i, y+(y1-y)/(steps-1)*i, z+(z1-z)/(steps-1)*i]) * sm.SE3.RPY([roll+(roll1-roll)/(steps-1)*i, pitch+(pitch1-pitch)/(steps-1)*i, yaw+(yaw1-yaw)/(steps-1)*i]) for i in range(steps)] - '''if self.previous_desired: - [x,y,z] = self.previous_desired[1:4] - q0 = sm.UnitQuaternion.RPY(self.previous_desired[3], self.previous_desired[4], self.previous_desired[5]) - else: - [x, y, z] = self.robot.fkine(self.current_joint_positions).t - q0 = sm.UnitQuaternion(self.robot.fkine(self.current_joint_positions).R) - - x1, y1, z1, roll1, pitch1, yaw1 = self.desired[1:7] - q1 = sm.UnitQuaternion.RPY(roll1, pitch1, yaw1) - - steps = int(np.linalg.norm(np.array([x1, y1, z1]) - self.robot.fkine(self.current_joint_positions).t) * steps_per_m) - if steps < 2: - steps = 2 - - cart_traj = [] - for i in range(steps): - alpha = i / (steps - 1) - - # Convert to arrays for robust interpolation if needed - q0_array = q0.vec - q1_array = q1.vec - dot = np.dot(q0_array, q1_array) - dot = np.clip(dot, -1.0, 1.0) - - if abs(dot) > 0.9995: - # Linear interpolation + normalization - q_interp_array = (1 - alpha) * q0_array + alpha * q1_array - q_interp_array = q_interp_array / np.linalg.norm(q_interp_array) - q_interp = sm.UnitQuaternion(q_interp_array) - else: - q_interp = q0.interp(q1, alpha) - - # Interpolate translation - pos_interp = [ - x + (x1 - x) * alpha, - y + (y1 - y) * alpha, - z + (z1 - z) * alpha - ] - - # Compose SE3 transform - cart_traj.append(sm.SE3(pos_interp) * q_interp.SE3())''' - - - - if self.desired[-1]: - timestamps = self.trapezoidal_timestamps(steps, self.desired[-1], 0.8) - for j in range(steps): - sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') - if sol[1] == 1: - fowards = self.robot.fkine_all(sol[0]) - out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) - if np.any(out_of_bounds): - #print(fowards.t) - #indices = np.where(out_of_bounds)[0] - #print(f"indices: {indices}") - self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") - ''' - for i in indices: - try: - print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") - except IndexError: - print(f"index {i} is out of bounds, but no corresponding joint found.") - self.previous_desired_tcp_position = self.desired_tcp_position - ''' - break - duration = timestamps[j] - if duration == 0: - prev_sol = list(sol[0]) - continue - point = JointTrajectoryPoint() - point.positions = list(sol[0]) - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - prev_sol = list(sol[0]) - else: - self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") - prev_sol = self.current_joint_positions - if len(msg.points) == 0: - self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") - self.previous_desired = self.desired - return - msg.header.stamp = self.get_clock().now().to_msg() - self.publisher.publish(msg) - self.previous_desired = self.desired - - - - else: - prev_duration = 0 - ''' - if self.previous_desired == None: - [x,y,z] = self.robot.fkine(self.current_joint_positions).t - [roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy() - else: - [x,y,z] = self.previous_desired[:3] - [roll, pitch, yaw] = self.previous_desired[3:] - ''' - for j in range(steps): - sol = self.robot.ik_LM(cart_traj[j], q0=self.current_joint_positions, mask = self.cost_mask, joint_limits = True, method = 'chan') if j == 0 else self.robot.ik_LM(cart_traj[j], q0=prev_sol, mask = self.cost_mask, joint_limits = True, method = 'chan') - if sol[1] == 1: - fowards = self.robot.fkine_all(sol[0]) - out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] != None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] != None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] != None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] != None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] != None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] != None else False) - if np.any(out_of_bounds): - #print(fowards.t) - #indices = np.where(out_of_bounds)[0] - #print(f"indices: {indices}") - self.get_logger().warn("send_tcp_coordinates: One or more links moved out of bounds!") - ''' - for i in indices: - try: - print(f"Joint {self.robot.links[i].name} is out of bounds: (x,y,z) = {fowards.t[i]}") - except IndexError: - print(f"index {i} is out of bounds, but no corresponding joint found.") - self.previous_desired_tcp_position = self.desired_tcp_position - ''' - break - duration = 0 - prev = self.current_joint_positions if j == 0 else prev_sol - for p1, p2, max_vel in zip(sol[0], prev, self.joint_velocity_limits.values()): - duration = max(duration, abs(p1 - p2) / max_vel)#, 1/self.hz) # as minimun - prev_sol = list(sol[0]) - if duration == 0: - continue - point = JointTrajectoryPoint() - point.positions = list(sol[0]) - duration *= 1.2 - duration /= self.speed_scaling - duration += prev_duration - prev_duration = duration - point.time_from_start.sec = int(duration) - point.time_from_start.nanosec = int((duration - int(duration)) * 1e9) - msg.points.append(point) - else: - self.get_logger().warn(f"send_tcp_coordinates: IK could not find a solution for (x,y,z) = {cart_traj[j].t} and (r,p,y) = {cart_traj[j].rpy()}!") - prev_sol = self.current_joint_positions - if len(msg.points) == 0: - self.get_logger().warn("send_tcp_coordinates: The resulting trajectory is empty. Either the IK failed or the trajectory is too short.") - self.previous_desired = self.desired - return - msg.header.stamp = self.get_clock().now().to_msg() - self.publisher.publish(msg) - self.previous_desired = self.desired - except Exception as e: - self.get_logger().fatal(f"send_tcp_coordinates: {e}") - - def send_joint_trajectory(self): - - try: - self.new = False - viapoints = np.array([i for i in self.desired[1:]]) - msg = JointTrajectory() - msg.joint_names = self.joint_names - traj = rtb.mstraj(viapoints, q0 = self.current_joint_positions ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=[self.speed_scaling*i for i in self.joint_velocity_limits.values()]) - msg.points = [] - for i in range(len(traj.q)): - point = JointTrajectoryPoint() - point.positions = list(traj.q[i]) - point.time_from_start.sec = int(traj.t[i]) - point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) - msg.points.append(point) - msg.header.stamp = self.get_clock().now().to_msg() - self.publisher.publish(msg) - self.previous_desired = None - except Exception as e: - print(f'Error in joint_angles_handler: {e}') - - def send_cartesian_trajectory(self): - - try: - self.new = False - viapoints = np.array([i[:6] for i in self.desired[1:]]) - msg = JointTrajectory() - msg.joint_names = self.joint_names - x,y,z = self.robot.fkine(self.current_joint_positions).t - r,p,yaw = self.robot.fkine(self.current_joint_positions).rpy() - q0 = [x, y, z, r, p, yaw] - traj = rtb.mstraj(viapoints, q0 = q0 ,dt=0.01, tacc=1.5/self.speed_scaling, qdmax=2*self.speed_scaling) - msg.points = [] - prev_sol = self.current_joint_positions - n = max(int(len(traj.q)/200), 1) - for i in range(len(traj.q)): - T = sm.SE3(traj.q[i][:3]) * sm.SE3.RPY(traj.q[i][3:], order='xyz') - sol = self.robot.ik_LM(T, q0=prev_sol, mask = self.cost_mask, joint_limits = True) - if sol[1] == 1: - point = JointTrajectoryPoint() - point.positions = list(sol[0]) - point.time_from_start.sec = int(traj.t[i]) - if traj.t[i] == 0: - continue - point.time_from_start.nanosec = int((traj.t[i] - int(traj.t[i])) * 1e9) - msg.points.append(point) - prev_sol = list(sol[0]) - else: self.get_logger().warn(f"send_cartesian_trajectory: IK could not find a solution for (x,y,z) = {traj.q[i][:3]} and (r,p,y) = {traj.q[i][3:]}!") - msg.header.stamp = self.get_clock().now().to_msg() - msg.points = msg.points[::n] - self.publisher.publish(msg) - self.previous_desired = None - except Exception as e: - print(f'Error in joint_angles_handler: {e}') - - self.previous_desired = None - - def update_position(self): - """Calls the appropriate function to update the robot's position.""" - try: - if self.desired is None or not(self.new): - return - - if self.desired[0] == "joint_positions": - self.new = False - self.send_joint_positions() - return - elif self.desired[0] == "tcp_coordinates": - self.new = False - self.send_tcp_coordinates() - return - elif self.desired[0] == "joint_trajectory": - self.new = False - self.send_joint_trajectory() - return - elif self.desired[0] == "cartesian_trajectory": - self.new = False - self.send_cartesian_trajectory() - return - else: - self.get_logger().warn(f"update_position: Unknown desired type '{self.desired[0]}'.") - return - - - except Exception as e: - self.get_logger().fatal(f'update_position: {e}') - - - def clean_log_string(self, s): - - s = str(s) - - # Remove ANSI escape sequences (e.g., \x1b[31m) - ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') - s = ansi_escape.sub('', s) - - # Replace tabs/newlines with spaces - s = s.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ').replace("'", ' '). replace('"', ' ').replace('`', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ').replace('´', ' ').replace('`', ' ').replace('“', ' ').replace('”', ' ').replace('‘', ' ').replace('’', ' ') - - # Strip leading/trailing whitespace - s = s.strip() - - # Optionally enforce ASCII only (replace non-ASCII chars with '?') - s = s.encode('ascii', 'replace').decode('ascii') - - return s - - - def log_callback(self, msg: Log): - """Callback function to handle incoming log messages.""" - - # Send the log message as an OSC message - msg_log = oscbuildparse.OSCMessage(f"/log/{self.log_dict.get(msg.level, 'UNKNOWN')}", ',isss', [int(msg.level), str(msg.stamp.sec+msg.stamp.nanosec*1e-9) , str(msg.name), self.clean_log_string(msg.msg)]) - osc_send(msg_log, "osc_log_client") - - -def main(): - """Main function to get joint names and start the ROS 2 & OSC system.""" - rclpy.init() - while True: - use_urdf = input("Do you have a URDF file you want to use? (y/n): ").strip().lower() - if use_urdf == 'y': - while True: - robot_urdf = input("Enter the absolute path to the URDF file: ") - if os.path.isfile(robot_urdf): - if not robot_urdf.endswith('.urdf'): - print("The file is not a URDF file. Please enter a valid URDF file.") - continue - break - else: - print("Invalid path. Please enter a valid path to the URDF file.") - tree = ET.parse(robot_urdf) - root = tree.getroot() - robot = rtb.ERobot.URDF(robot_urdf) - joint_names = [joint.get('name') for joint in root.findall('joint') if joint.get('type') == 'revolute' or joint.get('type') == 'continuous' or joint.get('type') == 'prismatic'] - print(robot) - joint_velocity_limits = {} - - # Iterate over all joints in the URDF - for joint in root.findall('.//joint'): - joint_name = joint.get('name') # Get the name of the joint - - # Look for the tag under each joint - limit = joint.find('limit') - - if limit is not None: - # Extract the velocity limit (if it exists) - velocity_limit = limit.get('velocity') - - if velocity_limit is not None: - joint_velocity_limits[joint_name] = float(velocity_limit) - - while True: - try: - print('-+'*50) - print("The cost mask determines which coordinates are used for the IK.\nEach element of the cost mask corresponds to a Cartesian coordinate [x, y, z, roll, pitch, yaw].") - print("The cost mask 111000 means that the IK will only consider translation and no rotaion.") - cost_mask = [int(i) for i in input(f"Enter the cost mask (6 integers (1 or 0), of which <= {robot.n} are 1): ")] - if sum(cost_mask) <= robot.n and len(cost_mask) == 6: - break - else: - print(f"Invalid input. Expected 6 integers of which {robot.n if robot.n < 6 else 6} or less are 1.") - except ValueError: - print("Invalid input. Please enter integers only.") - print(f"The following coordinates will be used for the IK: {[j for i,j in enumerate(['x','y','z','roll','pitch','yaw']) if cost_mask[i]==1]}") - break - elif use_urdf == 'n': - node = JointNameListener() - print("Wainting 10 sec for JointState messages to extract joint names...") - rclpy.spin_once(node) - counter = 0 - while not(node.joint_names): - if counter > 100: - joint_names = None - break - counter+=1 - time.sleep(0.1) - rclpy.spin_once(node) - joint_names = node.joint_names - node.destroy_node() - if joint_names: - correct_names = input("The following joint names were found:\n" + "\n".join(joint_names) + "\nAre these correct? (y/n): ").strip().lower() - while True: - if correct_names == 'y': - break - elif correct_names == 'n': - joint_names = None - break - correct_names = input("Invalid input. Please enter 'y' or 'n'.") - if not(joint_names): - print("Please enter the joint names manually.") - while True: - joint_names = [] - print('-+'*50) - print("Enter the joint names manually one by one. Type 'done' when you are finished:") - print("Attention: The order of the joints is important. It should be the same in which you want to send the joint positions.") - while True: - print('-'*50) - joint_name = input("Enter joint name (or 'done' to finish): ").strip() - if joint_name.lower() == 'done': - break - if joint_name: - joint_names.append(joint_name) - print('-+'*50) - correct_names = input(f"Are those the joint names as defined in your JointTrajectroy recieving Node?: {joint_names}. (y/n)?: ").strip() - if correct_names.lower() == 'y': - break - else: - print("Please re-enter the joint names.") - while True: - try: - joint_velocity_limits = {} - for name in joint_names: - while True: - try: - print('--'*50) - limit = input(f"Enter the velocity limit for joint '{name}': ").strip() - if limit == "": - continue - else: - joint_velocity_limits[name] = float(limit) - break - except ValueError: - print("Invalid input. Please enter a numeric value or press Enter to skip.") - break - except ValueError: - print("Invalid input. Please enter numeric values or leave blank to skip.") - robot = None - cost_mask = None - break - print("Invalid input. Please enter 'y' or 'n'.") - - - node = OSC_ROS2_interface(joint_names, joint_velocity_limits, robot, cost_mask) - - # Run ROS 2 spin, and osc_process will be handled by the timer - try: - rclpy.spin(node) - except KeyboardInterrupt: - print("") - finally: - node.destroy_node() - osc_terminate() - -if __name__ == '__main__': - main() diff --git a/workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 b/workspace/install/osc_ros2/share/ament_index/resource_index/packages/osc_ros2 deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 b/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 deleted file mode 100644 index aff3120..0000000 --- a/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2 +++ /dev/null @@ -1 +0,0 @@ -rclpy \ No newline at end of file diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv deleted file mode 100644 index 79d4c95..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv +++ /dev/null @@ -1 +0,0 @@ -prepend-non-duplicate;AMENT_PREFIX_PATH; diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 deleted file mode 100644 index 26b9997..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em - -colcon_prepend_unique_value AMENT_PREFIX_PATH "$env:COLCON_CURRENT_PREFIX" diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh b/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh deleted file mode 100644 index f3041f6..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh +++ /dev/null @@ -1,3 +0,0 @@ -# generated from colcon_core/shell/template/hook_prepend_value.sh.em - -_colcon_prepend_unique_value AMENT_PREFIX_PATH "$COLCON_CURRENT_PREFIX" diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv deleted file mode 100644 index 257067d..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv +++ /dev/null @@ -1 +0,0 @@ -prepend-non-duplicate;PYTHONPATH;lib/python3.10/site-packages diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 deleted file mode 100644 index caffe83..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1 +++ /dev/null @@ -1,3 +0,0 @@ -# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em - -colcon_prepend_unique_value PYTHONPATH "$env:COLCON_CURRENT_PREFIX\lib/python3.10/site-packages" diff --git a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh b/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh deleted file mode 100644 index 660c348..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh +++ /dev/null @@ -1,3 +0,0 @@ -# generated from colcon_core/shell/template/hook_prepend_value.sh.em - -_colcon_prepend_unique_value PYTHONPATH "$COLCON_CURRENT_PREFIX/lib/python3.10/site-packages" diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.bash b/workspace/install/osc_ros2/share/osc_ros2/package.bash deleted file mode 100644 index 92f5b25..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/package.bash +++ /dev/null @@ -1,31 +0,0 @@ -# generated from colcon_bash/shell/template/package.bash.em - -# This script extends the environment for this package. - -# a bash script is able to determine its own path if necessary -if [ -z "$COLCON_CURRENT_PREFIX" ]; then - # the prefix is two levels up from the package specific share directory - _colcon_package_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`/../.." > /dev/null && pwd)" -else - _colcon_package_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" -fi - -# function to source another script with conditional trace output -# first argument: the path of the script -# additional arguments: arguments to the script -_colcon_package_bash_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$@" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# source sh script of this package -_colcon_package_bash_source_script "$_colcon_package_bash_COLCON_CURRENT_PREFIX/share/osc_ros2/package.sh" - -unset _colcon_package_bash_source_script -unset _colcon_package_bash_COLCON_CURRENT_PREFIX diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.dsv b/workspace/install/osc_ros2/share/osc_ros2/package.dsv deleted file mode 100644 index ece85b1..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/package.dsv +++ /dev/null @@ -1,6 +0,0 @@ -source;share/osc_ros2/hook/pythonpath.ps1 -source;share/osc_ros2/hook/pythonpath.dsv -source;share/osc_ros2/hook/pythonpath.sh -source;share/osc_ros2/hook/ament_prefix_path.ps1 -source;share/osc_ros2/hook/ament_prefix_path.dsv -source;share/osc_ros2/hook/ament_prefix_path.sh diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.ps1 b/workspace/install/osc_ros2/share/osc_ros2/package.ps1 deleted file mode 100644 index ed891bc..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/package.ps1 +++ /dev/null @@ -1,116 +0,0 @@ -# generated from colcon_powershell/shell/template/package.ps1.em - -# function to append a value to a variable -# which uses colons as separators -# duplicates as well as leading separators are avoided -# first argument: the name of the result variable -# second argument: the value to be prepended -function colcon_append_unique_value { - param ( - $_listname, - $_value - ) - - # get values from variable - if (Test-Path Env:$_listname) { - $_values=(Get-Item env:$_listname).Value - } else { - $_values="" - } - $_duplicate="" - # start with no values - $_all_values="" - # iterate over existing values in the variable - if ($_values) { - $_values.Split(";") | ForEach { - # not an empty string - if ($_) { - # not a duplicate of _value - if ($_ -eq $_value) { - $_duplicate="1" - } - if ($_all_values) { - $_all_values="${_all_values};$_" - } else { - $_all_values="$_" - } - } - } - } - # append only non-duplicates - if (!$_duplicate) { - # avoid leading separator - if ($_all_values) { - $_all_values="${_all_values};${_value}" - } else { - $_all_values="${_value}" - } - } - - # export the updated variable - Set-Item env:\$_listname -Value "$_all_values" -} - -# function to prepend a value to a variable -# which uses colons as separators -# duplicates as well as trailing separators are avoided -# first argument: the name of the result variable -# second argument: the value to be prepended -function colcon_prepend_unique_value { - param ( - $_listname, - $_value - ) - - # get values from variable - if (Test-Path Env:$_listname) { - $_values=(Get-Item env:$_listname).Value - } else { - $_values="" - } - # start with the new value - $_all_values="$_value" - # iterate over existing values in the variable - if ($_values) { - $_values.Split(";") | ForEach { - # not an empty string - if ($_) { - # not a duplicate of _value - if ($_ -ne $_value) { - # keep non-duplicate values - $_all_values="${_all_values};$_" - } - } - } - } - # export the updated variable - Set-Item env:\$_listname -Value "$_all_values" -} - -# function to source another script with conditional trace output -# first argument: the path of the script -# additional arguments: arguments to the script -function colcon_package_source_powershell_script { - param ( - $_colcon_package_source_powershell_script - ) - # source script with conditional trace output - if (Test-Path $_colcon_package_source_powershell_script) { - if ($env:COLCON_TRACE) { - echo ". '$_colcon_package_source_powershell_script'" - } - . "$_colcon_package_source_powershell_script" - } else { - Write-Error "not found: '$_colcon_package_source_powershell_script'" - } -} - - -# a powershell script is able to determine its own path -# the prefix is two levels up from the package specific share directory -$env:COLCON_CURRENT_PREFIX=(Get-Item $PSCommandPath).Directory.Parent.Parent.FullName - -colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/osc_ros2/hook/pythonpath.ps1" -colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/osc_ros2/hook/ament_prefix_path.ps1" - -Remove-Item Env:\COLCON_CURRENT_PREFIX diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.sh b/workspace/install/osc_ros2/share/osc_ros2/package.sh deleted file mode 100644 index c4c25c5..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/package.sh +++ /dev/null @@ -1,87 +0,0 @@ -# generated from colcon_core/shell/template/package.sh.em - -# This script extends the environment for this package. - -# function to prepend a value to a variable -# which uses colons as separators -# duplicates as well as trailing separators are avoided -# first argument: the name of the result variable -# second argument: the value to be prepended -_colcon_prepend_unique_value() { - # arguments - _listname="$1" - _value="$2" - - # get values from variable - eval _values=\"\$$_listname\" - # backup the field separator - _colcon_prepend_unique_value_IFS=$IFS - IFS=":" - # start with the new value - _all_values="$_value" - # workaround SH_WORD_SPLIT not being set in zsh - if [ "$(command -v colcon_zsh_convert_to_array)" ]; then - colcon_zsh_convert_to_array _values - fi - # iterate over existing values in the variable - for _item in $_values; do - # ignore empty strings - if [ -z "$_item" ]; then - continue - fi - # ignore duplicates of _value - if [ "$_item" = "$_value" ]; then - continue - fi - # keep non-duplicate values - _all_values="$_all_values:$_item" - done - unset _item - # restore the field separator - IFS=$_colcon_prepend_unique_value_IFS - unset _colcon_prepend_unique_value_IFS - # export the updated variable - eval export $_listname=\"$_all_values\" - unset _all_values - unset _values - - unset _value - unset _listname -} - -# since a plain shell script can't determine its own path when being sourced -# either use the provided COLCON_CURRENT_PREFIX -# or fall back to the build time prefix (if it exists) -_colcon_package_sh_COLCON_CURRENT_PREFIX="/workspace/install/osc_ros2" -if [ -z "$COLCON_CURRENT_PREFIX" ]; then - if [ ! -d "$_colcon_package_sh_COLCON_CURRENT_PREFIX" ]; then - echo "The build time path \"$_colcon_package_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 - unset _colcon_package_sh_COLCON_CURRENT_PREFIX - return 1 - fi - COLCON_CURRENT_PREFIX="$_colcon_package_sh_COLCON_CURRENT_PREFIX" -fi -unset _colcon_package_sh_COLCON_CURRENT_PREFIX - -# function to source another script with conditional trace output -# first argument: the path of the script -# additional arguments: arguments to the script -_colcon_package_sh_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$@" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# source sh hooks -_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/osc_ros2/hook/pythonpath.sh" -_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/osc_ros2/hook/ament_prefix_path.sh" - -unset _colcon_package_sh_source_script -unset COLCON_CURRENT_PREFIX - -# do not unset _colcon_prepend_unique_value since it might be used by non-primary shell hooks diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.xml b/workspace/install/osc_ros2/share/osc_ros2/package.xml deleted file mode 100644 index 086e035..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/package.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - osc_ros2 - 1.0.0 - Creates an interface for communication between OSC and ROS2 - Alexander Schaefer - Apache-2.0 - - rclpy - - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest - - - ament_python - - diff --git a/workspace/install/osc_ros2/share/osc_ros2/package.zsh b/workspace/install/osc_ros2/share/osc_ros2/package.zsh deleted file mode 100644 index b8ae59f..0000000 --- a/workspace/install/osc_ros2/share/osc_ros2/package.zsh +++ /dev/null @@ -1,42 +0,0 @@ -# generated from colcon_zsh/shell/template/package.zsh.em - -# This script extends the environment for this package. - -# a zsh script is able to determine its own path if necessary -if [ -z "$COLCON_CURRENT_PREFIX" ]; then - # the prefix is two levels up from the package specific share directory - _colcon_package_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`/../.." > /dev/null && pwd)" -else - _colcon_package_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" -fi - -# function to source another script with conditional trace output -# first argument: the path of the script -# additional arguments: arguments to the script -_colcon_package_zsh_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$@" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# function to convert array-like strings into arrays -# to workaround SH_WORD_SPLIT not being set -colcon_zsh_convert_to_array() { - local _listname=$1 - local _dollar="$" - local _split="{=" - local _to_array="(\"$_dollar$_split$_listname}\")" - eval $_listname=$_to_array -} - -# source sh script of this package -_colcon_package_zsh_source_script "$_colcon_package_zsh_COLCON_CURRENT_PREFIX/share/osc_ros2/package.sh" -unset convert_zsh_to_array - -unset _colcon_package_zsh_source_script -unset _colcon_package_zsh_COLCON_CURRENT_PREFIX diff --git a/workspace/install/setup.bash b/workspace/install/setup.bash deleted file mode 100644 index 10ea0f7..0000000 --- a/workspace/install/setup.bash +++ /dev/null @@ -1,31 +0,0 @@ -# generated from colcon_bash/shell/template/prefix_chain.bash.em - -# This script extends the environment with the environment of other prefix -# paths which were sourced when this file was generated as well as all packages -# contained in this prefix path. - -# function to source another script with conditional trace output -# first argument: the path of the script -_colcon_prefix_chain_bash_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$1" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# source chained prefixes -# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script -COLCON_CURRENT_PREFIX="/opt/ros/humble" -_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash" - -# source this prefix -# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script -COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)" -_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash" - -unset COLCON_CURRENT_PREFIX -unset _colcon_prefix_chain_bash_source_script diff --git a/workspace/install/setup.ps1 b/workspace/install/setup.ps1 deleted file mode 100644 index 558e9b9..0000000 --- a/workspace/install/setup.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -# generated from colcon_powershell/shell/template/prefix_chain.ps1.em - -# This script extends the environment with the environment of other prefix -# paths which were sourced when this file was generated as well as all packages -# contained in this prefix path. - -# function to source another script with conditional trace output -# first argument: the path of the script -function _colcon_prefix_chain_powershell_source_script { - param ( - $_colcon_prefix_chain_powershell_source_script_param - ) - # source script with conditional trace output - if (Test-Path $_colcon_prefix_chain_powershell_source_script_param) { - if ($env:COLCON_TRACE) { - echo ". '$_colcon_prefix_chain_powershell_source_script_param'" - } - . "$_colcon_prefix_chain_powershell_source_script_param" - } else { - Write-Error "not found: '$_colcon_prefix_chain_powershell_source_script_param'" - } -} - -# source chained prefixes -_colcon_prefix_chain_powershell_source_script "/opt/ros/humble\local_setup.ps1" - -# source this prefix -$env:COLCON_CURRENT_PREFIX=(Split-Path $PSCommandPath -Parent) -_colcon_prefix_chain_powershell_source_script "$env:COLCON_CURRENT_PREFIX\local_setup.ps1" diff --git a/workspace/install/setup.sh b/workspace/install/setup.sh deleted file mode 100644 index 70a84aa..0000000 --- a/workspace/install/setup.sh +++ /dev/null @@ -1,45 +0,0 @@ -# generated from colcon_core/shell/template/prefix_chain.sh.em - -# This script extends the environment with the environment of other prefix -# paths which were sourced when this file was generated as well as all packages -# contained in this prefix path. - -# since a plain shell script can't determine its own path when being sourced -# either use the provided COLCON_CURRENT_PREFIX -# or fall back to the build time prefix (if it exists) -_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX=/workspace/install -if [ ! -z "$COLCON_CURRENT_PREFIX" ]; then - _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" -elif [ ! -d "$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX" ]; then - echo "The build time path \"$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 - unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX - return 1 -fi - -# function to source another script with conditional trace output -# first argument: the path of the script -_colcon_prefix_chain_sh_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$1" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# source chained prefixes -# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script -COLCON_CURRENT_PREFIX="/opt/ros/humble" -_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh" - - -# source this prefix -# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script -COLCON_CURRENT_PREFIX="$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX" -_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh" - -unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX -unset _colcon_prefix_chain_sh_source_script -unset COLCON_CURRENT_PREFIX diff --git a/workspace/install/setup.zsh b/workspace/install/setup.zsh deleted file mode 100644 index 54799fd..0000000 --- a/workspace/install/setup.zsh +++ /dev/null @@ -1,31 +0,0 @@ -# generated from colcon_zsh/shell/template/prefix_chain.zsh.em - -# This script extends the environment with the environment of other prefix -# paths which were sourced when this file was generated as well as all packages -# contained in this prefix path. - -# function to source another script with conditional trace output -# first argument: the path of the script -_colcon_prefix_chain_zsh_source_script() { - if [ -f "$1" ]; then - if [ -n "$COLCON_TRACE" ]; then - echo "# . \"$1\"" - fi - . "$1" - else - echo "not found: \"$1\"" 1>&2 - fi -} - -# source chained prefixes -# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script -COLCON_CURRENT_PREFIX="/opt/ros/humble" -_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh" - -# source this prefix -# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script -COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)" -_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh" - -unset COLCON_CURRENT_PREFIX -unset _colcon_prefix_chain_zsh_source_script diff --git a/workspace/log/COLCON_IGNORE b/workspace/log/COLCON_IGNORE deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/log/build_2025-05-28_04-13-20/events.log b/workspace/log/build_2025-05-28_04-13-20/events.log deleted file mode 100644 index 90db505..0000000 --- a/workspace/log/build_2025-05-28_04-13-20/events.log +++ /dev/null @@ -1,46 +0,0 @@ -[0.000000] (-) TimerEvent: {} -[0.000225] (osc_ros2) JobQueued: {'identifier': 'osc_ros2', 'dependencies': OrderedDict()} -[0.000348] (osc_ros2) JobStarted: {'identifier': 'osc_ros2'} -[0.099483] (-) TimerEvent: {} -[0.199628] (-) TimerEvent: {} -[0.299775] (-) TimerEvent: {} -[0.305620] (osc_ros2) Command: {'cmd': ['/usr/bin/python3', '-W', 'ignore:setup.py install is deprecated', '-W', 'ignore:easy_install command is deprecated', 'setup.py', 'egg_info', '--egg-base', '../../build/osc_ros2', 'build', '--build-base', '/workspace/build/osc_ros2/build', 'install', '--record', '/workspace/build/osc_ros2/install.log', '--single-version-externally-managed', 'install_data'], 'cwd': '/workspace/src/osc_ros2', 'env': {'HOSTNAME': 'ad72f3440b4e', 'SHLVL': '1', 'LD_LIBRARY_PATH': '/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib', 'HOME': '/root', 'OLDPWD': '/', 'ROS_PYTHON_VERSION': '3', 'ROS_DISTRO': 'humble', '_': '/usr/bin/colcon', 'ROS_VERSION': '2', 'TERM': 'xterm', 'ROS_LOCALHOST_ONLY': '0', 'PATH': '/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', 'LANG': 'C.UTF-8', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'AMENT_PREFIX_PATH': '/opt/ros/humble', 'PWD': '/workspace/build/osc_ros2', 'LC_ALL': 'C.UTF-8', 'PYTHONPATH': '/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages', 'COLCON': '1'}, 'shell': False} -[0.399853] (-) TimerEvent: {} -[0.419376] (osc_ros2) StdoutLine: {'line': b'running egg_info\n'} -[0.419581] (osc_ros2) StdoutLine: {'line': b'creating ../../build/osc_ros2/osc_ros2.egg-info\n'} -[0.419665] (osc_ros2) StdoutLine: {'line': b'writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO\n'} -[0.419773] (osc_ros2) StdoutLine: {'line': b'writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt\n'} -[0.419835] (osc_ros2) StdoutLine: {'line': b'writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt\n'} -[0.419888] (osc_ros2) StdoutLine: {'line': b'writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt\n'} -[0.419941] (osc_ros2) StdoutLine: {'line': b'writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt\n'} -[0.420009] (osc_ros2) StdoutLine: {'line': b"writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} -[0.420756] (osc_ros2) StdoutLine: {'line': b"reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} -[0.421180] (osc_ros2) StdoutLine: {'line': b"writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} -[0.421245] (osc_ros2) StdoutLine: {'line': b'running build\n'} -[0.421312] (osc_ros2) StdoutLine: {'line': b'running build_py\n'} -[0.421406] (osc_ros2) StdoutLine: {'line': b'creating /workspace/build/osc_ros2/build\n'} -[0.421504] (osc_ros2) StdoutLine: {'line': b'creating /workspace/build/osc_ros2/build/lib\n'} -[0.421594] (osc_ros2) StdoutLine: {'line': b'creating /workspace/build/osc_ros2/build/lib/osc_ros2\n'} -[0.421645] (osc_ros2) StdoutLine: {'line': b'copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2\n'} -[0.421689] (osc_ros2) StdoutLine: {'line': b'copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2\n'} -[0.421741] (osc_ros2) StdoutLine: {'line': b'running install\n'} -[0.421782] (osc_ros2) StdoutLine: {'line': b'running install_lib\n'} -[0.422031] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2\n'} -[0.422093] (osc_ros2) StdoutLine: {'line': b'copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2\n'} -[0.422151] (osc_ros2) StdoutLine: {'line': b'copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2\n'} -[0.422417] (osc_ros2) StdoutLine: {'line': b'byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc\n'} -[0.422543] (osc_ros2) StdoutLine: {'line': b'byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc\n'} -[0.427108] (osc_ros2) StdoutLine: {'line': b'running install_data\n'} -[0.427204] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/share/ament_index\n'} -[0.427261] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/share/ament_index/resource_index\n'} -[0.427316] (osc_ros2) StdoutLine: {'line': b'creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages\n'} -[0.427366] (osc_ros2) StdoutLine: {'line': b'copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages\n'} -[0.427407] (osc_ros2) StdoutLine: {'line': b'copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2\n'} -[0.427447] (osc_ros2) StdoutLine: {'line': b'running install_egg_info\n'} -[0.428124] (osc_ros2) StdoutLine: {'line': b'Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info\n'} -[0.428731] (osc_ros2) StdoutLine: {'line': b'running install_scripts\n'} -[0.438155] (osc_ros2) StdoutLine: {'line': b'Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2\n'} -[0.438306] (osc_ros2) StdoutLine: {'line': b"writing list of installed files to '/workspace/build/osc_ros2/install.log'\n"} -[0.447607] (osc_ros2) CommandEnded: {'returncode': 0} -[0.452862] (osc_ros2) JobEnded: {'identifier': 'osc_ros2', 'rc': 0} -[0.453237] (-) EventReactorShutdown: {} diff --git a/workspace/log/build_2025-05-28_04-13-20/logger_all.log b/workspace/log/build_2025-05-28_04-13-20/logger_all.log deleted file mode 100644 index d49b047..0000000 --- a/workspace/log/build_2025-05-28_04-13-20/logger_all.log +++ /dev/null @@ -1,126 +0,0 @@ -[0.070s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build'] -[0.070s] DEBUG:colcon:Parsed command line arguments: Namespace(log_base=None, log_level=None, verb_name='build', build_base='build', install_base='install', merge_install=False, symlink_install=False, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=16, event_handlers=None, ignore_user_meta=False, metas=['./colcon.meta'], base_paths=['.'], packages_ignore=None, packages_ignore_regex=None, paths=None, packages_up_to=None, packages_up_to_regex=None, packages_above=None, packages_above_and_dependencies=None, packages_above_depth=None, packages_select_by_dep=None, packages_skip_by_dep=None, packages_skip_up_to=None, packages_select_build_failed=False, packages_skip_build_finished=False, packages_select_test_failures=False, packages_skip_test_passed=False, packages_select=None, packages_skip=None, packages_select_regex=None, packages_skip_regex=None, packages_start=None, packages_end=None, cmake_args=None, cmake_target=None, cmake_target_skip_unavailable=False, cmake_clean_cache=False, cmake_clean_first=False, cmake_force_configure=False, ament_cmake_args=None, catkin_cmake_args=None, catkin_skip_building_tests=False, mixin_files=None, mixin=None, verb_parser=, verb_extension=, main=>, mixin_verb=('build',)) -[0.150s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters -[0.150s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/Gazebo.meta' -[0.151s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/fastrtps.meta' -[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters -[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters -[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters -[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover -[0.151s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover -[0.151s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/workspace' -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install'] -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore' -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install' -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg'] -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg' -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta'] -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta' -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros'] -[0.151s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros' -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python'] -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake' -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python' -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py'] -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py' -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install'] -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore' -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install'] -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore' -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install'] -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore' -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored -[0.157s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ignore', 'ignore_ament_install'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore_ament_install' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_pkg'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_pkg' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_meta'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_meta' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ros'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ros' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['cmake', 'python'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'cmake' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['python_setup_py'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python_setup_py' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ignore', 'ignore_ament_install'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore_ament_install' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_pkg'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_pkg' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_meta'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_meta' -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ros'] -[0.158s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ros' -[0.159s] DEBUG:colcon.colcon_core.package_identification:Package 'src/osc_ros2' with type 'ros.ament_python' and name 'osc_ros2' -[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults -[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover -[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults -[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover -[0.159s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_args' from command line to 'None' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target' from command line to 'None' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target_skip_unavailable' from command line to 'False' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_cache' from command line to 'False' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_first' from command line to 'False' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_force_configure' from command line to 'False' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'ament_cmake_args' from command line to 'None' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_cmake_args' from command line to 'None' -[0.170s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_skip_building_tests' from command line to 'False' -[0.170s] DEBUG:colcon.colcon_core.verb:Building package 'osc_ros2' with the following arguments: {'ament_cmake_args': None, 'build_base': '/workspace/build/osc_ros2', 'catkin_cmake_args': None, 'catkin_skip_building_tests': False, 'cmake_args': None, 'cmake_clean_cache': False, 'cmake_clean_first': False, 'cmake_force_configure': False, 'cmake_target': None, 'cmake_target_skip_unavailable': False, 'install_base': '/workspace/install/osc_ros2', 'merge_install': False, 'path': '/workspace/src/osc_ros2', 'symlink_install': False, 'test_result_base': None} -[0.170s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor -[0.171s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete -[0.171s] INFO:colcon.colcon_ros.task.ament_python.build:Building ROS package in '/workspace/src/osc_ros2' with build type 'ament_python' -[0.171s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'ament_prefix_path') -[0.172s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems -[0.172s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1' -[0.173s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv' -[0.173s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh' -[0.173s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell -[0.173s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment -[0.299s] INFO:colcon.colcon_core.task.python.build:Building Python package in '/workspace/src/osc_ros2' -[0.299s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell -[0.299s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment -[0.477s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -[0.618s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake module files -[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake config files -[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib' -[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' -[0.620s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/pkgconfig/osc_ros2.pc' -[0.621s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/python3.10/site-packages' -[0.621s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'pythonpath') -[0.621s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1' -[0.621s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv' -[0.621s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh' -[0.621s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' -[0.621s] Level 1:colcon.colcon_core.environment:create_environment_scripts_only(osc_ros2) -[0.622s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.ps1' -[0.622s] INFO:colcon.colcon_core.shell:Creating package descriptor '/workspace/install/osc_ros2/share/osc_ros2/package.dsv' -[0.622s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.sh' -[0.623s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.bash' -[0.623s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.zsh' -[0.623s] Level 1:colcon.colcon_core.environment:create_file_with_runtime_dependencies(/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2) -[0.624s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop -[0.624s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed -[0.624s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0' -[0.624s] DEBUG:colcon.colcon_core.event_reactor:joining thread -[0.628s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.notify_send': Could not find 'notify-send' -[0.628s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems -[0.628s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems -[0.628s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2' -[0.628s] DEBUG:colcon.colcon_notification.desktop_notification.notify2:Failed to initialize notify2: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11 -[0.628s] DEBUG:colcon.colcon_core.event_reactor:joined thread -[0.628s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.ps1' -[0.629s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_ps1.py' -[0.629s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.ps1' -[0.630s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.sh' -[0.630s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_sh.py' -[0.630s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.sh' -[0.631s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.bash' -[0.631s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.bash' -[0.632s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.zsh' -[0.632s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.zsh' diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log deleted file mode 100644 index d2728af..0000000 --- a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/command.log +++ /dev/null @@ -1,2 +0,0 @@ -Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stderr.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stderr.log deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log deleted file mode 100644 index 5f28670..0000000 --- a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout.log +++ /dev/null @@ -1,35 +0,0 @@ -running egg_info -creating ../../build/osc_ros2/osc_ros2.egg-info -writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt -writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -running build -running build_py -creating /workspace/build/osc_ros2/build -creating /workspace/build/osc_ros2/build/lib -creating /workspace/build/osc_ros2/build/lib/osc_ros2 -copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 -copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 -running install -running install_lib -creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc -byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc -running install_data -creating /workspace/install/osc_ros2/share/ament_index -creating /workspace/install/osc_ros2/share/ament_index/resource_index -creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages -copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages -copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2 -running install_egg_info -Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info -running install_scripts -Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 -writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log deleted file mode 100644 index 5f28670..0000000 --- a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/stdout_stderr.log +++ /dev/null @@ -1,35 +0,0 @@ -running egg_info -creating ../../build/osc_ros2/osc_ros2.egg-info -writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt -writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -running build -running build_py -creating /workspace/build/osc_ros2/build -creating /workspace/build/osc_ros2/build/lib -creating /workspace/build/osc_ros2/build/lib/osc_ros2 -copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 -copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 -running install -running install_lib -creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc -byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc -running install_data -creating /workspace/install/osc_ros2/share/ament_index -creating /workspace/install/osc_ros2/share/ament_index/resource_index -creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages -copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages -copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2 -running install_egg_info -Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info -running install_scripts -Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 -writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log b/workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log deleted file mode 100644 index 45d9ff9..0000000 --- a/workspace/log/build_2025-05-28_04-13-20/osc_ros2/streams.log +++ /dev/null @@ -1,37 +0,0 @@ -[0.306s] Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -[0.419s] running egg_info -[0.419s] creating ../../build/osc_ros2/osc_ros2.egg-info -[0.419s] writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -[0.419s] writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -[0.420s] writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -[0.420s] writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt -[0.420s] writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -[0.420s] writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -[0.420s] reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -[0.421s] writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -[0.421s] running build -[0.421s] running build_py -[0.421s] creating /workspace/build/osc_ros2/build -[0.421s] creating /workspace/build/osc_ros2/build/lib -[0.421s] creating /workspace/build/osc_ros2/build/lib/osc_ros2 -[0.421s] copying osc_ros2/__init__.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 -[0.421s] copying osc_ros2/osc_ros2.py -> /workspace/build/osc_ros2/build/lib/osc_ros2 -[0.421s] running install -[0.421s] running install_lib -[0.422s] creating /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -[0.422s] copying /workspace/build/osc_ros2/build/lib/osc_ros2/__init__.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -[0.422s] copying /workspace/build/osc_ros2/build/lib/osc_ros2/osc_ros2.py -> /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2 -[0.422s] byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/__init__.py to __init__.cpython-310.pyc -[0.422s] byte-compiling /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2/osc_ros2.py to osc_ros2.cpython-310.pyc -[0.427s] running install_data -[0.427s] creating /workspace/install/osc_ros2/share/ament_index -[0.427s] creating /workspace/install/osc_ros2/share/ament_index/resource_index -[0.427s] creating /workspace/install/osc_ros2/share/ament_index/resource_index/packages -[0.427s] copying resource/osc_ros2 -> /workspace/install/osc_ros2/share/ament_index/resource_index/packages -[0.427s] copying package.xml -> /workspace/install/osc_ros2/share/osc_ros2 -[0.427s] running install_egg_info -[0.428s] Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info -[0.428s] running install_scripts -[0.438s] Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 -[0.438s] writing list of installed files to '/workspace/build/osc_ros2/install.log' -[0.447s] Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/build_2025-05-28_04-16-52/events.log b/workspace/log/build_2025-05-28_04-16-52/events.log deleted file mode 100644 index 0498981..0000000 --- a/workspace/log/build_2025-05-28_04-16-52/events.log +++ /dev/null @@ -1,30 +0,0 @@ -[0.000000] (-) TimerEvent: {} -[0.000210] (osc_ros2) JobQueued: {'identifier': 'osc_ros2', 'dependencies': OrderedDict()} -[0.000283] (osc_ros2) JobStarted: {'identifier': 'osc_ros2'} -[0.099571] (-) TimerEvent: {} -[0.199703] (-) TimerEvent: {} -[0.299829] (-) TimerEvent: {} -[0.305183] (osc_ros2) Command: {'cmd': ['/usr/bin/python3', '-W', 'ignore:setup.py install is deprecated', '-W', 'ignore:easy_install command is deprecated', 'setup.py', 'egg_info', '--egg-base', '../../build/osc_ros2', 'build', '--build-base', '/workspace/build/osc_ros2/build', 'install', '--record', '/workspace/build/osc_ros2/install.log', '--single-version-externally-managed', 'install_data'], 'cwd': '/workspace/src/osc_ros2', 'env': {'HOSTNAME': 'ad72f3440b4e', 'SHLVL': '1', 'LD_LIBRARY_PATH': '/opt/ros/humble/opt/rviz_ogre_vendor/lib:/opt/ros/humble/lib/x86_64-linux-gnu:/opt/ros/humble/lib', 'HOME': '/root', 'OLDPWD': '/', 'ROS_PYTHON_VERSION': '3', 'COLCON_PREFIX_PATH': '/workspace/install', 'ROS_DISTRO': 'humble', '_': '/usr/bin/colcon', 'ROS_VERSION': '2', 'TERM': 'xterm', 'ROS_LOCALHOST_ONLY': '0', 'PATH': '/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', 'LANG': 'C.UTF-8', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'AMENT_PREFIX_PATH': '/workspace/install/osc_ros2:/opt/ros/humble', 'PWD': '/workspace/build/osc_ros2', 'LC_ALL': 'C.UTF-8', 'PYTHONPATH': '/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:/workspace/install/osc_ros2/lib/python3.10/site-packages:/opt/ros/humble/lib/python3.10/site-packages:/opt/ros/humble/local/lib/python3.10/dist-packages', 'COLCON': '1'}, 'shell': False} -[0.399896] (-) TimerEvent: {} -[0.423494] (osc_ros2) StdoutLine: {'line': b'running egg_info\n'} -[0.423758] (osc_ros2) StdoutLine: {'line': b'writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO\n'} -[0.423871] (osc_ros2) StdoutLine: {'line': b'writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt\n'} -[0.423940] (osc_ros2) StdoutLine: {'line': b'writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt\n'} -[0.423995] (osc_ros2) StdoutLine: {'line': b'writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt\n'} -[0.424050] (osc_ros2) StdoutLine: {'line': b'writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt\n'} -[0.424816] (osc_ros2) StdoutLine: {'line': b"reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} -[0.425191] (osc_ros2) StdoutLine: {'line': b"writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt'\n"} -[0.425256] (osc_ros2) StdoutLine: {'line': b'running build\n'} -[0.425303] (osc_ros2) StdoutLine: {'line': b'running build_py\n'} -[0.425468] (osc_ros2) StdoutLine: {'line': b'running install\n'} -[0.425604] (osc_ros2) StdoutLine: {'line': b'running install_lib\n'} -[0.426145] (osc_ros2) StdoutLine: {'line': b'running install_data\n'} -[0.426206] (osc_ros2) StdoutLine: {'line': b'running install_egg_info\n'} -[0.427040] (osc_ros2) StdoutLine: {'line': b"removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it)\n"} -[0.427275] (osc_ros2) StdoutLine: {'line': b'Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info\n'} -[0.427875] (osc_ros2) StdoutLine: {'line': b'running install_scripts\n'} -[0.437908] (osc_ros2) StdoutLine: {'line': b'Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2\n'} -[0.438055] (osc_ros2) StdoutLine: {'line': b"writing list of installed files to '/workspace/build/osc_ros2/install.log'\n"} -[0.447364] (osc_ros2) CommandEnded: {'returncode': 0} -[0.452905] (osc_ros2) JobEnded: {'identifier': 'osc_ros2', 'rc': 0} -[0.453236] (-) EventReactorShutdown: {} diff --git a/workspace/log/build_2025-05-28_04-16-52/logger_all.log b/workspace/log/build_2025-05-28_04-16-52/logger_all.log deleted file mode 100644 index 25c5e99..0000000 --- a/workspace/log/build_2025-05-28_04-16-52/logger_all.log +++ /dev/null @@ -1,126 +0,0 @@ -[0.061s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build'] -[0.061s] DEBUG:colcon:Parsed command line arguments: Namespace(log_base=None, log_level=None, verb_name='build', build_base='build', install_base='install', merge_install=False, symlink_install=False, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=16, event_handlers=None, ignore_user_meta=False, metas=['./colcon.meta'], base_paths=['.'], packages_ignore=None, packages_ignore_regex=None, paths=None, packages_up_to=None, packages_up_to_regex=None, packages_above=None, packages_above_and_dependencies=None, packages_above_depth=None, packages_select_by_dep=None, packages_skip_by_dep=None, packages_skip_up_to=None, packages_select_build_failed=False, packages_skip_build_finished=False, packages_select_test_failures=False, packages_skip_test_passed=False, packages_select=None, packages_skip=None, packages_select_regex=None, packages_skip_regex=None, packages_start=None, packages_end=None, cmake_args=None, cmake_target=None, cmake_target_skip_unavailable=False, cmake_clean_cache=False, cmake_clean_first=False, cmake_force_configure=False, ament_cmake_args=None, catkin_cmake_args=None, catkin_skip_building_tests=False, mixin_files=None, mixin=None, verb_parser=, verb_extension=, main=>, mixin_verb=('build',)) -[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters -[0.138s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/Gazebo.meta' -[0.138s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/fastrtps.meta' -[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters -[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters -[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters -[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover -[0.138s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover -[0.138s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/workspace' -[0.138s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install'] -[0.138s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore' -[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install' -[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg'] -[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg' -[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta'] -[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta' -[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros'] -[0.139s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ignore', 'ignore_ament_install'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore_ament_install' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_pkg'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_pkg' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_meta'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_meta' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ros'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ros' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['cmake', 'python'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'cmake' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['python_setup_py'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python_setup_py' -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ignore', 'ignore_ament_install'] -[0.145s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore' -[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore_ament_install' -[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_pkg'] -[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_pkg' -[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_meta'] -[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_meta' -[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ros'] -[0.146s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ros' -[0.147s] DEBUG:colcon.colcon_core.package_identification:Package 'src/osc_ros2' with type 'ros.ament_python' and name 'osc_ros2' -[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults -[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover -[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults -[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover -[0.147s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_args' from command line to 'None' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target' from command line to 'None' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target_skip_unavailable' from command line to 'False' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_cache' from command line to 'False' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_first' from command line to 'False' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_force_configure' from command line to 'False' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'ament_cmake_args' from command line to 'None' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_cmake_args' from command line to 'None' -[0.157s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_skip_building_tests' from command line to 'False' -[0.157s] DEBUG:colcon.colcon_core.verb:Building package 'osc_ros2' with the following arguments: {'ament_cmake_args': None, 'build_base': '/workspace/build/osc_ros2', 'catkin_cmake_args': None, 'catkin_skip_building_tests': False, 'cmake_args': None, 'cmake_clean_cache': False, 'cmake_clean_first': False, 'cmake_force_configure': False, 'cmake_target': None, 'cmake_target_skip_unavailable': False, 'install_base': '/workspace/install/osc_ros2', 'merge_install': False, 'path': '/workspace/src/osc_ros2', 'symlink_install': False, 'test_result_base': None} -[0.157s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor -[0.158s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete -[0.158s] INFO:colcon.colcon_ros.task.ament_python.build:Building ROS package in '/workspace/src/osc_ros2' with build type 'ament_python' -[0.158s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'ament_prefix_path') -[0.160s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems -[0.160s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1' -[0.160s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv' -[0.160s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh' -[0.161s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell -[0.161s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment -[0.288s] INFO:colcon.colcon_core.task.python.build:Building Python package in '/workspace/src/osc_ros2' -[0.288s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell -[0.288s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment -[0.465s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -[0.605s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -[0.607s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake module files -[0.607s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2' for CMake config files -[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib' -[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' -[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/pkgconfig/osc_ros2.pc' -[0.608s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/lib/python3.10/site-packages' -[0.608s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'pythonpath') -[0.608s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1' -[0.608s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv' -[0.608s] INFO:colcon.colcon_core.shell:Creating environment hook '/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh' -[0.609s] Level 1:colcon.colcon_core.environment:checking '/workspace/install/osc_ros2/bin' -[0.609s] Level 1:colcon.colcon_core.environment:create_environment_scripts_only(osc_ros2) -[0.609s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.ps1' -[0.609s] INFO:colcon.colcon_core.shell:Creating package descriptor '/workspace/install/osc_ros2/share/osc_ros2/package.dsv' -[0.610s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.sh' -[0.610s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.bash' -[0.610s] INFO:colcon.colcon_core.shell:Creating package script '/workspace/install/osc_ros2/share/osc_ros2/package.zsh' -[0.611s] Level 1:colcon.colcon_core.environment:create_file_with_runtime_dependencies(/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2) -[0.611s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop -[0.611s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed -[0.611s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0' -[0.611s] DEBUG:colcon.colcon_core.event_reactor:joining thread -[0.614s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.notify_send': Could not find 'notify-send' -[0.614s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems -[0.614s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems -[0.614s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2' -[0.614s] DEBUG:colcon.colcon_notification.desktop_notification.notify2:Failed to initialize notify2: org.freedesktop.DBus.Error.NotSupported: Unable to autolaunch a dbus-daemon without a $DISPLAY for X11 -[0.614s] DEBUG:colcon.colcon_core.event_reactor:joined thread -[0.615s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.ps1' -[0.615s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_ps1.py' -[0.616s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.ps1' -[0.617s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.sh' -[0.617s] INFO:colcon.colcon_core.shell:Creating prefix util module '/workspace/install/_local_setup_util_sh.py' -[0.617s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.sh' -[0.618s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.bash' -[0.618s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.bash' -[0.619s] INFO:colcon.colcon_core.shell:Creating prefix script '/workspace/install/local_setup.zsh' -[0.619s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/workspace/install/setup.zsh' diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log deleted file mode 100644 index d2728af..0000000 --- a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/command.log +++ /dev/null @@ -1,2 +0,0 @@ -Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stderr.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stderr.log deleted file mode 100644 index e69de29..0000000 diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log deleted file mode 100644 index c53ed50..0000000 --- a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout.log +++ /dev/null @@ -1,19 +0,0 @@ -running egg_info -writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt -writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -running build -running build_py -running install -running install_lib -running install_data -running install_egg_info -removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it) -Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info -running install_scripts -Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 -writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log deleted file mode 100644 index c53ed50..0000000 --- a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/stdout_stderr.log +++ /dev/null @@ -1,19 +0,0 @@ -running egg_info -writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt -writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -running build -running build_py -running install -running install_lib -running install_data -running install_egg_info -removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it) -Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info -running install_scripts -Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 -writing list of installed files to '/workspace/build/osc_ros2/install.log' diff --git a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log b/workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log deleted file mode 100644 index 68e1362..0000000 --- a/workspace/log/build_2025-05-28_04-16-52/osc_ros2/streams.log +++ /dev/null @@ -1,21 +0,0 @@ -[0.306s] Invoking command in '/workspace/src/osc_ros2': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data -[0.423s] running egg_info -[0.423s] writing ../../build/osc_ros2/osc_ros2.egg-info/PKG-INFO -[0.424s] writing dependency_links to ../../build/osc_ros2/osc_ros2.egg-info/dependency_links.txt -[0.424s] writing entry points to ../../build/osc_ros2/osc_ros2.egg-info/entry_points.txt -[0.424s] writing requirements to ../../build/osc_ros2/osc_ros2.egg-info/requires.txt -[0.424s] writing top-level names to ../../build/osc_ros2/osc_ros2.egg-info/top_level.txt -[0.425s] reading manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -[0.425s] writing manifest file '../../build/osc_ros2/osc_ros2.egg-info/SOURCES.txt' -[0.425s] running build -[0.425s] running build_py -[0.425s] running install -[0.425s] running install_lib -[0.426s] running install_data -[0.426s] running install_egg_info -[0.427s] removing '/workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info' (and everything under it) -[0.427s] Copying ../../build/osc_ros2/osc_ros2.egg-info to /workspace/install/osc_ros2/lib/python3.10/site-packages/osc_ros2-1.0.0-py3.10.egg-info -[0.428s] running install_scripts -[0.438s] Installing interface script to /workspace/install/osc_ros2/lib/osc_ros2 -[0.438s] writing list of installed files to '/workspace/build/osc_ros2/install.log' -[0.447s] Invoked command in '/workspace/src/osc_ros2' returned '0': PYTHONPATH=/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/workspace/install/osc_ros2/lib/python3.10/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated -W ignore:easy_install command is deprecated setup.py egg_info --egg-base ../../build/osc_ros2 build --build-base /workspace/build/osc_ros2/build install --record /workspace/build/osc_ros2/install.log --single-version-externally-managed install_data diff --git a/workspace/log/latest b/workspace/log/latest deleted file mode 120000 index b57d247..0000000 --- a/workspace/log/latest +++ /dev/null @@ -1 +0,0 @@ -latest_build \ No newline at end of file diff --git a/workspace/log/latest_build b/workspace/log/latest_build deleted file mode 120000 index 77bb7f9..0000000 --- a/workspace/log/latest_build +++ /dev/null @@ -1 +0,0 @@ -build_2025-05-28_04-16-52 \ No newline at end of file From 21fb3b9b2108e09407a05c94e1ef98370ec52394 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 06:44:37 +0200 Subject: [PATCH 04/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..2d7cd15 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,27 @@ +# This file is a template, and might need editing before it works on your project. +# This is a sample GitLab CI/CD configuration file that should run without any modifications. +# It demonstrates a basic 3 stage CI/CD pipeline. Instead of real tests or scripts, +# it uses echo commands to simulate the pipeline execution. +# +# A pipeline is composed of independent jobs that run scripts, grouped into stages. +# Stages run in sequential order, but jobs within stages run in parallel. +# +# For more information, see: https://docs.gitlab.com/ee/ci/yaml/#stages +# +# You can copy and paste this template into a new `.gitlab-ci.yml` file. +# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword. +# +# To contribute improvements to CI/CD templates, please follow the Development guide at: +# https://docs.gitlab.com/development/cicd/templates/ +# This specific template is located at: +# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml + +stages: # List of stages for jobs, and their order of execution + - sync + +sync-docs-job: # This job runs in the build stage, which runs first. + stage: sync + script: + - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater + - chmod +x confluence-updater + - ./confluence-updater -u $(CU_USER) -s $(CU_SECRET) --fqdn imek.atlassian.net From 82365c784a866da63afb40b1da83912d92b46344 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 06:49:23 +0200 Subject: [PATCH 05/22] [AN] (feat) Adds confluence_updater.yaml --- confluence-updater.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 confluence-updater.yaml diff --git a/confluence-updater.yaml b/confluence-updater.yaml new file mode 100644 index 0000000..b608575 --- /dev/null +++ b/confluence-updater.yaml @@ -0,0 +1,4 @@ +pages: + - filePath: ./README.md + pageId: 1134231563 # You have to create a page first then get its id to link it + # PAGE ID: https://imek.atlassian.net/wiki/spaces/LIGETI/pages//Interface+Documentation \ No newline at end of file From 9f7d6908c16a7f71e7519ca74d4ce4f50d113cec Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 06:53:51 +0200 Subject: [PATCH 06/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2d7cd15..b23b616 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,4 +24,4 @@ sync-docs-job: # This job runs in the build stage, which runs first. script: - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - - ./confluence-updater -u $(CU_USER) -s $(CU_SECRET) --fqdn imek.atlassian.net + - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn imek.atlassian.net From 2056cbce0644bd12946be97f7a9e3d236abb728a Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 06:54:52 +0200 Subject: [PATCH 07/22] Adds curl to CI/CD --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b23b616..dd4cdc8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,6 +22,7 @@ stages: # List of stages for jobs, and their order of execution sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: + - apk add --no-cache curl - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn imek.atlassian.net From d00a8ec01f92109fcf17ffd08935a1173515c43f Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 06:56:12 +0200 Subject: [PATCH 08/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dd4cdc8..74fec4c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ stages: # List of stages for jobs, and their order of execution sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: - - apk add --no-cache curl + - apt-get install curl - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn imek.atlassian.net From 521de925f682d96c5de97503a062915ee0362e26 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 06:56:41 +0200 Subject: [PATCH 09/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 74fec4c..1a9a9b4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,6 +22,7 @@ stages: # List of stages for jobs, and their order of execution sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: + - apt-get update - apt-get install curl - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater From 5f9266791a47522e5b6ed1eeb416af9b52481ced Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 06:58:19 +0200 Subject: [PATCH 10/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1a9a9b4..4000bc1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,8 +22,7 @@ stages: # List of stages for jobs, and their order of execution sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: - - apt-get update - - apt-get install curl + - dnf -y install curl - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn imek.atlassian.net From 284af8e02342460cd9fa942a5c99ae7ab2b187a0 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 07:01:32 +0200 Subject: [PATCH 11/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4000bc1..d9cfebf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,8 @@ stages: # List of stages for jobs, and their order of execution sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: - - dnf -y install curl + - apt update + - apt install -y curl - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn imek.atlassian.net From b1f7ccb40e7accc2924d053ec60dfaf5e51fffb4 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 07:01:50 +0200 Subject: [PATCH 12/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d9cfebf..f13fa0f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ stages: # List of stages for jobs, and their order of execution sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: - - apt update + - apt update -y - apt install -y curl - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater From 28d5fbe232e98ce82f57859dbd16cd135b4aee36 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 07:03:34 +0200 Subject: [PATCH 13/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f13fa0f..b11eb24 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,9 +21,8 @@ stages: # List of stages for jobs, and their order of execution sync-docs-job: # This job runs in the build stage, which runs first. stage: sync + image: curlimages/curl:latest script: - - apt update -y - - apt install -y curl - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn imek.atlassian.net From 2e8605ac2ee7238fd7f80fc578bee7d1c279a2f6 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 07:04:08 +0200 Subject: [PATCH 14/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b11eb24..c6d4720 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,4 +25,4 @@ sync-docs-job: # This job runs in the build stage, which runs first. script: - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn imek.atlassian.net + - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn https://imek.atlassian.net From d4d1e3ad777fdb5f05b1ed81b9d83edaa71351a9 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 07:14:44 +0200 Subject: [PATCH 15/22] Edit confluence-updater.yaml From 4d6e95220b25bffd5fbf7d767f6745132313abaf Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 07:25:12 +0200 Subject: [PATCH 16/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c6d4720..7b60514 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,4 +25,4 @@ sync-docs-job: # This job runs in the build stage, which runs first. script: - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - chmod +x confluence-updater - - ./confluence-updater -u $CU_USER -s $CU_SECRET --fqdn https://imek.atlassian.net + - ./confluence-updater --fqdn https://imek.atlassian.net From c59674639afbe3150126519171ff74a70020e610 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 07:27:28 +0200 Subject: [PATCH 17/22] Edit confluence-updater.yaml --- confluence-updater.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/confluence-updater.yaml b/confluence-updater.yaml index b608575..1e45629 100644 --- a/confluence-updater.yaml +++ b/confluence-updater.yaml @@ -1,4 +1,5 @@ pages: - filePath: ./README.md + overrideTitle: Interface Documentation # Optional pageId: 1134231563 # You have to create a page first then get its id to link it # PAGE ID: https://imek.atlassian.net/wiki/spaces/LIGETI/pages//Interface+Documentation \ No newline at end of file From b89a0fe2942734bb16d624d8b69590b9d7d8f74e Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 08:04:49 +0200 Subject: [PATCH 18/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7b60514..27e1534 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,12 +17,17 @@ # https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml stages: # List of stages for jobs, and their order of execution + - prepare - sync +image: python:3.10 + +prepare-job: + stage: prepare + script: + - pip install confluence.md + sync-docs-job: # This job runs in the build stage, which runs first. stage: sync - image: curlimages/curl:latest script: - - curl -L https://github.com/Kerwood/confluence-updater/releases/latest/download/confluence-updater-x86_64-unknown-linux-musl -o confluence-updater - - chmod +x confluence-updater - - ./confluence-updater --fqdn https://imek.atlassian.net + - confluence.md --user $CU_USER --token $CU_SECRET --url https://imek.atlassian.net update --file README.md --title $(head -n1 README.md | cut -d' ' -f2-) From c92be871362ec8ec9fbfd46dad5f0bdf48d9b59e Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 08:06:05 +0200 Subject: [PATCH 19/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 27e1534..0726063 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,4 +30,4 @@ prepare-job: sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: - - confluence.md --user $CU_USER --token $CU_SECRET --url https://imek.atlassian.net update --file README.md --title $(head -n1 README.md | cut -d' ' -f2-) + - confluence.md --user $CU_USER --token $CU_SECRET --url https://imek.atlassian.net update --file README.md --page_id 1134493746 --title $(head -n1 README.md | cut -d' ' -f2-) From f2a64781c4a413ff96cd0b85041f357d117e1a9c Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 08:07:00 +0200 Subject: [PATCH 20/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0726063..3d8e429 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,17 +17,12 @@ # https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Getting-Started.gitlab-ci.yml stages: # List of stages for jobs, and their order of execution - - prepare - sync image: python:3.10 -prepare-job: - stage: prepare - script: - - pip install confluence.md - sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: + - pip install confluence.md - confluence.md --user $CU_USER --token $CU_SECRET --url https://imek.atlassian.net update --file README.md --page_id 1134493746 --title $(head -n1 README.md | cut -d' ' -f2-) From a5fedc4ec0247ee6d900970e3c756ee3055e0953 Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 08:08:09 +0200 Subject: [PATCH 21/22] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3d8e429..f399d45 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,4 +25,4 @@ sync-docs-job: # This job runs in the build stage, which runs first. stage: sync script: - pip install confluence.md - - confluence.md --user $CU_USER --token $CU_SECRET --url https://imek.atlassian.net update --file README.md --page_id 1134493746 --title $(head -n1 README.md | cut -d' ' -f2-) + - confluence.md --user $CU_USER --token $CU_SECRET --url https://imek.atlassian.net update --file README.md --page_id 1134493746 --title "$(head -n1 README.md | cut -d' ' -f2-)" From b9434a5e7f19a6a8143091bbc4aa40f7e916777a Mon Sep 17 00:00:00 2001 From: Ali Amr Ali Taha Elnwegy Date: Wed, 28 May 2025 08:11:29 +0200 Subject: [PATCH 22/22] Delete confluence-updater.yaml --- confluence-updater.yaml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 confluence-updater.yaml diff --git a/confluence-updater.yaml b/confluence-updater.yaml deleted file mode 100644 index 1e45629..0000000 --- a/confluence-updater.yaml +++ /dev/null @@ -1,5 +0,0 @@ -pages: - - filePath: ./README.md - overrideTitle: Interface Documentation # Optional - pageId: 1134231563 # You have to create a page first then get its id to link it - # PAGE ID: https://imek.atlassian.net/wiki/spaces/LIGETI/pages//Interface+Documentation \ No newline at end of file