Compare commits

...

45 Commits

Author SHA1 Message Date
6ea5c3783d Update README.md 2025-06-11 14:56:54 +02:00
d93b4b8de1 [AN] (fix) Fixes mistake in README 2025-06-08 22:36:08 +02:00
70f78ada2b Merge branch 'main' of TUHH:m-4/ligeti/ros2osc/ba-alexanderschaefer 2025-06-08 22:30:09 +02:00
cdec866f4f Merge branch 'with-config' 2025-06-08 22:29:18 +02:00
ce3f00c3e2 Merge branch 'with-config' into 'main'
With config

See merge request m-4/ligeti/ros2osc/ba-alexanderschaefer!1
2025-06-08 22:22:46 +02:00
6942ff044e Merge branch 'main' into 'with-config'
# Conflicts:
#   workspace/.gitignore
2025-06-08 22:19:41 +02:00
c665883185 Merge branch 'main' into with-config 2025-06-08 22:16:10 +02:00
Ali
4ab2ff3c3b [AN] (feat) Interface with config fully works 2025-06-08 22:13:18 +02:00
Ali
6db7143bd5 [AN] (feat) Successfully writes and reads config 2025-06-08 11:15:59 +02:00
Ali
b45371d39b [AN] (feat) Moves the interactive input to another file 2025-06-08 10:41:50 +02:00
b9434a5e7f Delete confluence-updater.yaml 2025-05-28 08:11:29 +02:00
a5fedc4ec0 Update .gitlab-ci.yml file 2025-05-28 08:08:09 +02:00
f2a64781c4 Update .gitlab-ci.yml file 2025-05-28 08:07:00 +02:00
c92be87136 Update .gitlab-ci.yml file 2025-05-28 08:06:05 +02:00
b89a0fe294 Update .gitlab-ci.yml file 2025-05-28 08:04:49 +02:00
c59674639a Edit confluence-updater.yaml 2025-05-28 07:27:28 +02:00
4d6e95220b Update .gitlab-ci.yml file 2025-05-28 07:25:12 +02:00
d4d1e3ad77 Edit confluence-updater.yaml 2025-05-28 07:14:44 +02:00
2e8605ac2e Update .gitlab-ci.yml file 2025-05-28 07:04:08 +02:00
28d5fbe232 Update .gitlab-ci.yml file 2025-05-28 07:03:34 +02:00
b1f7ccb40e Update .gitlab-ci.yml file 2025-05-28 07:01:50 +02:00
284af8e023 Update .gitlab-ci.yml file 2025-05-28 07:01:32 +02:00
5f9266791a Update .gitlab-ci.yml file 2025-05-28 06:58:19 +02:00
521de925f6 Update .gitlab-ci.yml file 2025-05-28 06:56:41 +02:00
d00a8ec01f Update .gitlab-ci.yml file 2025-05-28 06:56:12 +02:00
2056cbce06 Adds curl to CI/CD 2025-05-28 06:54:52 +02:00
9f7d6908c1 Update .gitlab-ci.yml file 2025-05-28 06:53:51 +02:00
82365c784a [AN] (feat) Adds confluence_updater.yaml 2025-05-28 06:49:23 +02:00
21fb3b9b21 Update .gitlab-ci.yml file 2025-05-28 06:44:37 +02:00
Ali
2d5b63d7e5 [AN] (fix) clean workspace 2025-05-28 06:23:20 +02:00
Ali
5bf594ccea [AN] (fix) relax requirements version 2025-05-28 06:18:43 +02:00
Ali
1fd356e9e1 [AN] (feat) fix docs 2025-05-28 06:05:17 +02:00
Ali
b4abe1eec1 [AN] (feat) Prepare for using configs 2025-05-28 06:00:56 +02:00
Ali
a783bbf2a2 [AN] (fix) Fixed Documentation Error 2025-05-28 05:00:30 +02:00
Ali
3c16c02deb [AN] (fix) Easier Installtion Process 2025-05-28 04:58:57 +02:00
Alexander Schaefer
09644709f9 AS: commit before final presentation 2025-05-26 23:38:12 +02:00
Alexander Schaefer
26e6abd14f AS: clean up 2025-05-25 17:27:47 +02:00
Alexander Schaefer
b4ca5846d8 AS: removing build log install 2025-05-23 18:37:01 +02:00
Alexander Schaefer
87191d9221 AS: adding painting robot folder 2025-05-23 18:36:19 +02:00
Alexander Schaefer
377ceeab15 AS: testing with painting robot 2025-05-23 14:05:33 +02:00
Alexander Schaefer
f1780b673c AS: nothing 2025-05-23 13:34:13 +02:00
Alexander Schaefer
290d853b9b AS: no change 2025-05-23 11:18:15 +02:00
Alexander Schaefer
c725c3a9bf AS: final final commit 2025-05-15 16:15:43 +02:00
Alexander Schaefer
7793fb1a8c AS: final commit 2025-05-15 16:14:04 +02:00
Alexander Schaefer
3e9bff103d AS: cleanup 2025-05-15 15:59:59 +02:00
84 changed files with 1023 additions and 2536 deletions

BIN
.DS_Store vendored

Binary file not shown.

28
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,28 @@
# 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
image: python:3.10
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-)"

View File

@@ -1,4 +1,3 @@
# OSCROS 2 Interface
## Description
@@ -53,13 +52,13 @@ 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 ROS 2_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
```bash
docker run -it --rm -p 6080:6080 --network ros_ursim ursim:latest
docker run --name URSIM -it -p 6080:6080 --network ros_ursim ursim:latest
```
When successfully started this container will print its IP address in the terminal. Note this down:
@@ -73,12 +72,12 @@ IP address of the simulator
On another terminal run
```
docker run -it --rm --network ros_ursim ros2_humble:latest
docker run -it --name ROS --network ros_ursim -p50002-50100:50002-50100 -p5005-8000:5005-8000 -v ./workspace:/workspace ros2_humble:latest
```
Also note the IP address, using `hostname`
```
hostname -i
hostname -I
```
With both containers running we can now open the URSim interface on any browser by going to this address:
@@ -98,7 +97,7 @@ source /opt/ros/humble/setup.bash
Next, launch the driver for communication with the UR simulation, with the IP address of the UR container
```
ros2 launch ur_robot_driver ur_control.launch.py ur_type:=ur10e robot_ip:=<ur.controller.ip.address>
ros2 launch ur_robot_driver ur10e.launch.py robot_ip:=<ur.controller.ip.address>
```
Now, from the VNC interface, we can start the external control program by clicking on the play button in the bottom right of the screen.
@@ -112,7 +111,7 @@ docker ps
Use the appropriate container ID to launch bash within that container. We need the container ID of the ros2_humble container.
```
docker exec -it <container_id> /bin/bash
docker exec -it ROS /bin/bash
```
Once inside, we again must source the ROS 2 environment
@@ -135,26 +134,8 @@ If everything worked, this should either move the robot or complain about it bei
source /opt/ros/humble/setup.bash
```
2. **Install Required Python Libraries**
2. **Build the Workspace**
```bash
pip install numpy==1.22.4 scipy==1.7.3 spatialmath-python==1.1.14 roboticstoolbox-python==1.1.1 osc4py3
```
if an error occurs during installation run:
```bash
python3 -m pip install --upgrade pip setuptools wheel
```
and try again.
If you don't have pip installed run
```bash
sudo apt update
sudo apt install python3-pip
```
3. **Clone and Build the Workspace**
```bash
git clone <this_repo>
cd workspace
colcon build
source install/setup.bash
@@ -163,7 +144,7 @@ If everything worked, this should either move the robot or complain about it bei
Now you should find three new folders in your directory: log, build and install. You can check with `ls`
```bash
workspace/
├── src
├── srcdocker run --name URSIM
├── build
├── install
└── log
@@ -171,9 +152,9 @@ workspace/
4. **Run the Interface**
```bash
```bash
ros2 run osc_ros2 interface
```
```
---
@@ -250,4 +231,4 @@ An example patch in PureData is provided (`/workspace/src/6_DOF_example.pd`) tha
[^1]: [What is Docker?](https://docs.docker.com/get-started/)
[^2]: [WSL2 & Docker Networking](https://stackoverflow.com/questions/65426891)
[^3]: [Cisco VPN and WSL2](https://github.com/Microsoft/WSL/issues/4277)
[^3]: [Cisco VPN and WSL2](https://github.com/Microsoft/WSL/issues/4277)

View File

@@ -2,4 +2,5 @@ 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
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==1.22.4 scipy==1.7.3 spatialmath-python roboticstoolbox-python osc4py3

19
examples/log.py Normal file
View File

@@ -0,0 +1,19 @@
import socket
from ssl import SOCK_STREAM
from oscpy import *
UDP_IP = "172.18.0.1"
UDP_PORT = 5005
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(10*1024)
if "#bundle" in data[:8].decode():
b = Bundle(data)
print(b)
else:
m = Message(data)
print(m)

45
examples/move.py Normal file
View File

@@ -0,0 +1,45 @@
import socket
import time
from oscpy import *
SEND_IP = "172.18.0.2"
SEND_PORT = 8000
RECV_IP = "172.18.0.1"
RECV_PORT = 7000
pub = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sub = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = Message("/joint_positions", [-1]*6).encode()
n = pub.sendto(msg, (SEND_IP, SEND_PORT))
if n > 0:
print(f"INFO: Sent {n} bytes")
time.sleep(10)
msg = Message("/tcp_coordinates", [-1]*6).encode()
n = pub.sendto(msg, (SEND_IP, SEND_PORT))
if n > 0:
print(f"INFO: Sent {n} bytes")
time.sleep(10)
sub.bind((RECV_IP, RECV_PORT))
joint_names = []
found = False
while not found:
data, addr = sub.recvfrom(5*1024)
if "#bundle" in data[:8].decode():
b = Bundle().decode(data)
for msg in b.msgs:
if "/joint_state/name" in msg.address:
joint_names = msg.args
found = True
if joint_names:
msg = Message(f"/joint_position/{joint_names[2]}", [ 0 ])
n = pub.sendto(msg.encode(), (SEND_IP, SEND_PORT))
if n > 0:
print(f"INFO: Sent {n} bytes")

138
examples/oscpy/__init__.py Normal file
View File

@@ -0,0 +1,138 @@
import struct
from typing import final, override
OSC_TYPES = str | int | float | bool | bytes
def get_string_size(data: bytes) -> int:
n = data.find(b'\x00')
n = n + 4 - n%4
return n
def to_osc_string(s: str) -> bytes:
n = len(s)
b = struct.pack(f'{n}s{4 - n%4}x', s.encode())
return b
def to_osc_blob(b: bytes) -> bytes:
n = len(b)
b = struct.pack(f'i{4 - n%4}p', n, b)
return b
def parse_string(data: bytes) -> tuple[bytes, str]:
n = get_string_size(data)
values: tuple[bytes] = struct.unpack(f'>{n}s', data[:n])
value = values[0].split(b"\x00", 1)
return data[n:], value[0].decode()
def parse_float(data: bytes) -> tuple[bytes, float]:
values: tuple[float] = struct.unpack('>f', data[:4])
return data[4:], values[0]
def parse_int(data: bytes) -> tuple[bytes, int]:
values: tuple[int] = struct.unpack('>i', data[:4])
return data[4:], values[0]
def parse_blob(data: bytes) -> tuple[bytes, bytes]:
n_values: tuple[int] = struct.unpack('>i', data[:4])
n: int = n_values[0]
values: tuple[bytes] = struct.unpack(f'>{n}p', data[4:4+n])
return data[4+n:], values[0]
def parse_args(tt: str, data: bytes) -> list[OSC_TYPES]:
tt = tt[1:]
args: list[OSC_TYPES] = []
for c in tt:
match c:
case 's':
data, val = parse_string(data)
args.append(val)
case 'b':
data, val = parse_blob(data)
args.append(val)
case 'f':
data, val = parse_float(data)
args.append(val)
case 'i':
data, val = parse_int(data)
args.append(val)
case _:
print(f"[ERROR]: Got {c}")
return args
def encode_args(args: list[OSC_TYPES]) -> bytes:
encoded = b''
for arg in args:
match arg:
case str(): encoded += to_osc_string(arg)
case float(): encoded += struct.pack('>f', arg)
case int(): encoded += struct.pack('>i', arg)
case bytes(): encoded += to_osc_blob(arg)
return encoded
def parse_type(arg: OSC_TYPES) -> str:
match arg:
case str(): return "s"
case float(): return "f"
case int(): return "i"
case bytes(): return "b"
@final
class Message:
def __init__(self, address: str = "/", args: list[OSC_TYPES] = []):
self.address: str = address
self.type_tags = ","
for arg in args:
self.type_tags = self.type_tags + parse_type(arg)
self.args: list[OSC_TYPES] = args
def decode(self, data: bytes):
data, self.address = parse_string(data)
data, self.type_tags = parse_string(data)
self.args = parse_args(self.type_tags, data)
return self
def encode(self) -> bytes:
msg = to_osc_string(self.address)
msg += to_osc_string(self.type_tags)
msg += encode_args(self.args)
return msg
@override
def __str__(self) -> str:
return f"{self.address} [{self.type_tags}]: {self.args}"
@final
class Bundle:
def __init__(self, time_tag: float = 0.0, msgs: list[Message] = []):
self.header = "#bundle"
self.ttag = time_tag
self.msgs = msgs
def decode(self, data: bytes):
data, self.header = parse_string(data)
data[4:]
data, self.ttag = parse_float(data)
data = data[4:]
self.msgs: list[Message] = []
while len(data) > 0:
data, n = parse_int(data)
msg_data = data[:n]
data = data[n:]
self.msgs.append(Message().decode(msg_data))
return self
def encode(self) -> bytes:
bundle = to_osc_string("#bundle")
bundle += struct.pack('4xf4x', self.ttag)
for msg in self.msgs:
msg_data = msg.encode()
bundle += struct.pack('i', len(msg_data))
bundle += msg_data
return bundle
@override
def __str__(self) -> str:
out = f"{self.header} ({self.ttag}):\n"
for msg in self.msgs:
out += f" - {msg}\n"
return out

27
examples/state.py Normal file
View File

@@ -0,0 +1,27 @@
import socket
import struct
from oscpy import *
UDP_IP = "172.18.0.1"
UDP_PORT = 7000
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
while True:
data, addr = sock.recvfrom(10*1024)
n = get_string_size(data)
[tag] = struct.unpack(f'{n}s', data[:n])
if "#bundle" in tag.decode():
b = Bundle(data)
print("Bundle:")
for msg in b.msgs:
print(" -", msg)
else:
msg = Message(data)
if msg.address == "/time":
msg.args[0] = float(msg.args[0])
print(msg)

7
examples/test.py Normal file
View File

@@ -0,0 +1,7 @@
from oscpy import *
encoded = Message("/", ["test", 0.1, 9]).encode()
new_msg = Message().decode(encoded).encode()
assert(encoded == new_msg)

100
painting_robot/com_node.py Normal file
View File

@@ -0,0 +1,100 @@
import rclpy
from rclpy.node import Node
from std_msgs.msg import Int32
from math import sin, cos, pi
from trajectory_msgs.msg import JointTrajectory
from sensor_msgs.msg import JointState
import time
# Adjusted joint limits based on nearest multiple of step angle
class ArmControllerNode(Node):
def __init__(self):
super().__init__('arm_controller_node')
self.subscription = self.create_subscription(
JointTrajectory,
'/scaled_joint_trajectory_controller/joint_trajectory',
self.joint_trajectory_callback,
100
)
self.dq1_publisher = self.create_publisher(Int32, 'dq1_steps', 10)
self.dq2_publisher = self.create_publisher(Int32, 'dq2_steps', 10)
self.joint_state_publisher = self.create_publisher(JointState, 'joint_states', 10)
self.q1_min = -1.57
self.q1_max = 1
self.q2_min = 0.02
self.q2_max = 2.8
self.current_q1 = 0.00
self.current_q2 = 1.57 # Initial joint angles
steps_per_revolution = 200
gear_ratio = 19.2
self.steps_per_radian = (steps_per_revolution * gear_ratio) / (2 * pi)
def publish_joint_state(self):
joint_state_msg = JointState()
joint_state_msg.header.stamp = self.get_clock().now().to_msg()
joint_state_msg.name = ['joint_1', 'joint_2']
joint_state_msg.position = [self.current_q1, self.current_q2]
joint_state_msg.velocity = [0.0, 0.0]
joint_state_msg.effort = [0.0, 0.0]
self.joint_state_publisher.publish(joint_state_msg)
self.ceate_timer(0.2, self.publish_joint_state)
def joint_trajectory_callback(self, msg):
prev_timetag = 0
for point in msg.points:
timetag = point.time_from_start.sec + point.time_from_start.nanosec / 1e9 - prev_timetag
prev_timetag = point.time_from_start.sec + point.time_from_start.nanosec / 1e9
new_q1=max(min(point.positions[0],self.q1_max),self.q1_min)
new_q2=max(min(point.positions[1],self.q2_max),self.q2_min)
dq1 = new_q1 - self.current_q1
dq2 = new_q2 - self.current_q2
dq1_steps = int(round(dq1 * self.steps_per_radian))
dq2_steps = int(round(dq2 * self.steps_per_radian))
self.current_q1 += dq1_steps/self.steps_per_radian
self.current_q2 += dq2_steps/self.steps_per_radian
dq1_steps_msg = Int32()
dq1_steps_msg.data = dq1_steps
self.dq1_publisher.publish(dq1_steps_msg)
dq2_steps_msg = Int32()
dq2_steps_msg.data = dq2_steps
self.dq2_publisher.publish(dq2_steps_msg)
x= 0.4 * cos(self.current_q1) + 0.25025 * cos(self.current_q1+self.current_q2)
y= 0.4 * sin(self.current_q1) + 0.25025 * sin(self.current_q1+self.current_q2)
self.get_logger().info(f"Steps taken: steps_q1 = {dq1_steps}, steps_q2 = {dq2_steps}")
self.get_logger().info(f"New joint positions (in radians): q1 = {self.current_q1}, q2 = {self.current_q2}")
self.get_logger().info(f"New x_y positions (in meters): x = {x}, y = {y}")
self.get_logger().info(f"Duration: {timetag}")
time.sleep(timetag)
def main(args=None):
try:
rclpy.init(args=args)
node = ArmControllerNode()
rclpy.spin(node)
except KeyboardInterrupt:
print('Communication to painting robot closed')
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,38 @@
<?xml version="1.0"?>
<robot name="painting_robot">
<!-- Base Link -->
<link name="base_link"/>
<!-- Link 1 -->
<link name="link1"/>
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<origin xyz="0 0 0" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit effort="10.0" velocity="0.5" lower="-1.57" upper="1"/>
</joint>
<!-- Link 2 -->
<link name="link2"/>
<joint name="joint2" type="revolute">
<parent link="link1"/>
<child link="link2"/>
<origin xyz="0.4 0 0" rpy="0 0 0"/> <!-- 400.00mm from base -->
<axis xyz="0 0 1"/>
<limit effort="10.0" velocity="0.5" lower="0.02" upper="2.8"/>
</joint>
<!-- Tool endpoint -->
<link name="tool0"/>
<joint name="tool0_fixed_joint" type="fixed">
<parent link="link2"/>
<child link="tool0"/>
<origin xyz="0.25025 0 0" rpy="0 0 0"/> <!-- TCP 250.25mm from joint2 -->
</joint>
</robot>

BIN
workspace/.DS_Store vendored

Binary file not shown.

6
workspace/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
build/*
build/**
install/*
install/**
log/*
log/**

View File

@@ -1 +0,0 @@
colcon

View File

@@ -1 +0,0 @@
0

View File

@@ -1 +0,0 @@
# generated from colcon_core/shell/template/command_prefix.sh.em

View File

@@ -1,20 +0,0 @@
AMENT_PREFIX_PATH=/BA/workspace/install/painting_robot_control:/BA/workspace/install/mock_robot:/BA/workspace/install/joint_info:/BA/workspace/install/joint_control:/BA/workspace/install/osc_ros2:/opt/ros/humble
COLCON=1
COLCON_PREFIX_PATH=/BA/workspace/install
HOME=/root
HOSTNAME=0e38e264ac6b
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=/BA/workspace/src
PATH=/opt/ros/humble/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/BA/workspace/build/osc_ros2
PYTHONPATH=/BA/workspace/build/painting_robot_control:/BA/workspace/install/painting_robot_control/lib/python3.10/site-packages:/BA/workspace/build/mock_robot:/BA/workspace/install/mock_robot/lib/python3.10/site-packages:/BA/workspace/build/joint_info:/BA/workspace/install/joint_info/lib/python3.10/site-packages:/BA/workspace/build/joint_control:/BA/workspace/install/joint_control/lib/python3.10/site-packages:/BA/workspace/build/osc_ros2:/BA/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

View File

@@ -1 +0,0 @@
/BA/workspace/src/osc_ros2/osc_ros2

View File

@@ -1,12 +0,0 @@
Metadata-Version: 2.1
Name: osc-ros2
Version: 0.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

View File

@@ -1,13 +0,0 @@
package.xml
setup.cfg
setup.py
osc_ros2/__init__.py
osc_ros2/osc_ros2.py
osc_ros2.egg-info/PKG-INFO
osc_ros2.egg-info/SOURCES.txt
osc_ros2.egg-info/dependency_links.txt
osc_ros2.egg-info/entry_points.txt
osc_ros2.egg-info/requires.txt
osc_ros2.egg-info/top_level.txt
osc_ros2.egg-info/zip-safe
resource/osc_ros2

View File

@@ -1,3 +0,0 @@
[console_scripts]
interface = osc_ros2.osc_ros2:main

View File

@@ -1,7 +0,0 @@
matplotlib==3.4.3
numpy==1.22.4
osc4py3
roboticstoolbox-python==1.1.1
scipy==1.7.3
setuptools
spatialmath-python==1.1.14

View File

@@ -1 +0,0 @@
osc_ros2

View File

@@ -1 +0,0 @@
/BA/workspace/src/osc_ros2/package.xml

View File

@@ -1,4 +0,0 @@
import sys
if sys.prefix == '/usr':
sys.real_prefix = sys.prefix
sys.prefix = sys.exec_prefix = '/BA/workspace/install/osc_ros2'

View File

@@ -1 +0,0 @@
/BA/workspace/src/osc_ros2/resource/osc_ros2

View File

@@ -1 +0,0 @@
/BA/workspace/src/osc_ros2/setup.cfg

View File

@@ -1 +0,0 @@
/BA/workspace/src/osc_ros2/setup.py

View File

@@ -1 +0,0 @@
prepend-non-duplicate;PYTHONPATH;/BA/workspace/build/osc_ros2

View File

@@ -1,3 +0,0 @@
# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em
colcon_prepend_unique_value PYTHONPATH "$env:COLCON_CURRENT_PREFIX\/BA/workspace/build/osc_ros2"

View File

@@ -1,3 +0,0 @@
# generated from colcon_core/shell/template/hook_prepend_value.sh.em
_colcon_prepend_unique_value PYTHONPATH "/BA/workspace/build/osc_ros2"

View File

@@ -1 +0,0 @@
isolated

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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="/BA/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

View File

@@ -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

View File

@@ -1,33 +0,0 @@
#!/usr/bin/python3
# EASY-INSTALL-ENTRY-SCRIPT: 'osc-ros2','console_scripts','interface'
import re
import sys
# for compatibility with easy_install; see #2198
__requires__ = 'osc-ros2'
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', 'console_scripts', 'interface')())

View File

@@ -1,2 +0,0 @@
/BA/workspace/build/osc_ros2
.

View File

@@ -1 +0,0 @@
/BA/workspace/build/osc_ros2/resource/osc_ros2

View File

@@ -1 +0,0 @@
prepend-non-duplicate;AMENT_PREFIX_PATH;

View File

@@ -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"

View File

@@ -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"

View File

@@ -1 +0,0 @@
prepend-non-duplicate;PYTHONPATH;lib/python3.10/site-packages

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -1,9 +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
source;../../build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.ps1
source;../../build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.dsv
source;../../build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.sh

View File

@@ -1,117 +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"
colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\../../build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.ps1"
Remove-Item Env:\COLCON_CURRENT_PREFIX

View File

@@ -1,88 +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="/BA/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"
_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/../../build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.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

View File

@@ -1 +0,0 @@
/BA/workspace/build/osc_ros2/package.xml

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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=/BA/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

View File

@@ -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

View File

@@ -1,41 +0,0 @@
[0.000000] (-) TimerEvent: {}
[0.002571] (osc_ros2) JobQueued: {'identifier': 'osc_ros2', 'dependencies': OrderedDict()}
[0.002870] (osc_ros2) JobStarted: {'identifier': 'osc_ros2'}
[0.098385] (-) TimerEvent: {}
[0.199359] (-) TimerEvent: {}
[0.303463] (-) TimerEvent: {}
[0.405455] (-) TimerEvent: {}
[0.509296] (-) TimerEvent: {}
[0.611479] (-) TimerEvent: {}
[0.716450] (-) TimerEvent: {}
[0.779654] (osc_ros2) Command: {'cmd': ['/usr/bin/python3', '-W', 'ignore:setup.py install is deprecated', '-W', 'ignore:easy_install command is deprecated', 'setup.py', 'develop', '--editable', '--build-directory', '/BA/workspace/build/osc_ros2/build', '--no-deps', 'symlink_data'], 'cwd': '/BA/workspace/build/osc_ros2', 'env': {'HOSTNAME': '0e38e264ac6b', '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': '/BA/workspace/src', 'ROS_PYTHON_VERSION': '3', 'COLCON_PREFIX_PATH': '/BA/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': '/BA/workspace/install/painting_robot_control:/BA/workspace/install/mock_robot:/BA/workspace/install/joint_info:/BA/workspace/install/joint_control:/BA/workspace/install/osc_ros2:/opt/ros/humble', 'PWD': '/BA/workspace/build/osc_ros2', 'LC_ALL': 'C.UTF-8', 'PYTHONPATH': '/BA/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/BA/workspace/install/osc_ros2/lib/python3.10/site-packages:/BA/workspace/build/painting_robot_control:/BA/workspace/install/painting_robot_control/lib/python3.10/site-packages:/BA/workspace/build/mock_robot:/BA/workspace/install/mock_robot/lib/python3.10/site-packages:/BA/workspace/build/joint_info:/BA/workspace/install/joint_info/lib/python3.10/site-packages:/BA/workspace/build/joint_control:/BA/workspace/install/joint_control/lib/python3.10/site-packages:/BA/workspace/build/osc_ros2:/BA/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.817241] (-) TimerEvent: {}
[0.918255] (-) TimerEvent: {}
[1.022260] (-) TimerEvent: {}
[1.098407] (osc_ros2) StdoutLine: {'line': b'running develop\n'}
[1.123430] (-) TimerEvent: {}
[1.190061] (osc_ros2) StdoutLine: {'line': b'running egg_info\n'}
[1.190684] (osc_ros2) StdoutLine: {'line': b'creating osc_ros2.egg-info\n'}
[1.191366] (osc_ros2) StdoutLine: {'line': b'writing osc_ros2.egg-info/PKG-INFO\n'}
[1.192005] (osc_ros2) StdoutLine: {'line': b'writing dependency_links to osc_ros2.egg-info/dependency_links.txt\n'}
[1.192508] (osc_ros2) StdoutLine: {'line': b'writing entry points to osc_ros2.egg-info/entry_points.txt\n'}
[1.192936] (osc_ros2) StdoutLine: {'line': b'writing requirements to osc_ros2.egg-info/requires.txt\n'}
[1.193414] (osc_ros2) StdoutLine: {'line': b'writing top-level names to osc_ros2.egg-info/top_level.txt\n'}
[1.193787] (osc_ros2) StdoutLine: {'line': b"writing manifest file 'osc_ros2.egg-info/SOURCES.txt'\n"}
[1.196786] (osc_ros2) StdoutLine: {'line': b"reading manifest file 'osc_ros2.egg-info/SOURCES.txt'\n"}
[1.197888] (osc_ros2) StdoutLine: {'line': b"writing manifest file 'osc_ros2.egg-info/SOURCES.txt'\n"}
[1.199336] (osc_ros2) StdoutLine: {'line': b'running build_ext\n'}
[1.199670] (osc_ros2) StdoutLine: {'line': b'Creating /BA/workspace/install/osc_ros2/lib/python3.10/site-packages/osc-ros2.egg-link (link to .)\n'}
[1.200725] (osc_ros2) StdoutLine: {'line': b'Installing interface script to /BA/workspace/install/osc_ros2/lib/osc_ros2\n'}
[1.202175] (osc_ros2) StdoutLine: {'line': b'\n'}
[1.202459] (osc_ros2) StdoutLine: {'line': b'Installed /BA/workspace/build/osc_ros2\n'}
[1.202671] (osc_ros2) StdoutLine: {'line': b'running symlink_data\n'}
[1.203115] (osc_ros2) StdoutLine: {'line': b'creating /BA/workspace/install/osc_ros2/share/ament_index\n'}
[1.203345] (osc_ros2) StdoutLine: {'line': b'creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index\n'}
[1.203713] (osc_ros2) StdoutLine: {'line': b'creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages\n'}
[1.203869] (osc_ros2) StdoutLine: {'line': b'symbolically linking /BA/workspace/build/osc_ros2/resource/osc_ros2 -> /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages\n'}
[1.205307] (osc_ros2) StdoutLine: {'line': b'symbolically linking /BA/workspace/build/osc_ros2/package.xml -> /BA/workspace/install/osc_ros2/share/osc_ros2\n'}
[1.224499] (-) TimerEvent: {}
[1.225266] (osc_ros2) CommandEnded: {'returncode': 0}
[1.246871] (osc_ros2) JobEnded: {'identifier': 'osc_ros2', 'rc': 0}
[1.248599] (-) EventReactorShutdown: {}

View File

@@ -1,134 +0,0 @@
[0.135s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build', '--symlink-install']
[0.136s] 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=True, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=8, 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=<colcon_mixin.mixin.mixin_argument.MixinArgumentDecorator object at 0x7ffffe1ff040>, verb_extension=<colcon_core.verb.build.BuildVerb object at 0x7ffffe2e7fd0>, main=<bound method BuildVerb.main of <colcon_core.verb.build.BuildVerb object at 0x7ffffe2e7fd0>>, mixin_verb=('build',))
[0.259s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters
[0.259s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/Gazebo.meta'
[0.260s] INFO:colcon.colcon_metadata.package_discovery.colcon_meta:Using configuration from '/root/.colcon/metadata/default/fastrtps.meta'
[0.260s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters
[0.260s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters
[0.260s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters
[0.260s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover
[0.260s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover
[0.260s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/BA/workspace'
[0.260s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install']
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore'
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install'
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg']
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg'
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta']
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta'
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros']
[0.261s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros'
[0.272s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python']
[0.272s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake'
[0.272s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python'
[0.272s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py']
[0.272s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py'
[0.273s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install']
[0.273s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore'
[0.273s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored
[0.273s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install']
[0.273s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore'
[0.273s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install']
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore'
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ignore', 'ignore_ament_install']
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore'
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore_ament_install'
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_pkg']
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_pkg'
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_meta']
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_meta'
[0.274s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ros']
[0.275s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ros'
[0.275s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['cmake', 'python']
[0.275s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'cmake'
[0.275s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python'
[0.275s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['python_setup_py']
[0.275s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python_setup_py'
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ignore', 'ignore_ament_install']
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore'
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ignore_ament_install'
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_pkg']
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_pkg'
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['colcon_meta']
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'colcon_meta'
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extensions ['ros']
[0.276s] Level 1:colcon.colcon_core.package_identification:_identify(src/osc_ros2) by extension 'ros'
[0.282s] DEBUG:colcon.colcon_core.package_identification:Package 'src/osc_ros2' with type 'ros.ament_python' and name 'osc_ros2'
[0.282s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults
[0.282s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover
[0.282s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults
[0.282s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover
[0.282s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_args' from command line to 'None'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target' from command line to 'None'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_target_skip_unavailable' from command line to 'False'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_cache' from command line to 'False'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_clean_first' from command line to 'False'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'cmake_force_configure' from command line to 'False'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'ament_cmake_args' from command line to 'None'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_cmake_args' from command line to 'None'
[0.304s] Level 5:colcon.colcon_core.verb:set package 'osc_ros2' build argument 'catkin_skip_building_tests' from command line to 'False'
[0.304s] DEBUG:colcon.colcon_core.verb:Building package 'osc_ros2' with the following arguments: {'ament_cmake_args': None, 'build_base': '/BA/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': '/BA/workspace/install/osc_ros2', 'merge_install': False, 'path': '/BA/workspace/src/osc_ros2', 'symlink_install': True, 'test_result_base': None}
[0.304s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor
[0.308s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete
[0.309s] INFO:colcon.colcon_ros.task.ament_python.build:Building ROS package in '/BA/workspace/src/osc_ros2' with build type 'ament_python'
[0.309s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'ament_prefix_path')
[0.311s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems
[0.312s] INFO:colcon.colcon_core.shell:Creating environment hook '/BA/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.ps1'
[0.314s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/BA/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.dsv'
[0.314s] INFO:colcon.colcon_core.shell:Creating environment hook '/BA/workspace/install/osc_ros2/share/osc_ros2/hook/ament_prefix_path.sh'
[0.315s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell
[0.315s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment
[0.316s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/BA/workspace/install/painting_robot_control' in the environment variable AMENT_PREFIX_PATH doesn't exist
[0.316s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/BA/workspace/install/mock_robot' in the environment variable AMENT_PREFIX_PATH doesn't exist
[0.317s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/BA/workspace/install/joint_info' in the environment variable AMENT_PREFIX_PATH doesn't exist
[0.317s] WARNING:colcon.colcon_ros.prefix_path.ament:The path '/BA/workspace/install/joint_control' in the environment variable AMENT_PREFIX_PATH doesn't exist
[0.630s] INFO:colcon.colcon_core.task.python.build:Building Python package in '/BA/workspace/src/osc_ros2'
[0.631s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell
[0.631s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment
[1.098s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoking command in '/BA/workspace/build/osc_ros2': PYTHONPATH=/BA/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/BA/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 develop --editable --build-directory /BA/workspace/build/osc_ros2/build --no-deps symlink_data
[1.535s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'pythonpath_develop')
[1.535s] INFO:colcon.colcon_core.shell:Creating environment hook '/BA/workspace/build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.ps1'
[1.536s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoked command in '/BA/workspace/build/osc_ros2' returned '0': PYTHONPATH=/BA/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/BA/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 develop --editable --build-directory /BA/workspace/build/osc_ros2/build --no-deps symlink_data
[1.537s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/BA/workspace/build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.dsv'
[1.538s] INFO:colcon.colcon_core.shell:Creating environment hook '/BA/workspace/build/osc_ros2/share/osc_ros2/hook/pythonpath_develop.sh'
[1.541s] Level 1:colcon.colcon_core.environment:checking '/BA/workspace/install/osc_ros2' for CMake module files
[1.543s] Level 1:colcon.colcon_core.environment:checking '/BA/workspace/install/osc_ros2' for CMake config files
[1.547s] Level 1:colcon.colcon_core.environment:checking '/BA/workspace/install/osc_ros2/lib'
[1.547s] Level 1:colcon.colcon_core.environment:checking '/BA/workspace/install/osc_ros2/bin'
[1.547s] Level 1:colcon.colcon_core.environment:checking '/BA/workspace/install/osc_ros2/lib/pkgconfig/osc_ros2.pc'
[1.548s] Level 1:colcon.colcon_core.environment:checking '/BA/workspace/install/osc_ros2/lib/python3.10/site-packages'
[1.548s] Level 1:colcon.colcon_core.shell:create_environment_hook('osc_ros2', 'pythonpath')
[1.548s] INFO:colcon.colcon_core.shell:Creating environment hook '/BA/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.ps1'
[1.549s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/BA/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.dsv'
[1.550s] INFO:colcon.colcon_core.shell:Creating environment hook '/BA/workspace/install/osc_ros2/share/osc_ros2/hook/pythonpath.sh'
[1.550s] Level 1:colcon.colcon_core.environment:checking '/BA/workspace/install/osc_ros2/bin'
[1.550s] Level 1:colcon.colcon_core.environment:create_environment_scripts_only(osc_ros2)
[1.551s] INFO:colcon.colcon_core.shell:Creating package script '/BA/workspace/install/osc_ros2/share/osc_ros2/package.ps1'
[1.552s] INFO:colcon.colcon_core.shell:Creating package descriptor '/BA/workspace/install/osc_ros2/share/osc_ros2/package.dsv'
[1.553s] INFO:colcon.colcon_core.shell:Creating package script '/BA/workspace/install/osc_ros2/share/osc_ros2/package.sh'
[1.553s] INFO:colcon.colcon_core.shell:Creating package script '/BA/workspace/install/osc_ros2/share/osc_ros2/package.bash'
[1.554s] INFO:colcon.colcon_core.shell:Creating package script '/BA/workspace/install/osc_ros2/share/osc_ros2/package.zsh'
[1.555s] Level 1:colcon.colcon_core.environment:create_file_with_runtime_dependencies(/BA/workspace/install/osc_ros2/share/colcon-core/packages/osc_ros2)
[1.557s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop
[1.557s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed
[1.557s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0'
[1.557s] DEBUG:colcon.colcon_core.event_reactor:joining thread
[1.572s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.notify_send': Could not find 'notify-send'
[1.572s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems
[1.572s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems
[1.572s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2'
[1.574s] 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
[1.574s] DEBUG:colcon.colcon_core.event_reactor:joined thread
[1.574s] INFO:colcon.colcon_core.shell:Creating prefix script '/BA/workspace/install/local_setup.ps1'
[1.576s] INFO:colcon.colcon_core.shell:Creating prefix util module '/BA/workspace/install/_local_setup_util_ps1.py'
[1.577s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/BA/workspace/install/setup.ps1'
[1.579s] INFO:colcon.colcon_core.shell:Creating prefix script '/BA/workspace/install/local_setup.sh'
[1.579s] INFO:colcon.colcon_core.shell:Creating prefix util module '/BA/workspace/install/_local_setup_util_sh.py'
[1.580s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/BA/workspace/install/setup.sh'
[1.581s] INFO:colcon.colcon_core.shell:Creating prefix script '/BA/workspace/install/local_setup.bash'
[1.582s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/BA/workspace/install/setup.bash'
[1.583s] INFO:colcon.colcon_core.shell:Creating prefix script '/BA/workspace/install/local_setup.zsh'
[1.585s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/BA/workspace/install/setup.zsh'

View File

@@ -1,2 +0,0 @@
Invoking command in '/BA/workspace/build/osc_ros2': PYTHONPATH=/BA/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/BA/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 develop --editable --build-directory /BA/workspace/build/osc_ros2/build --no-deps symlink_data
Invoked command in '/BA/workspace/build/osc_ros2' returned '0': PYTHONPATH=/BA/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/BA/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 develop --editable --build-directory /BA/workspace/build/osc_ros2/build --no-deps symlink_data

View File

@@ -1,22 +0,0 @@
running develop
running egg_info
creating osc_ros2.egg-info
writing osc_ros2.egg-info/PKG-INFO
writing dependency_links to osc_ros2.egg-info/dependency_links.txt
writing entry points to osc_ros2.egg-info/entry_points.txt
writing requirements to osc_ros2.egg-info/requires.txt
writing top-level names to osc_ros2.egg-info/top_level.txt
writing manifest file 'osc_ros2.egg-info/SOURCES.txt'
reading manifest file 'osc_ros2.egg-info/SOURCES.txt'
writing manifest file 'osc_ros2.egg-info/SOURCES.txt'
running build_ext
Creating /BA/workspace/install/osc_ros2/lib/python3.10/site-packages/osc-ros2.egg-link (link to .)
Installing interface script to /BA/workspace/install/osc_ros2/lib/osc_ros2
Installed /BA/workspace/build/osc_ros2
running symlink_data
creating /BA/workspace/install/osc_ros2/share/ament_index
creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index
creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages
symbolically linking /BA/workspace/build/osc_ros2/resource/osc_ros2 -> /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages
symbolically linking /BA/workspace/build/osc_ros2/package.xml -> /BA/workspace/install/osc_ros2/share/osc_ros2

View File

@@ -1,22 +0,0 @@
running develop
running egg_info
creating osc_ros2.egg-info
writing osc_ros2.egg-info/PKG-INFO
writing dependency_links to osc_ros2.egg-info/dependency_links.txt
writing entry points to osc_ros2.egg-info/entry_points.txt
writing requirements to osc_ros2.egg-info/requires.txt
writing top-level names to osc_ros2.egg-info/top_level.txt
writing manifest file 'osc_ros2.egg-info/SOURCES.txt'
reading manifest file 'osc_ros2.egg-info/SOURCES.txt'
writing manifest file 'osc_ros2.egg-info/SOURCES.txt'
running build_ext
Creating /BA/workspace/install/osc_ros2/lib/python3.10/site-packages/osc-ros2.egg-link (link to .)
Installing interface script to /BA/workspace/install/osc_ros2/lib/osc_ros2
Installed /BA/workspace/build/osc_ros2
running symlink_data
creating /BA/workspace/install/osc_ros2/share/ament_index
creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index
creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages
symbolically linking /BA/workspace/build/osc_ros2/resource/osc_ros2 -> /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages
symbolically linking /BA/workspace/build/osc_ros2/package.xml -> /BA/workspace/install/osc_ros2/share/osc_ros2

View File

@@ -1,24 +0,0 @@
[0.785s] Invoking command in '/BA/workspace/build/osc_ros2': PYTHONPATH=/BA/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/BA/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 develop --editable --build-directory /BA/workspace/build/osc_ros2/build --no-deps symlink_data
[1.097s] running develop
[1.188s] running egg_info
[1.188s] creating osc_ros2.egg-info
[1.189s] writing osc_ros2.egg-info/PKG-INFO
[1.189s] writing dependency_links to osc_ros2.egg-info/dependency_links.txt
[1.190s] writing entry points to osc_ros2.egg-info/entry_points.txt
[1.190s] writing requirements to osc_ros2.egg-info/requires.txt
[1.191s] writing top-level names to osc_ros2.egg-info/top_level.txt
[1.191s] writing manifest file 'osc_ros2.egg-info/SOURCES.txt'
[1.194s] reading manifest file 'osc_ros2.egg-info/SOURCES.txt'
[1.195s] writing manifest file 'osc_ros2.egg-info/SOURCES.txt'
[1.197s] running build_ext
[1.197s] Creating /BA/workspace/install/osc_ros2/lib/python3.10/site-packages/osc-ros2.egg-link (link to .)
[1.198s] Installing interface script to /BA/workspace/install/osc_ros2/lib/osc_ros2
[1.199s]
[1.200s] Installed /BA/workspace/build/osc_ros2
[1.200s] running symlink_data
[1.200s] creating /BA/workspace/install/osc_ros2/share/ament_index
[1.201s] creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index
[1.201s] creating /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages
[1.202s] symbolically linking /BA/workspace/build/osc_ros2/resource/osc_ros2 -> /BA/workspace/install/osc_ros2/share/ament_index/resource_index/packages
[1.204s] symbolically linking /BA/workspace/build/osc_ros2/package.xml -> /BA/workspace/install/osc_ros2/share/osc_ros2
[1.223s] Invoked command in '/BA/workspace/build/osc_ros2' returned '0': PYTHONPATH=/BA/workspace/build/osc_ros2/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/BA/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 develop --editable --build-directory /BA/workspace/build/osc_ros2/build --no-deps symlink_data

View File

@@ -1 +0,0 @@
latest_build

View File

@@ -1 +0,0 @@
build_2025-05-14_17-08-22

Binary file not shown.

BIN
workspace/src/osc_ros2/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,429 @@
import os
import time
import toml
import socket
import xml.etree.ElementTree as ET
from typing import Any
import rclpy
import roboticstoolbox as rtb
from rclpy.node import Node
from sensor_msgs.msg import JointState
class JointNameListener(Node):
joint_names: list[str]|None
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)
def interactive_input() -> tuple[dict[str, Any], rtb.robot]:
config = {}
rconf = {}
nconf = {}
robot = None
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:
rconf["urdf"] = input("Enter the absolute path to the URDF file: ")
if os.path.isfile(rconf["urdf"]):
if not rconf["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(rconf["urdf"])
root = tree.getroot()
robot = rtb.ERobot.URDF(rconf["urdf"])
rconf["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)
rconf["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 <limit> 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:
rconf["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_string = input(f"Enter the cost mask (6 integers (1 or 0), of which <= {robot.n} are 1): ")
rconf["cost_mask"] = [int(i) for i in cost_mask_string]
if sum(rconf["cost_mask"]) <= robot.n and len(rconf["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 rconf['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:
rconf["joint_names"] = None
break
counter+=1
time.sleep(0.1)
rclpy.spin_once(node)
rconf["joint_names"] = node.joint_names
node.destroy_node()
if rconf["joint_names"]:
correct_names = input("The following joint names were found:\n" + "\n".join(rconf["joint_names"]) + "\nAre these correct? (y/n): ").strip().lower()
while True:
if correct_names == 'y':
break
elif correct_names == 'n':
rconf["joint_names"] = None
break
correct_names = input("Invalid input. Please enter 'y' or 'n'.")
if not(rconf["joint_names"]):
print("Please enter the joint names manually.")
while True:
rconf["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:
rconf["joint_names"].append(joint_name)
print('-+'*50)
correct_names = input(f"Are those the joint names as defined in your JointTrajectroy recieving Node?: {rconf['joint_names']}. (y/n)?: ").strip()
if correct_names.lower() == 'y':
break
else:
print("Please re-enter the joint names.")
while True:
try:
rconf["joint_velocity_limits"] = {}
for name in rconf["joint_names"]:
while True:
try:
print('--'*50)
limit = input(f"Enter the velocity limit for joint '{name}': ").strip()
if limit == "":
continue
else:
rconf["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
rconf["cost_mask"] = None
break
print("Invalid input. Please enter 'y' or 'n'.")
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:
rconf["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()]
rconf["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()]
rconf["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(rconf["x_limits"]) != 2 or len(rconf["y_limits"]) != 2 or len(rconf["z_limits"]) != 2:
print("Invalid input. Please enter exactly two values (or leave blank) for each limit.")
continue
if (rconf["x_limits"][0] is not None and rconf["x_limits"][1] is not None and rconf["x_limits"][0] >= rconf["x_limits"][1]) or \
(rconf["y_limits"][0] is not None and rconf["y_limits"][1] is not None and rconf["y_limits"][0] >= rconf["y_limits"][1]) or \
(rconf["z_limits"][0] is not None and rconf["z_limits"][1] is not None and rconf["z_limits"][0] >= rconf["z_limits"][1]):
print("Invalid input. Lower limit must be less than upper limit for each axis.")
continue
print("Current limits:")
print(f"x: {rconf['x_limits']}")
print(f"y: {rconf['y_limits']}")
print(f"z: {rconf['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':
rconf["x_limits"] = [None, None]
rconf["y_limits"] = [None, None]
rconf["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:
rconf["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()]
rconf["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()]
rconf["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(rconf["x_limits_workspace"]) != 2 or len(rconf["y_limits_workspace"]) != 2 or len(rconf["z_limits_workspace"]) != 2:
print("Invalid input. Please enter exactly two values (or leave blank) for each limit.")
continue
if (rconf["x_limits_workspace"][0] is not None and rconf["x_limits_workspace"][1] is not None and rconf["x_limits_workspace"][0] >= rconf["x_limits_workspace"][1]) or \
(rconf["y_limits_workspace"][0] is not None and rconf["y_limits_workspace"][1] is not None and rconf["y_limits_workspace"][0] >= rconf["y_limits_workspace"][1]) or \
(rconf["z_limits_workspace"][0] is not None and rconf["z_limits_workspace"][1] is not None and rconf["z_limits_workspace"][0] >= rconf["z_limits_workspace"][1]):
print("Invalid input. Lower limit must be less than upper limit for each axis.")
continue
print("Current limits:")
print(f"x: {rconf['x_limits_workspace']}")
print(f"y: {rconf['y_limits_workspace']}")
print(f"z: {rconf['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':
rconf["x_limits_workspace"] = [None, None]
rconf["y_limits_workspace"] = [None, None]
rconf["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
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(rconf["joint_names"])):
while True:
try:
lim = robot.qlim.copy()
# Find the link corresponding to the joint name
print("-" * 50)
print(f"Current position limits for joint '{rconf['joint_names'][i]}': [{robot.qlim[0][i]} {robot.qlim[1][i]}] rad")
lower_limit = input(f"Enter the new lower limit for joint '{rconf['joint_names'][i]}' (or press Enter to keep current): ").strip()
upper_limit = input(f"Enter the new upper limit for joint '{rconf['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 is not None:
if lower_limit<lim[0][i]:
while True:
sure = input(f"Are you sure you want to set the lower limit to {lower_limit} rad which is less than the default limit {lim[0][i]} (y/n)?: ").strip().lower()
if sure == 'y':
lim[0][i] = float(lower_limit)
break
elif sure == 'n':
print("Lower limit not changed.")
break
print("Invalid input. Please enter 'y' or 'n'.")
else:
lim[0][i] = float(lower_limit)
if upper_limit is not None:
if upper_limit>lim[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)
robot.qlim = lim
print(f"New limits for joint '{rconf['joint_names'][i]}': [{robot.qlim[0][i]} {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()
n_joints = len(rconf["joint_names"])
if update_limits == 'y':
rconf["joint_lim"] = [[]*n_joints,[]*n_joints]
for i, joint in enumerate(rconf["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
rconf["joint_lim"][0][i] = float(lower_limit) if lower_limit!="" else None
rconf["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: {rconf["joint_lim"][0]}\n upper: {rconf["joint_lim"][1]}')
break
elif update_limits == 'n':
rconf["joint_lim"] = None
break
print("Invalid input. Please enter 'y' or 'n'.")
while True:
try:
print('+-' * 50)
rconf["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 rconf["trajectory_topic_name"] == "":
rconf["trajectory_topic_name"] = '/scaled_joint_trajectory_controller/joint_trajectory'
break
elif rconf["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}")
print('--' * 50)
while True:
try:
print('+-' * 50)
rconf["hz"] = input("Enter the desired refresh frequency (Hz) (or press Enter for default: 100): ")
if rconf["hz"] == "":
rconf["hz"] = 100
else:
rconf["hz"] = float(rconf["hz"])
break
except ValueError:
print("Invalid input. Please enter a valid number.")
continue
while True:
try:
print('+-' * 50)
nconf["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 nconf["log_ip"] == "":
nconf["log_ip"] = "127.0.0.1"
print('--' * 50)
nconf["log_port"] = input("Enter the target port for the log messages (or press Enter for default: 5005): ")
if nconf["log_port"] == "":
nconf["log_port"] = 5005
else:
nconf["log_port"] = int(nconf["log_port"])
break
except ValueError:
print("Invalid input. Please enter a valid IP address.")
continue
while True:
try:
print('+-' * 50)
nconf["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 nconf["state_ip"] == "":
nconf["state_ip"] = "127.0.0.1"
print('--' * 50)
nconf["state_port"] = input("Enter the target port for the joint state messages (or press Enter for default: 7000): ")
if nconf["state_port"] == "":
nconf["state_port"] = 7000
else:
nconf["state_port"] = int(nconf["state_port"])
break
except ValueError:
print("Invalid input. Please enter a valid IP address.")
continue
while True:
try:
print('+-' * 50)
nconf["commands_port"] = input("Enter the port you want to send your commands to (or press Enter for default: 8000): ")
if nconf["commands_port"] == nconf["state_port"]:
print("The commands port must be different from the state port.")
continue
if nconf["commands_port"] == "":
nconf["commands_port"] = 8000
else:
nconf["commands_port"] = int(nconf["commands_port"])
break
except ValueError:
print("Invalid input. Please enter a valid port.")
continue
print()
print('=-=' * 50)
print()
print(f"Sending joint state's' to {nconf['state_ip']}:{nconf['state_port']}")
print()
print('=-=' * 50)
print()
print(f"Sending log messages to {nconf['log_ip']}:{nconf['log_port']}")
print()
print('=-=' * 50)
print()
print(f"Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{nconf['commands_port']}")
print()
print('=-=' * 50)
print()
config["robot"] = rconf
config["network"] = nconf
while True:
save_config = input("Do you want to save this interface? (y/n): ").strip().lower()
if save_config == "y":
config_path = input("Where do you want to save the config?: ").strip()
with open(f"{config_path}.toml", "w") as f:
toml.dump(config, f)
break
elif save_config == "n":
print("Will not be saving config")
print("Invalid input. Please enter 'y' or 'n'.")
return config, robot

View File

@@ -1,60 +1,59 @@
#ruff: noqa: F403, F405
import rclpy
import argparse
import toml
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
from osc_ros2.interactive_input import interactive_input
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):
def __init__(self, robot, config):
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.joint_names = config["robot"]["joint_names"]
self.joint_velocity_limits = config["robot"]["joint_velocity_limits"]
self.cost_mask = config["robot"]["cost_mask"]
self.trajectory_topic_name = config["robot"]["trajectory_topic_name"]
self.hz = config["robot"]["hz"]
self.state_ip = config["network"]["state_ip"]
self.state_port = config["network"]["state_port"]
self.log_ip = config["network"]["log_ip"]
self.log_port = config["network"]["log_port"]
self.commands_port = config["network"]["commands_port"]
float_or_none = lambda v: None if "None" in v else float(v)
self.x_limits = list(map(float_or_none, config["robot"]["x_limits"]))
self.y_limits = list(map(float_or_none, config["robot"]["y_limits"]))
self.z_limits = list(map(float_or_none, config["robot"]["z_limits"]))
self.x_limits_workspace = list(map(float_or_none, config["robot"]["x_limits_workspace"]))
self.y_limits_workspace = list(map(float_or_none, config["robot"]["y_limits_workspace"]))
self.z_limits_workspace = list(map(float_or_none, config["robot"]["z_limits_workspace"]))
self.robot = robot
self.desired = None
self.previous_desired = None
@@ -67,220 +66,17 @@ class OSC_ROS2_interface(Node):
}
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 limit 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 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 = [None, None]
self.y_limits = [None, None]
self.z_limits = [None, None]
break
print("Invalid input. Please enter 'y' or 'n'.")
# Ask the user if they want to set new joint limits
while True:
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_limit<lim[0][i]:
while True:
sure = input(f"Are you sure you want to set the lower limit to {lower_limit} rad which is less than the default limit {lim[0][i]} (y/n)?: ").strip().lower()
if sure == 'y':
lim[0][i] = float(lower_limit)
break
elif sure == 'n':
print("Lower limit not changed.")
break
print("Invalid input. Please enter 'y' or 'n'.")
else: lim[0][i] = float(lower_limit)
if upper_limit!=None:
if upper_limit>lim[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 to keep current): ").strip()
upper_limit = input(f"Enter the new upper limit for joint '{joint}' (or press Enter to keep current): ").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.")
break
elif update_limits == 'n':
self.joint_lim = None
print("Invalid input. Please enter 'y' or 'n'.")
print(f'New limits for joint:\n lower: {self.joint_lim[0]}\n upper: {self.joint_lim[1]}')
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}")
self.n_joints = len(self.joint_names)
# 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")
osc_udp_client(self.state_ip, self.state_port, "osc_client")
osc_udp_client(self.log_ip, self.log_port, "osc_log_client")
osc_udp_server('0.0.0.0', self.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)
@@ -288,39 +84,10 @@ class OSC_ROS2_interface(Node):
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.get_logger().info(f'Ready to receive OSC messages on {socket.gethostbyname(socket.gethostname())}:{self.commands_port}')
self.get_logger().info(f'Sending joint states to {self.state_ip}:{self.state_port}')
self.get_logger().info(f'Sending log messages to {self.log_ip}:{self.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
@@ -343,13 +110,24 @@ class OSC_ROS2_interface(Node):
self.get_logger().fatal(f"speed_scaling_handler: {e}")
def joint_trajectory_handler(self, *args):
pass
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("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])
@@ -416,12 +194,23 @@ class OSC_ROS2_interface(Node):
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:
pass
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("cartesian_trajectory_handler: Duration is not supported for cartesian trajectory yet. Ignoring duration.")
else:
self.get_logger().warn("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
@@ -436,7 +225,6 @@ class OSC_ROS2_interface(Node):
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
@@ -451,18 +239,20 @@ class OSC_ROS2_interface(Node):
f"joint_positions_handler: Joint '{self.joint_names[i]}' position {position} is out of bounds. Using {self.robot.qlim[1][i]}."
)
else:
for i, position in enumerate(desired_joint_positions[:len(self.joint_names)]):
if self.joint_lim[0][i] is not None and 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 and 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]}."
)
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:
@@ -481,7 +271,6 @@ class OSC_ROS2_interface(Node):
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:
@@ -494,13 +283,11 @@ class OSC_ROS2_interface(Node):
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:
@@ -509,23 +296,21 @@ class OSC_ROS2_interface(Node):
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())])
msg_time = oscbuildparse.OSCMessage("/time", ',s', [str(time.time())])
osc_send(msg_time, "osc_client")
if not(self.joint_names): self.joint_names = msg.name
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_tcp = oscbuildparse.OSCMessage("/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]])
@@ -535,21 +320,18 @@ class OSC_ROS2_interface(Node):
#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])
msg_position = oscbuildparse.OSCMessage("/joint_state/position", f',{"f"*self.n_joints}', [i for i in msg.position])
msg_velocity = oscbuildparse.OSCMessage("/joint_state/velocity", f',{"f"*self.n_joints}', [i for i in msg.velocity])
msg_effort = oscbuildparse.OSCMessage("/joint_state/effort", f',{"f"*self.n_joints}', [i for i in msg.effort])
msg_name = oscbuildparse.OSCMessage("/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}")
@@ -594,21 +376,17 @@ class OSC_ROS2_interface(Node):
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:
@@ -616,7 +394,7 @@ class OSC_ROS2_interface(Node):
msg = JointTrajectory()
msg.joint_names = self.joint_names
steps_per_m = 100
if self.previous_desired == None:
if self.previous_desired is None:
[x,y,z] = self.robot.fkine(self.current_joint_positions).t
[roll, pitch, yaw] = self.robot.fkine(self.current_joint_positions).rpy()
else:
@@ -625,7 +403,8 @@ class OSC_ROS2_interface(Node):
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
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]
@@ -668,16 +447,13 @@ class OSC_ROS2_interface(Node):
# 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[1] if self.x_limits[1] != None else False) | (fowards.t[1:,0] < self.x_limits[0] if self.x_limits[0] != None else False) | (fowards.t[1:,1] > self.y_limits[1] if self.y_limits[1] != None else False) | (fowards.t[1:,1] < self.y_limits[0] if self.y_limits[0] != None else False) | (fowards.t[1:,2] > self.z_limits[1] if self.z_limits[1] != None else False) | (fowards.t[1:,2] < self.z_limits[0] if self.z_limits[0] != None else False)
out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] is not None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] is not None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] is not None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] is not None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] is not None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] is not None else False)
if np.any(out_of_bounds):
#print(fowards.t)
#indices = np.where(out_of_bounds)[0]
@@ -712,9 +488,6 @@ class OSC_ROS2_interface(Node):
msg.header.stamp = self.get_clock().now().to_msg()
self.publisher.publish(msg)
self.previous_desired = self.desired
else:
prev_duration = 0
'''
@@ -729,7 +502,7 @@ class OSC_ROS2_interface(Node):
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[1] if self.x_limits[1] != None else False) | (fowards.t[1:,0] < self.x_limits[0] if self.x_limits[0] != None else False) | (fowards.t[1:,1] > self.y_limits[1] if self.y_limits[1] != None else False) | (fowards.t[1:,1] < self.y_limits[0] if self.y_limits[0] != None else False) | (fowards.t[1:,2] > self.z_limits[1] if self.z_limits[1] != None else False) | (fowards.t[1:,2] < self.z_limits[0] if self.z_limits[0] != None else False)
out_of_bounds = (fowards.t[1:,0] > self.x_limits_workspace[1] if self.x_limits_workspace[1] is not None else False) | (fowards.t[1:,0] < self.x_limits_workspace[0] if self.x_limits_workspace[0] is not None else False) | (fowards.t[1:,1] > self.y_limits_workspace[1] if self.y_limits_workspace[1] is not None else False) | (fowards.t[1:,1] < self.y_limits_workspace[0] if self.y_limits_workspace[0] is not None else False) | (fowards.t[1:,2] > self.z_limits_workspace[1] if self.z_limits_workspace[1] is not None else False) | (fowards.t[1:,2] < self.z_limits_workspace[0] if self.z_limits_workspace[0] is not None else False)
if np.any(out_of_bounds):
#print(fowards.t)
#indices = np.where(out_of_bounds)[0]
@@ -774,11 +547,58 @@ class OSC_ROS2_interface(Node):
self.get_logger().fatal(f"send_tcp_coordinates: {e}")
def send_joint_trajectory(self):
pass
self.previous_desired = None
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):
pass
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):
@@ -786,7 +606,6 @@ class OSC_ROS2_interface(Node):
try:
if self.desired is None or not(self.new):
return
if self.desired[0] == "joint_positions":
self.new = False
self.send_joint_positions()
@@ -806,35 +625,26 @@ class OSC_ROS2_interface(Node):
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")
@@ -842,122 +652,16 @@ class OSC_ROS2_interface(Node):
def main():
"""Main function to get joint names and start the ROS 2 & OSC system."""
parser = argparse.ArgumentParser(description="An interface between ROS2 and OSC for robotic arm manipulators", usage="ros2 run osc_ros2 interface [-c CONFIG.TOML]")
parser.add_argument("-c", "--config", type=argparse.FileType("r"), help="A robot TOML config, if the config is provided then the interface will not show the iteractive input")
args = parser.parse_args()
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 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 <limit> 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 [1, 1, 1, 0, 0, 0] 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)
if not args.config:
config, robot = interactive_input()
else:
config = toml.load(args.config)
robot = rtb.ERobot.URDF(config["robot"]["urdf"])
node = OSC_ROS2_interface(robot, config)
# Run ROS 2 spin, and osc_process will be handled by the timer
try:
@@ -966,7 +670,6 @@ def main():
print("")
finally:
node.destroy_node()
rclpy.shutdown()
osc_terminate()
if __name__ == '__main__':

View File

@@ -2,8 +2,8 @@
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>osc_ros2</name>
<version>0.0.0</version>
<description>Creates an interface for communication between OSC and Ros2</description>
<version>1.0.0</version>
<description>Creates an interface for communication between OSC and ROS2</description>
<maintainer email="a.schaefer@tuhh.de">Alexander Schaefer</maintainer>
<license>Apache-2.0</license>

View File

@@ -4,7 +4,7 @@ package_name = 'osc_ros2'
setup(
name=package_name,
version='0.0.0',
version='1.0.0',
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages',
@@ -14,11 +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',
'matplotlib==3.4.3',],
'spatialmath-python'],
zip_safe=True,
maintainer='Alexander Schaefer',
maintainer_email='a.schaefer@tuhh.de',

27
workspace/ur10e.toml Normal file
View File

@@ -0,0 +1,27 @@
[robot]
urdf = "/workspace/ur10e.urdf"
joint_names = [ "shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint",]
cost_mask_string = "111111"
x_limits = [ "None", "None",]
y_limits = [ "None", "None",]
z_limits = [ "None", "None",]
x_limits_workspace = [ "None", "None",]
y_limits_workspace = [ "None", "None",]
z_limits_workspace = [ "None", "None",]
trajectory_topic_name = "/scaled_joint_trajectory_controller/joint_trajectory"
hz = 100
[network]
log_ip = "127.0.0.1"
log_port = 5005
state_ip = "127.0.0.1"
state_port = 7000
commands_port = 8000
[robot.joint_velocity_limits]
shoulder_pan_joint = 2.0943951023931953
shoulder_lift_joint = 2.0943951023931953
elbow_joint = 3.141592653589793
wrist_1_joint = 3.141592653589793
wrist_2_joint = 3.141592653589793
wrist_3_joint = 3.141592653589793