From 58a6463e4eb5974d09c42db948f91b3812c73f81 Mon Sep 17 00:00:00 2001
From: Paul-Winpenny <plw1g21@soton.ac.uk>
Date: Thu, 14 Nov 2024 15:21:38 +0000
Subject: [PATCH] The ros2 setup is done

The steps to rebuild and run:
cd /GitLab/robobin/ros2
colcon build
source install/setup.bash
ros2 run robobin api_node

^A better way of doing it (not launching each node seperately) should be used. Research launch
---
 ros2/build/.built_by                          |   1 +
 ros2/build/COLCON_IGNORE                      |   0
 .../robobin/build/lib/robobin/__init__.py     |   0
 .../robobin/build/lib/robobin/api_node.py     |  24 ++
 ros2/build/robobin/colcon_build.rc            |   1 +
 .../robobin/colcon_command_prefix_setup_py.sh |   1 +
 .../colcon_command_prefix_setup_py.sh.env     |  31 ++
 ros2/build/robobin/install.log                |  14 +
 .../__pycache__/sitecustomize.cpython-312.pyc | Bin 0 -> 418 bytes
 .../robobin/prefix_override/sitecustomize.py  |   4 +
 ros2/build/robobin/robobin.egg-info/PKG-INFO  |   7 +
 .../robobin/robobin.egg-info/SOURCES.txt      |  16 +
 .../robobin.egg-info/dependency_links.txt     |   1 +
 .../robobin/robobin.egg-info/entry_points.txt |   2 +
 .../robobin/robobin.egg-info/requires.txt     |   1 +
 .../robobin/robobin.egg-info/top_level.txt    |   1 +
 ros2/build/robobin/robobin.egg-info/zip-safe  |   1 +
 ros2/install/.colcon_install_layout           |   1 +
 ros2/install/COLCON_IGNORE                    |   0
 ros2/install/_local_setup_util_ps1.py         | 407 ++++++++++++++++++
 ros2/install/_local_setup_util_sh.py          | 407 ++++++++++++++++++
 ros2/install/local_setup.bash                 | 121 ++++++
 ros2/install/local_setup.ps1                  |  55 +++
 ros2/install/local_setup.sh                   | 137 ++++++
 ros2/install/local_setup.zsh                  | 134 ++++++
 .../robobin-0.0.0-py3.12.egg-info/PKG-INFO    |   7 +
 .../robobin-0.0.0-py3.12.egg-info/SOURCES.txt |  16 +
 .../dependency_links.txt                      |   1 +
 .../entry_points.txt                          |   2 +
 .../requires.txt                              |   1 +
 .../top_level.txt                             |   1 +
 .../robobin-0.0.0-py3.12.egg-info/zip-safe    |   1 +
 .../site-packages/robobin/__init__.py         |   0
 .../__pycache__/__init__.cpython-312.pyc      | Bin 0 -> 193 bytes
 .../__pycache__/api_node.cpython-312.pyc      | Bin 0 -> 1460 bytes
 .../site-packages/robobin/api_node.py         |  24 ++
 ros2/install/robobin/lib/robobin/api_node     |  33 ++
 .../resource_index/packages/robobin           |   0
 .../share/colcon-core/packages/robobin        |   1 +
 .../share/robobin/hook/ament_prefix_path.dsv  |   1 +
 .../share/robobin/hook/ament_prefix_path.ps1  |   3 +
 .../share/robobin/hook/ament_prefix_path.sh   |   3 +
 .../robobin/share/robobin/hook/pythonpath.dsv |   1 +
 .../robobin/share/robobin/hook/pythonpath.ps1 |   3 +
 .../robobin/share/robobin/hook/pythonpath.sh  |   3 +
 .../robobin/share/robobin/package.bash        |  31 ++
 .../install/robobin/share/robobin/package.dsv |   6 +
 .../install/robobin/share/robobin/package.ps1 | 116 +++++
 ros2/install/robobin/share/robobin/package.sh |  87 ++++
 .../install/robobin/share/robobin/package.xml |  21 +
 .../install/robobin/share/robobin/package.zsh |  42 ++
 ros2/install/setup.bash                       |  31 ++
 ros2/install/setup.ps1                        |  29 ++
 ros2/install/setup.sh                         |  45 ++
 ros2/install/setup.zsh                        |  31 ++
 ros2/log/COLCON_IGNORE                        |   0
 ros2/log/build_2024-11-14_15-20-34/events.log | 161 +++++++
 .../build_2024-11-14_15-20-34/logger_all.log  | 128 ++++++
 .../robobin/command.log                       |   2 +
 .../robobin/stderr.log                        |   0
 .../robobin/stdout.log                        |  35 ++
 .../robobin/stdout_stderr.log                 |  35 ++
 .../robobin/streams.log                       |  37 ++
 ros2/log/latest                               |   1 +
 ros2/log/latest_build                         |   1 +
 ros2/src/robobin/robobin/api_node.py          |  24 ++
 ros2/src/robobin/setup.py                     |   3 +-
 67 files changed, 2333 insertions(+), 1 deletion(-)
 create mode 100644 ros2/build/.built_by
 create mode 100644 ros2/build/COLCON_IGNORE
 create mode 100644 ros2/build/robobin/build/lib/robobin/__init__.py
 create mode 100644 ros2/build/robobin/build/lib/robobin/api_node.py
 create mode 100644 ros2/build/robobin/colcon_build.rc
 create mode 100644 ros2/build/robobin/colcon_command_prefix_setup_py.sh
 create mode 100644 ros2/build/robobin/colcon_command_prefix_setup_py.sh.env
 create mode 100644 ros2/build/robobin/install.log
 create mode 100644 ros2/build/robobin/prefix_override/__pycache__/sitecustomize.cpython-312.pyc
 create mode 100644 ros2/build/robobin/prefix_override/sitecustomize.py
 create mode 100644 ros2/build/robobin/robobin.egg-info/PKG-INFO
 create mode 100644 ros2/build/robobin/robobin.egg-info/SOURCES.txt
 create mode 100644 ros2/build/robobin/robobin.egg-info/dependency_links.txt
 create mode 100644 ros2/build/robobin/robobin.egg-info/entry_points.txt
 create mode 100644 ros2/build/robobin/robobin.egg-info/requires.txt
 create mode 100644 ros2/build/robobin/robobin.egg-info/top_level.txt
 create mode 100644 ros2/build/robobin/robobin.egg-info/zip-safe
 create mode 100644 ros2/install/.colcon_install_layout
 create mode 100644 ros2/install/COLCON_IGNORE
 create mode 100644 ros2/install/_local_setup_util_ps1.py
 create mode 100644 ros2/install/_local_setup_util_sh.py
 create mode 100644 ros2/install/local_setup.bash
 create mode 100644 ros2/install/local_setup.ps1
 create mode 100644 ros2/install/local_setup.sh
 create mode 100644 ros2/install/local_setup.zsh
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/PKG-INFO
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/SOURCES.txt
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/dependency_links.txt
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/entry_points.txt
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/requires.txt
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/top_level.txt
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/zip-safe
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/__init__.cpython-312.pyc
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/api_node.cpython-312.pyc
 create mode 100644 ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py
 create mode 100755 ros2/install/robobin/lib/robobin/api_node
 create mode 100644 ros2/install/robobin/share/ament_index/resource_index/packages/robobin
 create mode 100644 ros2/install/robobin/share/colcon-core/packages/robobin
 create mode 100644 ros2/install/robobin/share/robobin/hook/ament_prefix_path.dsv
 create mode 100644 ros2/install/robobin/share/robobin/hook/ament_prefix_path.ps1
 create mode 100644 ros2/install/robobin/share/robobin/hook/ament_prefix_path.sh
 create mode 100644 ros2/install/robobin/share/robobin/hook/pythonpath.dsv
 create mode 100644 ros2/install/robobin/share/robobin/hook/pythonpath.ps1
 create mode 100644 ros2/install/robobin/share/robobin/hook/pythonpath.sh
 create mode 100644 ros2/install/robobin/share/robobin/package.bash
 create mode 100644 ros2/install/robobin/share/robobin/package.dsv
 create mode 100644 ros2/install/robobin/share/robobin/package.ps1
 create mode 100644 ros2/install/robobin/share/robobin/package.sh
 create mode 100644 ros2/install/robobin/share/robobin/package.xml
 create mode 100644 ros2/install/robobin/share/robobin/package.zsh
 create mode 100644 ros2/install/setup.bash
 create mode 100644 ros2/install/setup.ps1
 create mode 100644 ros2/install/setup.sh
 create mode 100644 ros2/install/setup.zsh
 create mode 100644 ros2/log/COLCON_IGNORE
 create mode 100644 ros2/log/build_2024-11-14_15-20-34/events.log
 create mode 100644 ros2/log/build_2024-11-14_15-20-34/logger_all.log
 create mode 100644 ros2/log/build_2024-11-14_15-20-34/robobin/command.log
 create mode 100644 ros2/log/build_2024-11-14_15-20-34/robobin/stderr.log
 create mode 100644 ros2/log/build_2024-11-14_15-20-34/robobin/stdout.log
 create mode 100644 ros2/log/build_2024-11-14_15-20-34/robobin/stdout_stderr.log
 create mode 100644 ros2/log/build_2024-11-14_15-20-34/robobin/streams.log
 create mode 120000 ros2/log/latest
 create mode 120000 ros2/log/latest_build
 create mode 100644 ros2/src/robobin/robobin/api_node.py

diff --git a/ros2/build/.built_by b/ros2/build/.built_by
new file mode 100644
index 00000000..06e74acb
--- /dev/null
+++ b/ros2/build/.built_by
@@ -0,0 +1 @@
+colcon
diff --git a/ros2/build/COLCON_IGNORE b/ros2/build/COLCON_IGNORE
new file mode 100644
index 00000000..e69de29b
diff --git a/ros2/build/robobin/build/lib/robobin/__init__.py b/ros2/build/robobin/build/lib/robobin/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/ros2/build/robobin/build/lib/robobin/api_node.py b/ros2/build/robobin/build/lib/robobin/api_node.py
new file mode 100644
index 00000000..2a718548
--- /dev/null
+++ b/ros2/build/robobin/build/lib/robobin/api_node.py
@@ -0,0 +1,24 @@
+# robobin/api_node.py
+
+import rclpy
+from rclpy.node import Node
+
+class ApiNode(Node):
+    def __init__(self):
+        super().__init__('api_node')
+        self.get_logger().info("ApiNode has been started.")
+
+def main(args=None):
+    rclpy.init(args=args)
+    node = ApiNode()
+    try:
+        rclpy.spin(node)
+    except KeyboardInterrupt:
+        pass
+    finally:
+        node.destroy_node()
+        rclpy.shutdown()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/ros2/build/robobin/colcon_build.rc b/ros2/build/robobin/colcon_build.rc
new file mode 100644
index 00000000..573541ac
--- /dev/null
+++ b/ros2/build/robobin/colcon_build.rc
@@ -0,0 +1 @@
+0
diff --git a/ros2/build/robobin/colcon_command_prefix_setup_py.sh b/ros2/build/robobin/colcon_command_prefix_setup_py.sh
new file mode 100644
index 00000000..f9867d51
--- /dev/null
+++ b/ros2/build/robobin/colcon_command_prefix_setup_py.sh
@@ -0,0 +1 @@
+# generated from colcon_core/shell/template/command_prefix.sh.em
diff --git a/ros2/build/robobin/colcon_command_prefix_setup_py.sh.env b/ros2/build/robobin/colcon_command_prefix_setup_py.sh.env
new file mode 100644
index 00000000..d2d753ad
--- /dev/null
+++ b/ros2/build/robobin/colcon_command_prefix_setup_py.sh.env
@@ -0,0 +1,31 @@
+AMENT_PREFIX_PATH=/opt/ros/jazzy
+COLCON=1
+DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
+HOME=/home/paulw
+LANG=en_US.UTF-8
+LD_LIBRARY_PATH=/opt/ros/jazzy/lib/aarch64-linux-gnu:/opt/ros/jazzy/lib
+LESSCLOSE=/usr/bin/lesspipe %s %s
+LESSOPEN=| /usr/bin/lesspipe %s
+LOGNAME=paulw
+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=00: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:*.avif=01;35:*.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:*~=00;90:*#=00;90:*.bak=00;90:*.crdownload=00;90:*.dpkg-dist=00;90:*.dpkg-new=00;90:*.dpkg-old=00;90:*.dpkg-tmp=00;90:*.old=00;90:*.orig=00;90:*.part=00;90:*.rej=00;90:*.rpmnew=00;90:*.rpmorig=00;90:*.rpmsave=00;90:*.swp=00;90:*.tmp=00;90:*.ucf-dist=00;90:*.ucf-new=00;90:*.ucf-old=00;90:
+OLDPWD=/home/paulw/GitLab/robobin/ros2/src
+PATH=/opt/ros/jazzy/bin:/home/paulw/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
+PWD=/home/paulw/GitLab/robobin/ros2/build/robobin
+PYTHONPATH=/opt/ros/jazzy/lib/python3.12/site-packages
+ROS_AUTOMATIC_DISCOVERY_RANGE=SUBNET
+ROS_DISTRO=jazzy
+ROS_PYTHON_VERSION=3
+ROS_VERSION=2
+SHELL=/bin/bash
+SHLVL=1
+SSH_CLIENT=192.168.0.20 57325 22
+SSH_CONNECTION=192.168.0.20 57325 192.168.0.46 22
+SSH_TTY=/dev/pts/0
+TERM=xterm-256color
+USER=paulw
+XDG_DATA_DIRS=/usr/local/share:/usr/share:/var/lib/snapd/desktop
+XDG_RUNTIME_DIR=/run/user/1000
+XDG_SESSION_CLASS=user
+XDG_SESSION_ID=5
+XDG_SESSION_TYPE=tty
+_=/usr/bin/colcon
diff --git a/ros2/build/robobin/install.log b/ros2/build/robobin/install.log
new file mode 100644
index 00000000..83483d31
--- /dev/null
+++ b/ros2/build/robobin/install.log
@@ -0,0 +1,14 @@
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/__init__.cpython-312.pyc
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/api_node.cpython-312.pyc
+/home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages/robobin
+/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/package.xml
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/dependency_links.txt
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/entry_points.txt
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/PKG-INFO
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/zip-safe
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/top_level.txt
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/SOURCES.txt
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/requires.txt
+/home/paulw/GitLab/robobin/ros2/install/robobin/lib/robobin/api_node
diff --git a/ros2/build/robobin/prefix_override/__pycache__/sitecustomize.cpython-312.pyc b/ros2/build/robobin/prefix_override/__pycache__/sitecustomize.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..39639946718b634da57ec100b96c99540778f501
GIT binary patch
literal 418
zcmX@j%ge<81g@fH>9c_JV-N=hn4yf%SwO~gh7^Vr#vFzyhE#?uCYTZgox+r@!N5?Y
zfL%6~As((Lg}H(e$Y+G<1+rl_F;p^EGHSBC1WEZ-vFMi;7gg!&XXNLm>K7!I=9KHZ
zXO{RRCg~UDC*>z)<^kzqBmK<0;*!Li9GIXc%Pr>O%HmsW1x2Z8nH9IVi&7JF;$fWB
ziqvE%XC=dDkUhWr2w9L+nwgUVGhQEJQha_{YEe;UN~(TwW=U#tX>mz@Ze~@gUP0wA
z4x8Nkl+v73yCP7~g1lL51SCE%Gcq#XX5hNP%+_wzXf;9X60`UXG0Ev!6SEqeTl{Y*
Zhg@I@0kXU%2v3#&z{<cPQN#h%1_1Z6Y##ss

literal 0
HcmV?d00001

diff --git a/ros2/build/robobin/prefix_override/sitecustomize.py b/ros2/build/robobin/prefix_override/sitecustomize.py
new file mode 100644
index 00000000..1fab0880
--- /dev/null
+++ b/ros2/build/robobin/prefix_override/sitecustomize.py
@@ -0,0 +1,4 @@
+import sys
+if sys.prefix == '/usr':
+    sys.real_prefix = sys.prefix
+    sys.prefix = sys.exec_prefix = '/home/paulw/GitLab/robobin/ros2/install/robobin'
diff --git a/ros2/build/robobin/robobin.egg-info/PKG-INFO b/ros2/build/robobin/robobin.egg-info/PKG-INFO
new file mode 100644
index 00000000..59b425a7
--- /dev/null
+++ b/ros2/build/robobin/robobin.egg-info/PKG-INFO
@@ -0,0 +1,7 @@
+Metadata-Version: 2.1
+Name: robobin
+Version: 0.0.0
+Summary: TODO: Package description
+Maintainer: paulw
+Maintainer-email: plw1g21@soton.ac.uk
+License: TODO: License declaration
diff --git a/ros2/build/robobin/robobin.egg-info/SOURCES.txt b/ros2/build/robobin/robobin.egg-info/SOURCES.txt
new file mode 100644
index 00000000..1800a72e
--- /dev/null
+++ b/ros2/build/robobin/robobin.egg-info/SOURCES.txt
@@ -0,0 +1,16 @@
+package.xml
+setup.cfg
+setup.py
+../../build/robobin/robobin.egg-info/PKG-INFO
+../../build/robobin/robobin.egg-info/SOURCES.txt
+../../build/robobin/robobin.egg-info/dependency_links.txt
+../../build/robobin/robobin.egg-info/entry_points.txt
+../../build/robobin/robobin.egg-info/requires.txt
+../../build/robobin/robobin.egg-info/top_level.txt
+../../build/robobin/robobin.egg-info/zip-safe
+resource/robobin
+robobin/__init__.py
+robobin/api_node.py
+test/test_copyright.py
+test/test_flake8.py
+test/test_pep257.py
\ No newline at end of file
diff --git a/ros2/build/robobin/robobin.egg-info/dependency_links.txt b/ros2/build/robobin/robobin.egg-info/dependency_links.txt
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/ros2/build/robobin/robobin.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/ros2/build/robobin/robobin.egg-info/entry_points.txt b/ros2/build/robobin/robobin.egg-info/entry_points.txt
new file mode 100644
index 00000000..e2a56917
--- /dev/null
+++ b/ros2/build/robobin/robobin.egg-info/entry_points.txt
@@ -0,0 +1,2 @@
+[console_scripts]
+api_node = robobin.api_node:main
diff --git a/ros2/build/robobin/robobin.egg-info/requires.txt b/ros2/build/robobin/robobin.egg-info/requires.txt
new file mode 100644
index 00000000..49fe098d
--- /dev/null
+++ b/ros2/build/robobin/robobin.egg-info/requires.txt
@@ -0,0 +1 @@
+setuptools
diff --git a/ros2/build/robobin/robobin.egg-info/top_level.txt b/ros2/build/robobin/robobin.egg-info/top_level.txt
new file mode 100644
index 00000000..2ca7c929
--- /dev/null
+++ b/ros2/build/robobin/robobin.egg-info/top_level.txt
@@ -0,0 +1 @@
+robobin
diff --git a/ros2/build/robobin/robobin.egg-info/zip-safe b/ros2/build/robobin/robobin.egg-info/zip-safe
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/ros2/build/robobin/robobin.egg-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/ros2/install/.colcon_install_layout b/ros2/install/.colcon_install_layout
new file mode 100644
index 00000000..3aad5336
--- /dev/null
+++ b/ros2/install/.colcon_install_layout
@@ -0,0 +1 @@
+isolated
diff --git a/ros2/install/COLCON_IGNORE b/ros2/install/COLCON_IGNORE
new file mode 100644
index 00000000..e69de29b
diff --git a/ros2/install/_local_setup_util_ps1.py b/ros2/install/_local_setup_util_ps1.py
new file mode 100644
index 00000000..3c6d9e87
--- /dev/null
+++ b/ros2/install/_local_setup_util_ps1.py
@@ -0,0 +1,407 @@
+# Copyright 2016-2019 Dirk Thomas
+# Licensed under the Apache License, Version 2.0
+
+import argparse
+from collections import OrderedDict
+import os
+from pathlib import Path
+import sys
+
+
+FORMAT_STR_COMMENT_LINE = '# {comment}'
+FORMAT_STR_SET_ENV_VAR = 'Set-Item -Path "Env:{name}" -Value "{value}"'
+FORMAT_STR_USE_ENV_VAR = '$env:{name}'
+FORMAT_STR_INVOKE_SCRIPT = '_colcon_prefix_powershell_source_script "{script_path}"'  # noqa: E501
+FORMAT_STR_REMOVE_LEADING_SEPARATOR = ''  # noqa: E501
+FORMAT_STR_REMOVE_TRAILING_SEPARATOR = ''  # noqa: E501
+
+DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists'
+DSV_TYPE_SET = 'set'
+DSV_TYPE_SET_IF_UNSET = 'set-if-unset'
+DSV_TYPE_SOURCE = 'source'
+
+
+def main(argv=sys.argv[1:]):  # noqa: D103
+    parser = argparse.ArgumentParser(
+        description='Output shell commands for the packages in topological '
+                    'order')
+    parser.add_argument(
+        'primary_extension',
+        help='The file extension of the primary shell')
+    parser.add_argument(
+        'additional_extension', nargs='?',
+        help='The additional file extension to be considered')
+    parser.add_argument(
+        '--merged-install', action='store_true',
+        help='All install prefixes are merged into a single location')
+    args = parser.parse_args(argv)
+
+    packages = get_packages(Path(__file__).parent, args.merged_install)
+
+    ordered_packages = order_packages(packages)
+    for pkg_name in ordered_packages:
+        if _include_comments():
+            print(
+                FORMAT_STR_COMMENT_LINE.format_map(
+                    {'comment': 'Package: ' + pkg_name}))
+        prefix = os.path.abspath(os.path.dirname(__file__))
+        if not args.merged_install:
+            prefix = os.path.join(prefix, pkg_name)
+        for line in get_commands(
+            pkg_name, prefix, args.primary_extension,
+            args.additional_extension
+        ):
+            print(line)
+
+    for line in _remove_ending_separators():
+        print(line)
+
+
+def get_packages(prefix_path, merged_install):
+    """
+    Find packages based on colcon-specific files created during installation.
+
+    :param Path prefix_path: The install prefix path of all packages
+    :param bool merged_install: The flag if the packages are all installed
+      directly in the prefix or if each package is installed in a subdirectory
+      named after the package
+    :returns: A mapping from the package name to the set of runtime
+      dependencies
+    :rtype: dict
+    """
+    packages = {}
+    # since importing colcon_core isn't feasible here the following constant
+    # must match colcon_core.location.get_relative_package_index_path()
+    subdirectory = 'share/colcon-core/packages'
+    if merged_install:
+        # return if workspace is empty
+        if not (prefix_path / subdirectory).is_dir():
+            return packages
+        # find all files in the subdirectory
+        for p in (prefix_path / subdirectory).iterdir():
+            if not p.is_file():
+                continue
+            if p.name.startswith('.'):
+                continue
+            add_package_runtime_dependencies(p, packages)
+    else:
+        # for each subdirectory look for the package specific file
+        for p in prefix_path.iterdir():
+            if not p.is_dir():
+                continue
+            if p.name.startswith('.'):
+                continue
+            p = p / subdirectory / p.name
+            if p.is_file():
+                add_package_runtime_dependencies(p, packages)
+
+    # remove unknown dependencies
+    pkg_names = set(packages.keys())
+    for k in packages.keys():
+        packages[k] = {d for d in packages[k] if d in pkg_names}
+
+    return packages
+
+
+def add_package_runtime_dependencies(path, packages):
+    """
+    Check the path and if it exists extract the packages runtime dependencies.
+
+    :param Path path: The resource file containing the runtime dependencies
+    :param dict packages: A mapping from package names to the sets of runtime
+      dependencies to add to
+    """
+    content = path.read_text()
+    dependencies = set(content.split(os.pathsep) if content else [])
+    packages[path.name] = dependencies
+
+
+def order_packages(packages):
+    """
+    Order packages topologically.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies
+    :returns: The package names
+    :rtype: list
+    """
+    # select packages with no dependencies in alphabetical order
+    to_be_ordered = list(packages.keys())
+    ordered = []
+    while to_be_ordered:
+        pkg_names_without_deps = [
+            name for name in to_be_ordered if not packages[name]]
+        if not pkg_names_without_deps:
+            reduce_cycle_set(packages)
+            raise RuntimeError(
+                'Circular dependency between: ' + ', '.join(sorted(packages)))
+        pkg_names_without_deps.sort()
+        pkg_name = pkg_names_without_deps[0]
+        to_be_ordered.remove(pkg_name)
+        ordered.append(pkg_name)
+        # remove item from dependency lists
+        for k in list(packages.keys()):
+            if pkg_name in packages[k]:
+                packages[k].remove(pkg_name)
+    return ordered
+
+
+def reduce_cycle_set(packages):
+    """
+    Reduce the set of packages to the ones part of the circular dependency.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies which is modified in place
+    """
+    last_depended = None
+    while len(packages) > 0:
+        # get all remaining dependencies
+        depended = set()
+        for pkg_name, dependencies in packages.items():
+            depended = depended.union(dependencies)
+        # remove all packages which are not dependent on
+        for name in list(packages.keys()):
+            if name not in depended:
+                del packages[name]
+        if last_depended:
+            # if remaining packages haven't changed return them
+            if last_depended == depended:
+                return packages.keys()
+        # otherwise reduce again
+        last_depended = depended
+
+
+def _include_comments():
+    # skipping comment lines when COLCON_TRACE is not set speeds up the
+    # processing especially on Windows
+    return bool(os.environ.get('COLCON_TRACE'))
+
+
+def get_commands(pkg_name, prefix, primary_extension, additional_extension):
+    commands = []
+    package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv')
+    if os.path.exists(package_dsv_path):
+        commands += process_dsv_file(
+            package_dsv_path, prefix, primary_extension, additional_extension)
+    return commands
+
+
+def process_dsv_file(
+    dsv_path, prefix, primary_extension=None, additional_extension=None
+):
+    commands = []
+    if _include_comments():
+        commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path}))
+    with open(dsv_path, 'r') as h:
+        content = h.read()
+    lines = content.splitlines()
+
+    basenames = OrderedDict()
+    for i, line in enumerate(lines):
+        # skip over empty or whitespace-only lines
+        if not line.strip():
+            continue
+        # skip over comments
+        if line.startswith('#'):
+            continue
+        try:
+            type_, remainder = line.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "Line %d in '%s' doesn't contain a semicolon separating the "
+                'type from the arguments' % (i + 1, dsv_path))
+        if type_ != DSV_TYPE_SOURCE:
+            # handle non-source lines
+            try:
+                commands += handle_dsv_types_except_source(
+                    type_, remainder, prefix)
+            except RuntimeError as e:
+                raise RuntimeError(
+                    "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e
+        else:
+            # group remaining source lines by basename
+            path_without_ext, ext = os.path.splitext(remainder)
+            if path_without_ext not in basenames:
+                basenames[path_without_ext] = set()
+            assert ext.startswith('.')
+            ext = ext[1:]
+            if ext in (primary_extension, additional_extension):
+                basenames[path_without_ext].add(ext)
+
+    # add the dsv extension to each basename if the file exists
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if os.path.exists(basename + '.dsv'):
+            extensions.add('dsv')
+
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if 'dsv' in extensions:
+            # process dsv files recursively
+            commands += process_dsv_file(
+                basename + '.dsv', prefix, primary_extension=primary_extension,
+                additional_extension=additional_extension)
+        elif primary_extension in extensions and len(extensions) == 1:
+            # source primary-only files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + primary_extension})]
+        elif additional_extension in extensions:
+            # source non-primary files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + additional_extension})]
+
+    return commands
+
+
+def handle_dsv_types_except_source(type_, remainder, prefix):
+    commands = []
+    if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET):
+        try:
+            env_name, value = remainder.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the value')
+        try_prefixed_value = os.path.join(prefix, value) if value else prefix
+        if os.path.exists(try_prefixed_value):
+            value = try_prefixed_value
+        if type_ == DSV_TYPE_SET:
+            commands += _set(env_name, value)
+        elif type_ == DSV_TYPE_SET_IF_UNSET:
+            commands += _set_if_unset(env_name, value)
+        else:
+            assert False
+    elif type_ in (
+        DSV_TYPE_APPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS
+    ):
+        try:
+            env_name_and_values = remainder.split(';')
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the values')
+        env_name = env_name_and_values[0]
+        values = env_name_and_values[1:]
+        for value in values:
+            if not value:
+                value = prefix
+            elif not os.path.isabs(value):
+                value = os.path.join(prefix, value)
+            if (
+                type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and
+                not os.path.exists(value)
+            ):
+                comment = f'skip extending {env_name} with not existing ' \
+                    f'path: {value}'
+                if _include_comments():
+                    commands.append(
+                        FORMAT_STR_COMMENT_LINE.format_map({'comment': comment}))
+            elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE:
+                commands += _append_unique_value(env_name, value)
+            else:
+                commands += _prepend_unique_value(env_name, value)
+    else:
+        raise RuntimeError(
+            'contains an unknown environment hook type: ' + type_)
+    return commands
+
+
+env_state = {}
+
+
+def _append_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # append even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional leading separator
+    extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': extend + value})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+def _prepend_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # prepend even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional trailing separator
+    extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name})
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value + extend})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+# generate commands for removing prepended underscores
+def _remove_ending_separators():
+    # do nothing if the shell extension does not implement the logic
+    if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None:
+        return []
+
+    global env_state
+    commands = []
+    for name in env_state:
+        # skip variables that already had values before this script started prepending
+        if name in os.environ:
+            continue
+        commands += [
+            FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}),
+            FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})]
+    return commands
+
+
+def _set(name, value):
+    global env_state
+    env_state[name] = value
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    return [line]
+
+
+def _set_if_unset(name, value):
+    global env_state
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    if env_state.get(name, os.environ.get(name)):
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+if __name__ == '__main__':  # pragma: no cover
+    try:
+        rc = main()
+    except RuntimeError as e:
+        print(str(e), file=sys.stderr)
+        rc = 1
+    sys.exit(rc)
diff --git a/ros2/install/_local_setup_util_sh.py b/ros2/install/_local_setup_util_sh.py
new file mode 100644
index 00000000..f67eaa98
--- /dev/null
+++ b/ros2/install/_local_setup_util_sh.py
@@ -0,0 +1,407 @@
+# Copyright 2016-2019 Dirk Thomas
+# Licensed under the Apache License, Version 2.0
+
+import argparse
+from collections import OrderedDict
+import os
+from pathlib import Path
+import sys
+
+
+FORMAT_STR_COMMENT_LINE = '# {comment}'
+FORMAT_STR_SET_ENV_VAR = 'export {name}="{value}"'
+FORMAT_STR_USE_ENV_VAR = '${name}'
+FORMAT_STR_INVOKE_SCRIPT = 'COLCON_CURRENT_PREFIX="{prefix}" _colcon_prefix_sh_source_script "{script_path}"'  # noqa: E501
+FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi'  # noqa: E501
+FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi'  # noqa: E501
+
+DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate'
+DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists'
+DSV_TYPE_SET = 'set'
+DSV_TYPE_SET_IF_UNSET = 'set-if-unset'
+DSV_TYPE_SOURCE = 'source'
+
+
+def main(argv=sys.argv[1:]):  # noqa: D103
+    parser = argparse.ArgumentParser(
+        description='Output shell commands for the packages in topological '
+                    'order')
+    parser.add_argument(
+        'primary_extension',
+        help='The file extension of the primary shell')
+    parser.add_argument(
+        'additional_extension', nargs='?',
+        help='The additional file extension to be considered')
+    parser.add_argument(
+        '--merged-install', action='store_true',
+        help='All install prefixes are merged into a single location')
+    args = parser.parse_args(argv)
+
+    packages = get_packages(Path(__file__).parent, args.merged_install)
+
+    ordered_packages = order_packages(packages)
+    for pkg_name in ordered_packages:
+        if _include_comments():
+            print(
+                FORMAT_STR_COMMENT_LINE.format_map(
+                    {'comment': 'Package: ' + pkg_name}))
+        prefix = os.path.abspath(os.path.dirname(__file__))
+        if not args.merged_install:
+            prefix = os.path.join(prefix, pkg_name)
+        for line in get_commands(
+            pkg_name, prefix, args.primary_extension,
+            args.additional_extension
+        ):
+            print(line)
+
+    for line in _remove_ending_separators():
+        print(line)
+
+
+def get_packages(prefix_path, merged_install):
+    """
+    Find packages based on colcon-specific files created during installation.
+
+    :param Path prefix_path: The install prefix path of all packages
+    :param bool merged_install: The flag if the packages are all installed
+      directly in the prefix or if each package is installed in a subdirectory
+      named after the package
+    :returns: A mapping from the package name to the set of runtime
+      dependencies
+    :rtype: dict
+    """
+    packages = {}
+    # since importing colcon_core isn't feasible here the following constant
+    # must match colcon_core.location.get_relative_package_index_path()
+    subdirectory = 'share/colcon-core/packages'
+    if merged_install:
+        # return if workspace is empty
+        if not (prefix_path / subdirectory).is_dir():
+            return packages
+        # find all files in the subdirectory
+        for p in (prefix_path / subdirectory).iterdir():
+            if not p.is_file():
+                continue
+            if p.name.startswith('.'):
+                continue
+            add_package_runtime_dependencies(p, packages)
+    else:
+        # for each subdirectory look for the package specific file
+        for p in prefix_path.iterdir():
+            if not p.is_dir():
+                continue
+            if p.name.startswith('.'):
+                continue
+            p = p / subdirectory / p.name
+            if p.is_file():
+                add_package_runtime_dependencies(p, packages)
+
+    # remove unknown dependencies
+    pkg_names = set(packages.keys())
+    for k in packages.keys():
+        packages[k] = {d for d in packages[k] if d in pkg_names}
+
+    return packages
+
+
+def add_package_runtime_dependencies(path, packages):
+    """
+    Check the path and if it exists extract the packages runtime dependencies.
+
+    :param Path path: The resource file containing the runtime dependencies
+    :param dict packages: A mapping from package names to the sets of runtime
+      dependencies to add to
+    """
+    content = path.read_text()
+    dependencies = set(content.split(os.pathsep) if content else [])
+    packages[path.name] = dependencies
+
+
+def order_packages(packages):
+    """
+    Order packages topologically.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies
+    :returns: The package names
+    :rtype: list
+    """
+    # select packages with no dependencies in alphabetical order
+    to_be_ordered = list(packages.keys())
+    ordered = []
+    while to_be_ordered:
+        pkg_names_without_deps = [
+            name for name in to_be_ordered if not packages[name]]
+        if not pkg_names_without_deps:
+            reduce_cycle_set(packages)
+            raise RuntimeError(
+                'Circular dependency between: ' + ', '.join(sorted(packages)))
+        pkg_names_without_deps.sort()
+        pkg_name = pkg_names_without_deps[0]
+        to_be_ordered.remove(pkg_name)
+        ordered.append(pkg_name)
+        # remove item from dependency lists
+        for k in list(packages.keys()):
+            if pkg_name in packages[k]:
+                packages[k].remove(pkg_name)
+    return ordered
+
+
+def reduce_cycle_set(packages):
+    """
+    Reduce the set of packages to the ones part of the circular dependency.
+
+    :param dict packages: A mapping from package name to the set of runtime
+      dependencies which is modified in place
+    """
+    last_depended = None
+    while len(packages) > 0:
+        # get all remaining dependencies
+        depended = set()
+        for pkg_name, dependencies in packages.items():
+            depended = depended.union(dependencies)
+        # remove all packages which are not dependent on
+        for name in list(packages.keys()):
+            if name not in depended:
+                del packages[name]
+        if last_depended:
+            # if remaining packages haven't changed return them
+            if last_depended == depended:
+                return packages.keys()
+        # otherwise reduce again
+        last_depended = depended
+
+
+def _include_comments():
+    # skipping comment lines when COLCON_TRACE is not set speeds up the
+    # processing especially on Windows
+    return bool(os.environ.get('COLCON_TRACE'))
+
+
+def get_commands(pkg_name, prefix, primary_extension, additional_extension):
+    commands = []
+    package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv')
+    if os.path.exists(package_dsv_path):
+        commands += process_dsv_file(
+            package_dsv_path, prefix, primary_extension, additional_extension)
+    return commands
+
+
+def process_dsv_file(
+    dsv_path, prefix, primary_extension=None, additional_extension=None
+):
+    commands = []
+    if _include_comments():
+        commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path}))
+    with open(dsv_path, 'r') as h:
+        content = h.read()
+    lines = content.splitlines()
+
+    basenames = OrderedDict()
+    for i, line in enumerate(lines):
+        # skip over empty or whitespace-only lines
+        if not line.strip():
+            continue
+        # skip over comments
+        if line.startswith('#'):
+            continue
+        try:
+            type_, remainder = line.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "Line %d in '%s' doesn't contain a semicolon separating the "
+                'type from the arguments' % (i + 1, dsv_path))
+        if type_ != DSV_TYPE_SOURCE:
+            # handle non-source lines
+            try:
+                commands += handle_dsv_types_except_source(
+                    type_, remainder, prefix)
+            except RuntimeError as e:
+                raise RuntimeError(
+                    "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e
+        else:
+            # group remaining source lines by basename
+            path_without_ext, ext = os.path.splitext(remainder)
+            if path_without_ext not in basenames:
+                basenames[path_without_ext] = set()
+            assert ext.startswith('.')
+            ext = ext[1:]
+            if ext in (primary_extension, additional_extension):
+                basenames[path_without_ext].add(ext)
+
+    # add the dsv extension to each basename if the file exists
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if os.path.exists(basename + '.dsv'):
+            extensions.add('dsv')
+
+    for basename, extensions in basenames.items():
+        if not os.path.isabs(basename):
+            basename = os.path.join(prefix, basename)
+        if 'dsv' in extensions:
+            # process dsv files recursively
+            commands += process_dsv_file(
+                basename + '.dsv', prefix, primary_extension=primary_extension,
+                additional_extension=additional_extension)
+        elif primary_extension in extensions and len(extensions) == 1:
+            # source primary-only files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + primary_extension})]
+        elif additional_extension in extensions:
+            # source non-primary files
+            commands += [
+                FORMAT_STR_INVOKE_SCRIPT.format_map({
+                    'prefix': prefix,
+                    'script_path': basename + '.' + additional_extension})]
+
+    return commands
+
+
+def handle_dsv_types_except_source(type_, remainder, prefix):
+    commands = []
+    if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET):
+        try:
+            env_name, value = remainder.split(';', 1)
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the value')
+        try_prefixed_value = os.path.join(prefix, value) if value else prefix
+        if os.path.exists(try_prefixed_value):
+            value = try_prefixed_value
+        if type_ == DSV_TYPE_SET:
+            commands += _set(env_name, value)
+        elif type_ == DSV_TYPE_SET_IF_UNSET:
+            commands += _set_if_unset(env_name, value)
+        else:
+            assert False
+    elif type_ in (
+        DSV_TYPE_APPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE,
+        DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS
+    ):
+        try:
+            env_name_and_values = remainder.split(';')
+        except ValueError:
+            raise RuntimeError(
+                "doesn't contain a semicolon separating the environment name "
+                'from the values')
+        env_name = env_name_and_values[0]
+        values = env_name_and_values[1:]
+        for value in values:
+            if not value:
+                value = prefix
+            elif not os.path.isabs(value):
+                value = os.path.join(prefix, value)
+            if (
+                type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and
+                not os.path.exists(value)
+            ):
+                comment = f'skip extending {env_name} with not existing ' \
+                    f'path: {value}'
+                if _include_comments():
+                    commands.append(
+                        FORMAT_STR_COMMENT_LINE.format_map({'comment': comment}))
+            elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE:
+                commands += _append_unique_value(env_name, value)
+            else:
+                commands += _prepend_unique_value(env_name, value)
+    else:
+        raise RuntimeError(
+            'contains an unknown environment hook type: ' + type_)
+    return commands
+
+
+env_state = {}
+
+
+def _append_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # append even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional leading separator
+    extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': extend + value})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+def _prepend_unique_value(name, value):
+    global env_state
+    if name not in env_state:
+        if os.environ.get(name):
+            env_state[name] = set(os.environ[name].split(os.pathsep))
+        else:
+            env_state[name] = set()
+    # prepend even if the variable has not been set yet, in case a shell script sets the
+    # same variable without the knowledge of this Python script.
+    # later _remove_ending_separators() will cleanup any unintentional trailing separator
+    extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name})
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value + extend})
+    if value not in env_state[name]:
+        env_state[name].add(value)
+    else:
+        if not _include_comments():
+            return []
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+# generate commands for removing prepended underscores
+def _remove_ending_separators():
+    # do nothing if the shell extension does not implement the logic
+    if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None:
+        return []
+
+    global env_state
+    commands = []
+    for name in env_state:
+        # skip variables that already had values before this script started prepending
+        if name in os.environ:
+            continue
+        commands += [
+            FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}),
+            FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})]
+    return commands
+
+
+def _set(name, value):
+    global env_state
+    env_state[name] = value
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    return [line]
+
+
+def _set_if_unset(name, value):
+    global env_state
+    line = FORMAT_STR_SET_ENV_VAR.format_map(
+        {'name': name, 'value': value})
+    if env_state.get(name, os.environ.get(name)):
+        line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line})
+    return [line]
+
+
+if __name__ == '__main__':  # pragma: no cover
+    try:
+        rc = main()
+    except RuntimeError as e:
+        print(str(e), file=sys.stderr)
+        rc = 1
+    sys.exit(rc)
diff --git a/ros2/install/local_setup.bash b/ros2/install/local_setup.bash
new file mode 100644
index 00000000..03f00256
--- /dev/null
+++ b/ros2/install/local_setup.bash
@@ -0,0 +1,121 @@
+# generated from colcon_bash/shell/template/prefix.bash.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# a bash script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)"
+else
+  _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prefix_bash_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prefix_bash_prepend_unique_value_IFS="$IFS"
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  _contained_value=""
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      _contained_value=1
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  if [ -z "$_contained_value" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      if [ "$_all_values" = "$_value" ]; then
+        echo "export $_listname=$_value"
+      else
+        echo "export $_listname=$_value:\$$_listname"
+      fi
+    fi
+  fi
+  unset _contained_value
+  # restore the field separator
+  IFS="$_colcon_prefix_bash_prepend_unique_value_IFS"
+  unset _colcon_prefix_bash_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# add this prefix to the COLCON_PREFIX_PATH
+_colcon_prefix_bash_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX"
+unset _colcon_prefix_bash_prepend_unique_value
+
+# check environment variable for custom Python executable
+if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then
+  if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then
+    echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    return 1
+  fi
+  _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE"
+else
+  # try the Python executable known at configure time
+  _colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if [ ! -f "$_colcon_python_executable" ]; then
+    if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then
+      echo "error: unable to find python3 executable"
+      return 1
+    fi
+    _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"`
+  fi
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# get all commands in topological order
+_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh bash)"
+unset _colcon_python_executable
+if [ -n "$COLCON_TRACE" ]; then
+  echo "$(declare -f _colcon_prefix_sh_source_script)"
+  echo "# Execute generated script:"
+  echo "# <<<"
+  echo "${_colcon_ordered_commands}"
+  echo "# >>>"
+  echo "unset _colcon_prefix_sh_source_script"
+fi
+eval "${_colcon_ordered_commands}"
+unset _colcon_ordered_commands
+
+unset _colcon_prefix_sh_source_script
+
+unset _colcon_prefix_bash_COLCON_CURRENT_PREFIX
diff --git a/ros2/install/local_setup.ps1 b/ros2/install/local_setup.ps1
new file mode 100644
index 00000000..6f68c8de
--- /dev/null
+++ b/ros2/install/local_setup.ps1
@@ -0,0 +1,55 @@
+# generated from colcon_powershell/shell/template/prefix.ps1.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# check environment variable for custom Python executable
+if ($env:COLCON_PYTHON_EXECUTABLE) {
+  if (!(Test-Path "$env:COLCON_PYTHON_EXECUTABLE" -PathType Leaf)) {
+    echo "error: COLCON_PYTHON_EXECUTABLE '$env:COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    exit 1
+  }
+  $_colcon_python_executable="$env:COLCON_PYTHON_EXECUTABLE"
+} else {
+  # use the Python executable known at configure time
+  $_colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if (!(Test-Path "$_colcon_python_executable" -PathType Leaf)) {
+    if (!(Get-Command "python3" -ErrorAction SilentlyContinue)) {
+      echo "error: unable to find python3 executable"
+      exit 1
+    }
+    $_colcon_python_executable="python3"
+  }
+}
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+function _colcon_prefix_powershell_source_script {
+  param (
+    $_colcon_prefix_powershell_source_script_param
+  )
+  # source script with conditional trace output
+  if (Test-Path $_colcon_prefix_powershell_source_script_param) {
+    if ($env:COLCON_TRACE) {
+      echo ". '$_colcon_prefix_powershell_source_script_param'"
+    }
+    . "$_colcon_prefix_powershell_source_script_param"
+  } else {
+    Write-Error "not found: '$_colcon_prefix_powershell_source_script_param'"
+  }
+}
+
+# get all commands in topological order
+$_colcon_ordered_commands = & "$_colcon_python_executable" "$(Split-Path $PSCommandPath -Parent)/_local_setup_util_ps1.py" ps1
+
+# execute all commands in topological order
+if ($env:COLCON_TRACE) {
+  echo "Execute generated script:"
+  echo "<<<"
+  $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Write-Output
+  echo ">>>"
+}
+if ($_colcon_ordered_commands) {
+  $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Invoke-Expression
+}
diff --git a/ros2/install/local_setup.sh b/ros2/install/local_setup.sh
new file mode 100644
index 00000000..e3e80de3
--- /dev/null
+++ b/ros2/install/local_setup.sh
@@ -0,0 +1,137 @@
+# generated from colcon_core/shell/template/prefix.sh.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# since a plain shell script can't determine its own path when being sourced
+# either use the provided COLCON_CURRENT_PREFIX
+# or fall back to the build time prefix (if it exists)
+_colcon_prefix_sh_COLCON_CURRENT_PREFIX="/home/paulw/GitLab/robobin/ros2/install"
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  if [ ! -d "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" ]; then
+    echo "The build time path \"$_colcon_prefix_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2
+    unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX
+    return 1
+  fi
+else
+  _colcon_prefix_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prefix_sh_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prefix_sh_prepend_unique_value_IFS="$IFS"
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  _contained_value=""
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      _contained_value=1
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  if [ -z "$_contained_value" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      if [ "$_all_values" = "$_value" ]; then
+        echo "export $_listname=$_value"
+      else
+        echo "export $_listname=$_value:\$$_listname"
+      fi
+    fi
+  fi
+  unset _contained_value
+  # restore the field separator
+  IFS="$_colcon_prefix_sh_prepend_unique_value_IFS"
+  unset _colcon_prefix_sh_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# add this prefix to the COLCON_PREFIX_PATH
+_colcon_prefix_sh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX"
+unset _colcon_prefix_sh_prepend_unique_value
+
+# check environment variable for custom Python executable
+if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then
+  if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then
+    echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    return 1
+  fi
+  _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE"
+else
+  # try the Python executable known at configure time
+  _colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if [ ! -f "$_colcon_python_executable" ]; then
+    if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then
+      echo "error: unable to find python3 executable"
+      return 1
+    fi
+    _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"`
+  fi
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# get all commands in topological order
+_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh)"
+unset _colcon_python_executable
+if [ -n "$COLCON_TRACE" ]; then
+  echo "_colcon_prefix_sh_source_script() {
+    if [ -f \"\$1\" ]; then
+      if [ -n \"\$COLCON_TRACE\" ]; then
+        echo \"# . \\\"\$1\\\"\"
+      fi
+      . \"\$1\"
+    else
+      echo \"not found: \\\"\$1\\\"\" 1>&2
+    fi
+  }"
+  echo "# Execute generated script:"
+  echo "# <<<"
+  echo "${_colcon_ordered_commands}"
+  echo "# >>>"
+  echo "unset _colcon_prefix_sh_source_script"
+fi
+eval "${_colcon_ordered_commands}"
+unset _colcon_ordered_commands
+
+unset _colcon_prefix_sh_source_script
+
+unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX
diff --git a/ros2/install/local_setup.zsh b/ros2/install/local_setup.zsh
new file mode 100644
index 00000000..b6487102
--- /dev/null
+++ b/ros2/install/local_setup.zsh
@@ -0,0 +1,134 @@
+# generated from colcon_zsh/shell/template/prefix.zsh.em
+
+# This script extends the environment with all packages contained in this
+# prefix path.
+
+# a zsh script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)"
+else
+  _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to convert array-like strings into arrays
+# to workaround SH_WORD_SPLIT not being set
+_colcon_prefix_zsh_convert_to_array() {
+  local _listname=$1
+  local _dollar="$"
+  local _split="{="
+  local _to_array="(\"$_dollar$_split$_listname}\")"
+  eval $_listname=$_to_array
+}
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prefix_zsh_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prefix_zsh_prepend_unique_value_IFS="$IFS"
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  _contained_value=""
+  # workaround SH_WORD_SPLIT not being set
+  _colcon_prefix_zsh_convert_to_array _values
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      _contained_value=1
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  if [ -z "$_contained_value" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      if [ "$_all_values" = "$_value" ]; then
+        echo "export $_listname=$_value"
+      else
+        echo "export $_listname=$_value:\$$_listname"
+      fi
+    fi
+  fi
+  unset _contained_value
+  # restore the field separator
+  IFS="$_colcon_prefix_zsh_prepend_unique_value_IFS"
+  unset _colcon_prefix_zsh_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# add this prefix to the COLCON_PREFIX_PATH
+_colcon_prefix_zsh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX"
+unset _colcon_prefix_zsh_prepend_unique_value
+unset _colcon_prefix_zsh_convert_to_array
+
+# check environment variable for custom Python executable
+if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then
+  if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then
+    echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist"
+    return 1
+  fi
+  _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE"
+else
+  # try the Python executable known at configure time
+  _colcon_python_executable="/usr/bin/python3"
+  # if it doesn't exist try a fall back
+  if [ ! -f "$_colcon_python_executable" ]; then
+    if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then
+      echo "error: unable to find python3 executable"
+      return 1
+    fi
+    _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"`
+  fi
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_sh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# get all commands in topological order
+_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh zsh)"
+unset _colcon_python_executable
+if [ -n "$COLCON_TRACE" ]; then
+  echo "$(declare -f _colcon_prefix_sh_source_script)"
+  echo "# Execute generated script:"
+  echo "# <<<"
+  echo "${_colcon_ordered_commands}"
+  echo "# >>>"
+  echo "unset _colcon_prefix_sh_source_script"
+fi
+eval "${_colcon_ordered_commands}"
+unset _colcon_ordered_commands
+
+unset _colcon_prefix_sh_source_script
+
+unset _colcon_prefix_zsh_COLCON_CURRENT_PREFIX
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/PKG-INFO b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/PKG-INFO
new file mode 100644
index 00000000..59b425a7
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/PKG-INFO
@@ -0,0 +1,7 @@
+Metadata-Version: 2.1
+Name: robobin
+Version: 0.0.0
+Summary: TODO: Package description
+Maintainer: paulw
+Maintainer-email: plw1g21@soton.ac.uk
+License: TODO: License declaration
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/SOURCES.txt b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/SOURCES.txt
new file mode 100644
index 00000000..1800a72e
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/SOURCES.txt
@@ -0,0 +1,16 @@
+package.xml
+setup.cfg
+setup.py
+../../build/robobin/robobin.egg-info/PKG-INFO
+../../build/robobin/robobin.egg-info/SOURCES.txt
+../../build/robobin/robobin.egg-info/dependency_links.txt
+../../build/robobin/robobin.egg-info/entry_points.txt
+../../build/robobin/robobin.egg-info/requires.txt
+../../build/robobin/robobin.egg-info/top_level.txt
+../../build/robobin/robobin.egg-info/zip-safe
+resource/robobin
+robobin/__init__.py
+robobin/api_node.py
+test/test_copyright.py
+test/test_flake8.py
+test/test_pep257.py
\ No newline at end of file
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/dependency_links.txt b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/dependency_links.txt
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/entry_points.txt b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/entry_points.txt
new file mode 100644
index 00000000..e2a56917
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/entry_points.txt
@@ -0,0 +1,2 @@
+[console_scripts]
+api_node = robobin.api_node:main
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/requires.txt b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/requires.txt
new file mode 100644
index 00000000..49fe098d
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/requires.txt
@@ -0,0 +1 @@
+setuptools
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/top_level.txt b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/top_level.txt
new file mode 100644
index 00000000..2ca7c929
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/top_level.txt
@@ -0,0 +1 @@
+robobin
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/zip-safe b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/zip-safe
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py b/ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/__init__.cpython-312.pyc b/ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/__init__.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0bac3748733cdbf991da07575f09d65763cda5ac
GIT binary patch
literal 193
zcmX@j%ge<81Yd>B(n0iN5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!O3=^9&rQ`YNG#1M
z*LTk>@kvb5FUn8KPs+>#(#1ylnR&$}i8(oN!JNz_{esGpjQl)fJwqe?;>?m%-GapA
z?8NlcVz{FC_{_Y_lK6PNg34bUHo5sJr8%i~MXW#z8G*PM#Q4a}$jDg43}gWS%l0!m

literal 0
HcmV?d00001

diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/api_node.cpython-312.pyc b/ros2/install/robobin/lib/python3.12/site-packages/robobin/__pycache__/api_node.cpython-312.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c24bcabaa0cd17ebb87017d4fc47465640523fe0
GIT binary patch
literal 1460
zcmb_b&2Jk;6o0cH_Sm(P7AaNSk6@HivZ}BlAS56{1XWZN6d`e{FU#69aW+}+F0*T;
z8yP7`L5&5dy`XaDhQdFQb1wuEm9E+oCvH|9sZqG_X1!~y3UOkjee=HNz4x2>?Spc;
z2)K-yx7rT~z#r1cmYyoZPf@uK3>a~sA$P?g9i^cVP~ZkIbqAQnl|6No-%wee={uyM
zah>Hh761fQfNOhcIRX)hh(Z69_KHDbZN+1}l}3|INsZwgDtE9qhX!HLP<COJFtS4%
z>Mq>I4xfRc#QA04PD&tv@sh*HZ`effJ-H9zIMgRS_zuA_vX`D9(1Z01?l=!18+koH
z;Y?Mg{Bt@2LtTlf<=du<ShgzZMAbDbs5Uuwt3haqkh7Yh#d^^7xrnK0+O8d%W?XFZ
z&~&_Z8@-zCu6l?`3%Iiy7fiF|SV3T#fxMFH_UY&KHLt_#zSVU$>o@H16RTMlUejyZ
zF7Cl%-FC5+<BXk--K_gjxaPTU)Lvh#2X@F`^{v*1)#kxCDI2`zN1}j@w$7#iYT1zT
z0)ne3PPXAOE%);WboPe}hxE$tv~+j6Km8l6Jfw36bncfI-#Mc14lxr9U4nG24woQJ
zv*WR@BlVJLe$lm@Q6y;?ms6xI?l`7t5K)#5<@3BRrces`I*G{1fQ+8(z%xbBmj-}B
zOlR@dBnve3CM;M$FLGcUThAzl3EAqw&l8LY$9%|G@FgisR*-`{w|W!jdu090b73^I
zT4b_P>A&(Kn1_&N8CO841a85%uWiC@^%iWBdHBCNWfcu2`715a4vc)Pi<aX@l9+aw
zJOFajx83;M$2@9!mS7*bAs3?ShjEGVAQWDd`~)!#*193{HeEvzGdO>&$$w)+<ZAM$
zvDUF{S6s%RysBUW1=33^+`0MH&3o66w94Z%FMRX%_Vt01(<?~3yTyL--kXPXc0i#}
zen=|^v~ox<%E(lI>WI#s92cN;`6&>+{D_tYD(-&`a{r!t8q8zAA7_>?!TzPf@`Aem
zva);)_Fo}VUr?of?dk{TRLNpFsO05}krU_fSX@l5r6wT>$*>VYB@}TM#ZNF|q~z`?
zT^dpUJ@FEnl7qn_3LKA+VGc<730yqZRI;?ojsdq}u|O(=^PrV>w|-SCk2L!AhXWO~
I3rWqt0Tp;Il>h($

literal 0
HcmV?d00001

diff --git a/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py b/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py
new file mode 100644
index 00000000..2a718548
--- /dev/null
+++ b/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py
@@ -0,0 +1,24 @@
+# robobin/api_node.py
+
+import rclpy
+from rclpy.node import Node
+
+class ApiNode(Node):
+    def __init__(self):
+        super().__init__('api_node')
+        self.get_logger().info("ApiNode has been started.")
+
+def main(args=None):
+    rclpy.init(args=args)
+    node = ApiNode()
+    try:
+        rclpy.spin(node)
+    except KeyboardInterrupt:
+        pass
+    finally:
+        node.destroy_node()
+        rclpy.shutdown()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/ros2/install/robobin/lib/robobin/api_node b/ros2/install/robobin/lib/robobin/api_node
new file mode 100755
index 00000000..cc9aa893
--- /dev/null
+++ b/ros2/install/robobin/lib/robobin/api_node
@@ -0,0 +1,33 @@
+#!/usr/bin/python3
+# EASY-INSTALL-ENTRY-SCRIPT: 'robobin==0.0.0','console_scripts','api_node'
+import re
+import sys
+
+# for compatibility with easy_install; see #2198
+__requires__ = 'robobin==0.0.0'
+
+try:
+    from importlib.metadata import distribution
+except ImportError:
+    try:
+        from importlib_metadata import distribution
+    except ImportError:
+        from pkg_resources import load_entry_point
+
+
+def importlib_load_entry_point(spec, group, name):
+    dist_name, _, _ = spec.partition('==')
+    matches = (
+        entry_point
+        for entry_point in distribution(dist_name).entry_points
+        if entry_point.group == group and entry_point.name == name
+    )
+    return next(matches).load()
+
+
+globals().setdefault('load_entry_point', importlib_load_entry_point)
+
+
+if __name__ == '__main__':
+    sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
+    sys.exit(load_entry_point('robobin==0.0.0', 'console_scripts', 'api_node')())
diff --git a/ros2/install/robobin/share/ament_index/resource_index/packages/robobin b/ros2/install/robobin/share/ament_index/resource_index/packages/robobin
new file mode 100644
index 00000000..e69de29b
diff --git a/ros2/install/robobin/share/colcon-core/packages/robobin b/ros2/install/robobin/share/colcon-core/packages/robobin
new file mode 100644
index 00000000..de58d893
--- /dev/null
+++ b/ros2/install/robobin/share/colcon-core/packages/robobin
@@ -0,0 +1 @@
+rclpy:std_msgs
\ No newline at end of file
diff --git a/ros2/install/robobin/share/robobin/hook/ament_prefix_path.dsv b/ros2/install/robobin/share/robobin/hook/ament_prefix_path.dsv
new file mode 100644
index 00000000..79d4c95b
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/hook/ament_prefix_path.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;AMENT_PREFIX_PATH;
diff --git a/ros2/install/robobin/share/robobin/hook/ament_prefix_path.ps1 b/ros2/install/robobin/share/robobin/hook/ament_prefix_path.ps1
new file mode 100644
index 00000000..26b99975
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/hook/ament_prefix_path.ps1
@@ -0,0 +1,3 @@
+# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em
+
+colcon_prepend_unique_value AMENT_PREFIX_PATH "$env:COLCON_CURRENT_PREFIX"
diff --git a/ros2/install/robobin/share/robobin/hook/ament_prefix_path.sh b/ros2/install/robobin/share/robobin/hook/ament_prefix_path.sh
new file mode 100644
index 00000000..f3041f68
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/hook/ament_prefix_path.sh
@@ -0,0 +1,3 @@
+# generated from colcon_core/shell/template/hook_prepend_value.sh.em
+
+_colcon_prepend_unique_value AMENT_PREFIX_PATH "$COLCON_CURRENT_PREFIX"
diff --git a/ros2/install/robobin/share/robobin/hook/pythonpath.dsv b/ros2/install/robobin/share/robobin/hook/pythonpath.dsv
new file mode 100644
index 00000000..c2ddcdb7
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/hook/pythonpath.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;PYTHONPATH;lib/python3.12/site-packages
diff --git a/ros2/install/robobin/share/robobin/hook/pythonpath.ps1 b/ros2/install/robobin/share/robobin/hook/pythonpath.ps1
new file mode 100644
index 00000000..bdd69aff
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/hook/pythonpath.ps1
@@ -0,0 +1,3 @@
+# generated from colcon_powershell/shell/template/hook_prepend_value.ps1.em
+
+colcon_prepend_unique_value PYTHONPATH "$env:COLCON_CURRENT_PREFIX\lib/python3.12/site-packages"
diff --git a/ros2/install/robobin/share/robobin/hook/pythonpath.sh b/ros2/install/robobin/share/robobin/hook/pythonpath.sh
new file mode 100644
index 00000000..45388fea
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/hook/pythonpath.sh
@@ -0,0 +1,3 @@
+# generated from colcon_core/shell/template/hook_prepend_value.sh.em
+
+_colcon_prepend_unique_value PYTHONPATH "$COLCON_CURRENT_PREFIX/lib/python3.12/site-packages"
diff --git a/ros2/install/robobin/share/robobin/package.bash b/ros2/install/robobin/share/robobin/package.bash
new file mode 100644
index 00000000..06c2f0c0
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/package.bash
@@ -0,0 +1,31 @@
+# generated from colcon_bash/shell/template/package.bash.em
+
+# This script extends the environment for this package.
+
+# a bash script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  # the prefix is two levels up from the package specific share directory
+  _colcon_package_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`/../.." > /dev/null && pwd)"
+else
+  _colcon_package_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_bash_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$@"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source sh script of this package
+_colcon_package_bash_source_script "$_colcon_package_bash_COLCON_CURRENT_PREFIX/share/robobin/package.sh"
+
+unset _colcon_package_bash_source_script
+unset _colcon_package_bash_COLCON_CURRENT_PREFIX
diff --git a/ros2/install/robobin/share/robobin/package.dsv b/ros2/install/robobin/share/robobin/package.dsv
new file mode 100644
index 00000000..acfa8631
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/package.dsv
@@ -0,0 +1,6 @@
+source;share/robobin/hook/pythonpath.ps1
+source;share/robobin/hook/pythonpath.dsv
+source;share/robobin/hook/pythonpath.sh
+source;share/robobin/hook/ament_prefix_path.ps1
+source;share/robobin/hook/ament_prefix_path.dsv
+source;share/robobin/hook/ament_prefix_path.sh
diff --git a/ros2/install/robobin/share/robobin/package.ps1 b/ros2/install/robobin/share/robobin/package.ps1
new file mode 100644
index 00000000..9d07a1c1
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/package.ps1
@@ -0,0 +1,116 @@
+# generated from colcon_powershell/shell/template/package.ps1.em
+
+# function to append a value to a variable
+# which uses colons as separators
+# duplicates as well as leading separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+function colcon_append_unique_value {
+  param (
+    $_listname,
+    $_value
+  )
+
+  # get values from variable
+  if (Test-Path Env:$_listname) {
+    $_values=(Get-Item env:$_listname).Value
+  } else {
+    $_values=""
+  }
+  $_duplicate=""
+  # start with no values
+  $_all_values=""
+  # iterate over existing values in the variable
+  if ($_values) {
+    $_values.Split(";") | ForEach {
+      # not an empty string
+      if ($_) {
+        # not a duplicate of _value
+        if ($_ -eq $_value) {
+          $_duplicate="1"
+        }
+        if ($_all_values) {
+          $_all_values="${_all_values};$_"
+        } else {
+          $_all_values="$_"
+        }
+      }
+    }
+  }
+  # append only non-duplicates
+  if (!$_duplicate) {
+    # avoid leading separator
+    if ($_all_values) {
+      $_all_values="${_all_values};${_value}"
+    } else {
+      $_all_values="${_value}"
+    }
+  }
+
+  # export the updated variable
+  Set-Item env:\$_listname -Value "$_all_values"
+}
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+function colcon_prepend_unique_value {
+  param (
+    $_listname,
+    $_value
+  )
+
+  # get values from variable
+  if (Test-Path Env:$_listname) {
+    $_values=(Get-Item env:$_listname).Value
+  } else {
+    $_values=""
+  }
+  # start with the new value
+  $_all_values="$_value"
+  # iterate over existing values in the variable
+  if ($_values) {
+    $_values.Split(";") | ForEach {
+      # not an empty string
+      if ($_) {
+        # not a duplicate of _value
+        if ($_ -ne $_value) {
+          # keep non-duplicate values
+          $_all_values="${_all_values};$_"
+        }
+      }
+    }
+  }
+  # export the updated variable
+  Set-Item env:\$_listname -Value "$_all_values"
+}
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+function colcon_package_source_powershell_script {
+  param (
+    $_colcon_package_source_powershell_script
+  )
+  # source script with conditional trace output
+  if (Test-Path $_colcon_package_source_powershell_script) {
+    if ($env:COLCON_TRACE) {
+      echo ". '$_colcon_package_source_powershell_script'"
+    }
+    . "$_colcon_package_source_powershell_script"
+  } else {
+    Write-Error "not found: '$_colcon_package_source_powershell_script'"
+  }
+}
+
+
+# a powershell script is able to determine its own path
+# the prefix is two levels up from the package specific share directory
+$env:COLCON_CURRENT_PREFIX=(Get-Item $PSCommandPath).Directory.Parent.Parent.FullName
+
+colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/robobin/hook/pythonpath.ps1"
+colcon_package_source_powershell_script "$env:COLCON_CURRENT_PREFIX\share/robobin/hook/ament_prefix_path.ps1"
+
+Remove-Item Env:\COLCON_CURRENT_PREFIX
diff --git a/ros2/install/robobin/share/robobin/package.sh b/ros2/install/robobin/share/robobin/package.sh
new file mode 100644
index 00000000..ec834e7d
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/package.sh
@@ -0,0 +1,87 @@
+# generated from colcon_core/shell/template/package.sh.em
+
+# This script extends the environment for this package.
+
+# function to prepend a value to a variable
+# which uses colons as separators
+# duplicates as well as trailing separators are avoided
+# first argument: the name of the result variable
+# second argument: the value to be prepended
+_colcon_prepend_unique_value() {
+  # arguments
+  _listname="$1"
+  _value="$2"
+
+  # get values from variable
+  eval _values=\"\$$_listname\"
+  # backup the field separator
+  _colcon_prepend_unique_value_IFS=$IFS
+  IFS=":"
+  # start with the new value
+  _all_values="$_value"
+  # workaround SH_WORD_SPLIT not being set in zsh
+  if [ "$(command -v colcon_zsh_convert_to_array)" ]; then
+    colcon_zsh_convert_to_array _values
+  fi
+  # iterate over existing values in the variable
+  for _item in $_values; do
+    # ignore empty strings
+    if [ -z "$_item" ]; then
+      continue
+    fi
+    # ignore duplicates of _value
+    if [ "$_item" = "$_value" ]; then
+      continue
+    fi
+    # keep non-duplicate values
+    _all_values="$_all_values:$_item"
+  done
+  unset _item
+  # restore the field separator
+  IFS=$_colcon_prepend_unique_value_IFS
+  unset _colcon_prepend_unique_value_IFS
+  # export the updated variable
+  eval export $_listname=\"$_all_values\"
+  unset _all_values
+  unset _values
+
+  unset _value
+  unset _listname
+}
+
+# since a plain shell script can't determine its own path when being sourced
+# either use the provided COLCON_CURRENT_PREFIX
+# or fall back to the build time prefix (if it exists)
+_colcon_package_sh_COLCON_CURRENT_PREFIX="/home/paulw/GitLab/robobin/ros2/install/robobin"
+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/robobin/hook/pythonpath.sh"
+_colcon_package_sh_source_script "$COLCON_CURRENT_PREFIX/share/robobin/hook/ament_prefix_path.sh"
+
+unset _colcon_package_sh_source_script
+unset COLCON_CURRENT_PREFIX
+
+# do not unset _colcon_prepend_unique_value since it might be used by non-primary shell hooks
diff --git a/ros2/install/robobin/share/robobin/package.xml b/ros2/install/robobin/share/robobin/package.xml
new file mode 100644
index 00000000..fd694d6d
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/package.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
+<package format="3">
+  <name>robobin</name>
+  <version>0.0.0</version>
+  <description>TODO: Package description</description>
+  <maintainer email="plw1g21@soton.ac.uk">paulw</maintainer>
+  <license>TODO: License declaration</license>
+
+  <depend>rclpy</depend>
+  <depend>std_msgs</depend>
+
+  <test_depend>ament_copyright</test_depend>
+  <test_depend>ament_flake8</test_depend>
+  <test_depend>ament_pep257</test_depend>
+  <test_depend>python3-pytest</test_depend>
+
+  <export>
+    <build_type>ament_python</build_type>
+  </export>
+</package>
diff --git a/ros2/install/robobin/share/robobin/package.zsh b/ros2/install/robobin/share/robobin/package.zsh
new file mode 100644
index 00000000..a6a5cc52
--- /dev/null
+++ b/ros2/install/robobin/share/robobin/package.zsh
@@ -0,0 +1,42 @@
+# generated from colcon_zsh/shell/template/package.zsh.em
+
+# This script extends the environment for this package.
+
+# a zsh script is able to determine its own path if necessary
+if [ -z "$COLCON_CURRENT_PREFIX" ]; then
+  # the prefix is two levels up from the package specific share directory
+  _colcon_package_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`/../.." > /dev/null && pwd)"
+else
+  _colcon_package_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX"
+fi
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+# additional arguments: arguments to the script
+_colcon_package_zsh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$@"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# function to convert array-like strings into arrays
+# to workaround SH_WORD_SPLIT not being set
+colcon_zsh_convert_to_array() {
+  local _listname=$1
+  local _dollar="$"
+  local _split="{="
+  local _to_array="(\"$_dollar$_split$_listname}\")"
+  eval $_listname=$_to_array
+}
+
+# source sh script of this package
+_colcon_package_zsh_source_script "$_colcon_package_zsh_COLCON_CURRENT_PREFIX/share/robobin/package.sh"
+unset convert_zsh_to_array
+
+unset _colcon_package_zsh_source_script
+unset _colcon_package_zsh_COLCON_CURRENT_PREFIX
diff --git a/ros2/install/setup.bash b/ros2/install/setup.bash
new file mode 100644
index 00000000..bb38dd20
--- /dev/null
+++ b/ros2/install/setup.bash
@@ -0,0 +1,31 @@
+# generated from colcon_bash/shell/template/prefix_chain.bash.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_chain_bash_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source chained prefixes
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="/opt/ros/jazzy"
+_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash"
+
+# source this prefix
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)"
+_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash"
+
+unset COLCON_CURRENT_PREFIX
+unset _colcon_prefix_chain_bash_source_script
diff --git a/ros2/install/setup.ps1 b/ros2/install/setup.ps1
new file mode 100644
index 00000000..0b38e3e7
--- /dev/null
+++ b/ros2/install/setup.ps1
@@ -0,0 +1,29 @@
+# generated from colcon_powershell/shell/template/prefix_chain.ps1.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+function _colcon_prefix_chain_powershell_source_script {
+  param (
+    $_colcon_prefix_chain_powershell_source_script_param
+  )
+  # source script with conditional trace output
+  if (Test-Path $_colcon_prefix_chain_powershell_source_script_param) {
+    if ($env:COLCON_TRACE) {
+      echo ". '$_colcon_prefix_chain_powershell_source_script_param'"
+    }
+    . "$_colcon_prefix_chain_powershell_source_script_param"
+  } else {
+    Write-Error "not found: '$_colcon_prefix_chain_powershell_source_script_param'"
+  }
+}
+
+# source chained prefixes
+_colcon_prefix_chain_powershell_source_script "/opt/ros/jazzy\local_setup.ps1"
+
+# source this prefix
+$env:COLCON_CURRENT_PREFIX=(Split-Path $PSCommandPath -Parent)
+_colcon_prefix_chain_powershell_source_script "$env:COLCON_CURRENT_PREFIX\local_setup.ps1"
diff --git a/ros2/install/setup.sh b/ros2/install/setup.sh
new file mode 100644
index 00000000..6824c942
--- /dev/null
+++ b/ros2/install/setup.sh
@@ -0,0 +1,45 @@
+# generated from colcon_core/shell/template/prefix_chain.sh.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# since a plain shell script can't determine its own path when being sourced
+# either use the provided COLCON_CURRENT_PREFIX
+# or fall back to the build time prefix (if it exists)
+_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX=/home/paulw/GitLab/robobin/ros2/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/jazzy"
+_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh"
+
+
+# source this prefix
+# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script
+COLCON_CURRENT_PREFIX="$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX"
+_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh"
+
+unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX
+unset _colcon_prefix_chain_sh_source_script
+unset COLCON_CURRENT_PREFIX
diff --git a/ros2/install/setup.zsh b/ros2/install/setup.zsh
new file mode 100644
index 00000000..6e4a496a
--- /dev/null
+++ b/ros2/install/setup.zsh
@@ -0,0 +1,31 @@
+# generated from colcon_zsh/shell/template/prefix_chain.zsh.em
+
+# This script extends the environment with the environment of other prefix
+# paths which were sourced when this file was generated as well as all packages
+# contained in this prefix path.
+
+# function to source another script with conditional trace output
+# first argument: the path of the script
+_colcon_prefix_chain_zsh_source_script() {
+  if [ -f "$1" ]; then
+    if [ -n "$COLCON_TRACE" ]; then
+      echo "# . \"$1\""
+    fi
+    . "$1"
+  else
+    echo "not found: \"$1\"" 1>&2
+  fi
+}
+
+# source chained prefixes
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="/opt/ros/jazzy"
+_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh"
+
+# source this prefix
+# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script
+COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)"
+_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh"
+
+unset COLCON_CURRENT_PREFIX
+unset _colcon_prefix_chain_zsh_source_script
diff --git a/ros2/log/COLCON_IGNORE b/ros2/log/COLCON_IGNORE
new file mode 100644
index 00000000..e69de29b
diff --git a/ros2/log/build_2024-11-14_15-20-34/events.log b/ros2/log/build_2024-11-14_15-20-34/events.log
new file mode 100644
index 00000000..7a31b124
--- /dev/null
+++ b/ros2/log/build_2024-11-14_15-20-34/events.log
@@ -0,0 +1,161 @@
+[0.000000] (-) TimerEvent: {}
+[0.001678] (robobin) JobQueued: {'identifier': 'robobin', 'dependencies': OrderedDict()}
+[0.003127] (robobin) JobStarted: {'identifier': 'robobin'}
+[0.098698] (-) TimerEvent: {}
+[0.199803] (-) TimerEvent: {}
+[0.300834] (-) TimerEvent: {}
+[0.401825] (-) TimerEvent: {}
+[0.502829] (-) TimerEvent: {}
+[0.603895] (-) TimerEvent: {}
+[0.704921] (-) TimerEvent: {}
+[0.805887] (-) TimerEvent: {}
+[0.906870] (-) TimerEvent: {}
+[1.007895] (-) TimerEvent: {}
+[1.108905] (-) TimerEvent: {}
+[1.209886] (-) TimerEvent: {}
+[1.310869] (-) TimerEvent: {}
+[1.411852] (-) TimerEvent: {}
+[1.512827] (-) TimerEvent: {}
+[1.613820] (-) TimerEvent: {}
+[1.714855] (-) TimerEvent: {}
+[1.816036] (-) TimerEvent: {}
+[1.917123] (-) TimerEvent: {}
+[2.018176] (-) TimerEvent: {}
+[2.119183] (-) TimerEvent: {}
+[2.220393] (-) TimerEvent: {}
+[2.329078] (-) TimerEvent: {}
+[2.430138] (-) TimerEvent: {}
+[2.531174] (-) TimerEvent: {}
+[2.632135] (-) TimerEvent: {}
+[2.733076] (-) TimerEvent: {}
+[2.834060] (-) TimerEvent: {}
+[2.935045] (-) TimerEvent: {}
+[3.035993] (-) TimerEvent: {}
+[3.136934] (-) TimerEvent: {}
+[3.237920] (-) TimerEvent: {}
+[3.338894] (-) TimerEvent: {}
+[3.439897] (-) TimerEvent: {}
+[3.540971] (-) TimerEvent: {}
+[3.642084] (-) TimerEvent: {}
+[3.743176] (-) TimerEvent: {}
+[3.844402] (-) TimerEvent: {}
+[3.945477] (-) TimerEvent: {}
+[4.046448] (-) TimerEvent: {}
+[4.147459] (-) TimerEvent: {}
+[4.248458] (-) TimerEvent: {}
+[4.349568] (-) TimerEvent: {}
+[4.450606] (-) TimerEvent: {}
+[4.551710] (-) TimerEvent: {}
+[4.652758] (-) TimerEvent: {}
+[4.753823] (-) TimerEvent: {}
+[4.854844] (-) TimerEvent: {}
+[4.955853] (-) TimerEvent: {}
+[5.056818] (-) TimerEvent: {}
+[5.157788] (-) TimerEvent: {}
+[5.258766] (-) TimerEvent: {}
+[5.359742] (-) TimerEvent: {}
+[5.460816] (-) TimerEvent: {}
+[5.561963] (-) TimerEvent: {}
+[5.663114] (-) TimerEvent: {}
+[5.764326] (-) TimerEvent: {}
+[5.865179] (-) TimerEvent: {}
+[5.966164] (-) TimerEvent: {}
+[6.067124] (-) TimerEvent: {}
+[6.168086] (-) TimerEvent: {}
+[6.269048] (-) TimerEvent: {}
+[6.370034] (-) TimerEvent: {}
+[6.471014] (-) TimerEvent: {}
+[6.572011] (-) TimerEvent: {}
+[6.672955] (-) TimerEvent: {}
+[6.773929] (-) TimerEvent: {}
+[6.874985] (-) TimerEvent: {}
+[6.976097] (-) TimerEvent: {}
+[7.077192] (-) TimerEvent: {}
+[7.178299] (-) TimerEvent: {}
+[7.279321] (-) TimerEvent: {}
+[7.380573] (-) TimerEvent: {}
+[7.481829] (-) TimerEvent: {}
+[7.583054] (-) TimerEvent: {}
+[7.627412] (robobin) Command: {'cmd': ['/usr/bin/python3', '-W', 'ignore:setup.py install is deprecated', 'setup.py', 'egg_info', '--egg-base', '../../build/robobin', 'build', '--build-base', '/home/paulw/GitLab/robobin/ros2/build/robobin/build', 'install', '--record', '/home/paulw/GitLab/robobin/ros2/build/robobin/install.log', '--single-version-externally-managed', 'install_data'], 'cwd': '/home/paulw/GitLab/robobin/ros2/src/robobin', 'env': {'LESSOPEN': '| /usr/bin/lesspipe %s', 'USER': 'paulw', 'SSH_CLIENT': '192.168.0.20 57325 22', 'XDG_SESSION_TYPE': 'tty', 'SHLVL': '1', 'LD_LIBRARY_PATH': '/opt/ros/jazzy/lib/aarch64-linux-gnu:/opt/ros/jazzy/lib', 'HOME': '/home/paulw', 'OLDPWD': '/home/paulw/GitLab/robobin/ros2/src', 'SSH_TTY': '/dev/pts/0', 'ROS_PYTHON_VERSION': '3', 'DBUS_SESSION_BUS_ADDRESS': 'unix:path=/run/user/1000/bus', 'ROS_DISTRO': 'jazzy', 'LOGNAME': 'paulw', '_': '/usr/bin/colcon', 'ROS_VERSION': '2', 'XDG_SESSION_CLASS': 'user', 'TERM': 'xterm-256color', 'XDG_SESSION_ID': '5', 'PATH': '/opt/ros/jazzy/bin:/home/paulw/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin', 'XDG_RUNTIME_DIR': '/run/user/1000', 'LANG': 'en_US.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=00: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:*.avif=01;35:*.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:*~=00;90:*#=00;90:*.bak=00;90:*.crdownload=00;90:*.dpkg-dist=00;90:*.dpkg-new=00;90:*.dpkg-old=00;90:*.dpkg-tmp=00;90:*.old=00;90:*.orig=00;90:*.part=00;90:*.rej=00;90:*.rpmnew=00;90:*.rpmorig=00;90:*.rpmsave=00;90:*.swp=00;90:*.tmp=00;90:*.ucf-dist=00;90:*.ucf-new=00;90:*.ucf-old=00;90:', 'AMENT_PREFIX_PATH': '/opt/ros/jazzy', 'SHELL': '/bin/bash', 'LESSCLOSE': '/usr/bin/lesspipe %s %s', 'ROS_AUTOMATIC_DISCOVERY_RANGE': 'SUBNET', 'PWD': '/home/paulw/GitLab/robobin/ros2/build/robobin', 'SSH_CONNECTION': '192.168.0.20 57325 192.168.0.46 22', 'XDG_DATA_DIRS': '/usr/local/share:/usr/share:/var/lib/snapd/desktop', 'PYTHONPATH': '/home/paulw/GitLab/robobin/ros2/build/robobin/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages:/opt/ros/jazzy/lib/python3.12/site-packages', 'COLCON': '1'}, 'shell': False}
+[7.683402] (-) TimerEvent: {}
+[7.784542] (-) TimerEvent: {}
+[7.885536] (-) TimerEvent: {}
+[7.986426] (-) TimerEvent: {}
+[8.087425] (-) TimerEvent: {}
+[8.188383] (-) TimerEvent: {}
+[8.289335] (-) TimerEvent: {}
+[8.390302] (-) TimerEvent: {}
+[8.491378] (-) TimerEvent: {}
+[8.592345] (-) TimerEvent: {}
+[8.693297] (-) TimerEvent: {}
+[8.794182] (-) TimerEvent: {}
+[8.895132] (-) TimerEvent: {}
+[8.996100] (-) TimerEvent: {}
+[9.097069] (-) TimerEvent: {}
+[9.197996] (-) TimerEvent: {}
+[9.298977] (-) TimerEvent: {}
+[9.399999] (-) TimerEvent: {}
+[9.500959] (-) TimerEvent: {}
+[9.601941] (-) TimerEvent: {}
+[9.702929] (-) TimerEvent: {}
+[9.750638] (robobin) StdoutLine: {'line': b'running egg_info\n'}
+[9.753005] (robobin) StdoutLine: {'line': b'creating ../../build/robobin/robobin.egg-info\n'}
+[9.803158] (-) TimerEvent: {}
+[9.898763] (robobin) StdoutLine: {'line': b'writing ../../build/robobin/robobin.egg-info/PKG-INFO\n'}
+[9.900953] (robobin) StdoutLine: {'line': b'writing dependency_links to ../../build/robobin/robobin.egg-info/dependency_links.txt\n'}
+[9.902482] (robobin) StdoutLine: {'line': b'writing entry points to ../../build/robobin/robobin.egg-info/entry_points.txt\n'}
+[9.903479] (-) TimerEvent: {}
+[9.904689] (robobin) StdoutLine: {'line': b'writing requirements to ../../build/robobin/robobin.egg-info/requires.txt\n'}
+[9.905850] (robobin) StdoutLine: {'line': b'writing top-level names to ../../build/robobin/robobin.egg-info/top_level.txt\n'}
+[9.907002] (robobin) StdoutLine: {'line': b"writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'\n"}
+[10.003711] (-) TimerEvent: {}
+[10.104710] (-) TimerEvent: {}
+[10.205843] (robobin) StdoutLine: {'line': b"reading manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'\n"}
+[10.206889] (-) TimerEvent: {}
+[10.211277] (robobin) StdoutLine: {'line': b"writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'\n"}
+[10.212575] (robobin) StdoutLine: {'line': b'running build\n'}
+[10.213640] (robobin) StdoutLine: {'line': b'running build_py\n'}
+[10.214729] (robobin) StdoutLine: {'line': b'creating /home/paulw/GitLab/robobin/ros2/build/robobin/build\n'}
+[10.215962] (robobin) StdoutLine: {'line': b'creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib\n'}
+[10.217366] (robobin) StdoutLine: {'line': b'creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin\n'}
+[10.218196] (robobin) StdoutLine: {'line': b'copying robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin\n'}
+[10.219424] (robobin) StdoutLine: {'line': b'copying robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin\n'}
+[10.220878] (robobin) StdoutLine: {'line': b'running install\n'}
+[10.277056] (robobin) StdoutLine: {'line': b'running install_lib\n'}
+[10.307117] (-) TimerEvent: {}
+[10.408083] (-) TimerEvent: {}
+[10.427441] (robobin) StdoutLine: {'line': b'creating /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin\n'}
+[10.428655] (robobin) StdoutLine: {'line': b'copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin\n'}
+[10.430091] (robobin) StdoutLine: {'line': b'copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin\n'}
+[10.434719] (robobin) StdoutLine: {'line': b'byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py to __init__.cpython-312.pyc\n'}
+[10.437346] (robobin) StdoutLine: {'line': b'byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py to api_node.cpython-312.pyc\n'}
+[10.440831] (robobin) StdoutLine: {'line': b'running install_data\n'}
+[10.442167] (robobin) StdoutLine: {'line': b'creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index\n'}
+[10.443586] (robobin) StdoutLine: {'line': b'creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index\n'}
+[10.444918] (robobin) StdoutLine: {'line': b'creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages\n'}
+[10.445851] (robobin) StdoutLine: {'line': b'copying resource/robobin -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages\n'}
+[10.447087] (robobin) StdoutLine: {'line': b'copying package.xml -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin\n'}
+[10.448351] (robobin) StdoutLine: {'line': b'running install_egg_info\n'}
+[10.508362] (-) TimerEvent: {}
+[10.608566] (robobin) StdoutLine: {'line': b'Copying ../../build/robobin/robobin.egg-info to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info\n'}
+[10.609588] (-) TimerEvent: {}
+[10.618969] (robobin) StdoutLine: {'line': b'running install_scripts\n'}
+[10.709836] (-) TimerEvent: {}
+[10.810901] (-) TimerEvent: {}
+[10.912006] (-) TimerEvent: {}
+[11.012984] (-) TimerEvent: {}
+[11.113971] (-) TimerEvent: {}
+[11.214936] (-) TimerEvent: {}
+[11.315916] (-) TimerEvent: {}
+[11.416930] (-) TimerEvent: {}
+[11.517928] (-) TimerEvent: {}
+[11.618940] (-) TimerEvent: {}
+[11.690523] (robobin) StdoutLine: {'line': b'Installing api_node script to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/robobin\n'}
+[11.693152] (robobin) StdoutLine: {'line': b"writing list of installed files to '/home/paulw/GitLab/robobin/ros2/build/robobin/install.log'\n"}
+[11.719376] (-) TimerEvent: {}
+[11.820461] (-) TimerEvent: {}
+[11.921626] (-) TimerEvent: {}
+[11.967974] (robobin) CommandEnded: {'returncode': 0}
+[12.023487] (-) TimerEvent: {}
+[12.059042] (robobin) JobEnded: {'identifier': 'robobin', 'rc': 0}
+[12.064874] (-) EventReactorShutdown: {}
diff --git a/ros2/log/build_2024-11-14_15-20-34/logger_all.log b/ros2/log/build_2024-11-14_15-20-34/logger_all.log
new file mode 100644
index 00000000..1e0be30c
--- /dev/null
+++ b/ros2/log/build_2024-11-14_15-20-34/logger_all.log
@@ -0,0 +1,128 @@
+[1.050s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build']
+[1.051s] DEBUG:colcon:Parsed command line arguments: Namespace(log_base=None, log_level=None, verb_name='build', build_base='build', install_base='install', merge_install=False, symlink_install=False, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=4, 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, allow_overriding=[], 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, verb_parser=<colcon_defaults.argument_parser.defaults.DefaultArgumentsDecorator object at 0xffff89bbfbf0>, verb_extension=<colcon_core.verb.build.BuildVerb object at 0xffff89d62a20>, main=<bound method BuildVerb.main of <colcon_core.verb.build.BuildVerb object at 0xffff89d62a20>>)
+[1.397s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters
+[1.398s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters
+[1.398s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters
+[1.398s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters
+[1.398s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover
+[1.399s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover
+[1.399s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/home/paulw/GitLab/robobin/ros2'
+[1.400s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install']
+[1.401s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore'
+[1.401s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install'
+[1.402s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg']
+[1.402s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg'
+[1.402s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta']
+[1.402s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta'
+[1.403s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros']
+[1.403s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros'
+[1.608s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python']
+[1.609s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake'
+[1.609s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python'
+[1.610s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py']
+[1.610s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py'
+[1.611s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install']
+[1.611s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore'
+[1.612s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored
+[1.613s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install']
+[1.613s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore'
+[1.614s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored
+[1.614s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install']
+[1.615s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore'
+[1.615s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored
+[1.616s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ignore', 'ignore_ament_install']
+[1.617s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore'
+[1.617s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ignore_ament_install'
+[1.618s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_pkg']
+[1.618s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_pkg'
+[1.618s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['colcon_meta']
+[1.618s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'colcon_meta'
+[1.619s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['ros']
+[1.619s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'ros'
+[1.620s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['cmake', 'python']
+[1.620s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'cmake'
+[1.620s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python'
+[1.621s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extensions ['python_setup_py']
+[1.621s] Level 1:colcon.colcon_core.package_identification:_identify(src) by extension 'python_setup_py'
+[1.622s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extensions ['ignore', 'ignore_ament_install']
+[1.622s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extension 'ignore'
+[1.623s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extension 'ignore_ament_install'
+[1.623s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extensions ['colcon_pkg']
+[1.624s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extension 'colcon_pkg'
+[1.624s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extensions ['colcon_meta']
+[1.624s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extension 'colcon_meta'
+[1.625s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extensions ['ros']
+[1.625s] Level 1:colcon.colcon_core.package_identification:_identify(src/robobin) by extension 'ros'
+[1.659s] DEBUG:colcon.colcon_core.package_identification:Package 'src/robobin' with type 'ros.ament_python' and name 'robobin'
+[1.659s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults
+[1.660s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover
+[1.660s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults
+[1.660s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover
+[1.660s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults
+[1.871s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) check parameters
+[1.871s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) discover
+[1.898s] DEBUG:colcon.colcon_installed_package_information.package_discovery:Found 192 installed packages in /opt/ros/jazzy
+[1.903s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) using defaults
+[2.198s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'cmake_args' from command line to 'None'
+[2.198s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'cmake_target' from command line to 'None'
+[2.199s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'cmake_target_skip_unavailable' from command line to 'False'
+[2.199s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'cmake_clean_cache' from command line to 'False'
+[2.199s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'cmake_clean_first' from command line to 'False'
+[2.199s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'cmake_force_configure' from command line to 'False'
+[2.199s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'ament_cmake_args' from command line to 'None'
+[2.199s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'catkin_cmake_args' from command line to 'None'
+[2.200s] Level 5:colcon.colcon_core.verb:set package 'robobin' build argument 'catkin_skip_building_tests' from command line to 'False'
+[2.200s] DEBUG:colcon.colcon_core.verb:Building package 'robobin' with the following arguments: {'ament_cmake_args': None, 'build_base': '/home/paulw/GitLab/robobin/ros2/build/robobin', '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': '/home/paulw/GitLab/robobin/ros2/install/robobin', 'merge_install': False, 'path': '/home/paulw/GitLab/robobin/ros2/src/robobin', 'symlink_install': False, 'test_result_base': None}
+[2.201s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor
+[2.206s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete
+[2.208s] INFO:colcon.colcon_ros.task.ament_python.build:Building ROS package in '/home/paulw/GitLab/robobin/ros2/src/robobin' with build type 'ament_python'
+[2.209s] Level 1:colcon.colcon_core.shell:create_environment_hook('robobin', 'ament_prefix_path')
+[2.229s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems
+[2.230s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/hook/ament_prefix_path.ps1'
+[2.237s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/hook/ament_prefix_path.dsv'
+[2.242s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/hook/ament_prefix_path.sh'
+[2.248s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell
+[2.248s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment
+[4.035s] INFO:colcon.colcon_core.task.python.build:Building Python package in '/home/paulw/GitLab/robobin/ros2/src/robobin'
+[4.037s] INFO:colcon.colcon_core.shell:Skip shell extension 'powershell' for command environment: Not usable outside of PowerShell
+[4.037s] DEBUG:colcon.colcon_core.shell:Skip shell extension 'dsv' for command environment
+[9.840s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoking command in '/home/paulw/GitLab/robobin/ros2/src/robobin': PYTHONPATH=/home/paulw/GitLab/robobin/ros2/build/robobin/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated setup.py egg_info --egg-base ../../build/robobin build --build-base /home/paulw/GitLab/robobin/ros2/build/robobin/build install --record /home/paulw/GitLab/robobin/ros2/build/robobin/install.log --single-version-externally-managed install_data
+[14.175s] DEBUG:colcon.colcon_core.event_handler.log_command:Invoked command in '/home/paulw/GitLab/robobin/ros2/src/robobin' returned '0': PYTHONPATH=/home/paulw/GitLab/robobin/ros2/build/robobin/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated setup.py egg_info --egg-base ../../build/robobin build --build-base /home/paulw/GitLab/robobin/ros2/build/robobin/build install --record /home/paulw/GitLab/robobin/ros2/build/robobin/install.log --single-version-externally-managed install_data
+[14.199s] Level 1:colcon.colcon_core.environment:checking '/home/paulw/GitLab/robobin/ros2/install/robobin' for CMake module files
+[14.204s] Level 1:colcon.colcon_core.environment:checking '/home/paulw/GitLab/robobin/ros2/install/robobin' for CMake config files
+[14.209s] Level 1:colcon.colcon_core.environment:checking '/home/paulw/GitLab/robobin/ros2/install/robobin/lib'
+[14.211s] Level 1:colcon.colcon_core.environment:checking '/home/paulw/GitLab/robobin/ros2/install/robobin/bin'
+[14.211s] Level 1:colcon.colcon_core.environment:checking '/home/paulw/GitLab/robobin/ros2/install/robobin/lib/pkgconfig/robobin.pc'
+[14.213s] Level 1:colcon.colcon_core.environment:checking '/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages'
+[14.214s] Level 1:colcon.colcon_core.shell:create_environment_hook('robobin', 'pythonpath')
+[14.216s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/hook/pythonpath.ps1'
+[14.219s] INFO:colcon.colcon_core.shell:Creating environment descriptor '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/hook/pythonpath.dsv'
+[14.221s] INFO:colcon.colcon_core.shell:Creating environment hook '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/hook/pythonpath.sh'
+[14.226s] Level 1:colcon.colcon_core.environment:checking '/home/paulw/GitLab/robobin/ros2/install/robobin/bin'
+[14.226s] Level 1:colcon.colcon_core.environment:create_environment_scripts_only(robobin)
+[14.228s] INFO:colcon.colcon_core.shell:Creating package script '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/package.ps1'
+[14.236s] INFO:colcon.colcon_core.shell:Creating package descriptor '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/package.dsv'
+[14.242s] INFO:colcon.colcon_core.shell:Creating package script '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/package.sh'
+[14.248s] INFO:colcon.colcon_core.shell:Creating package script '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/package.bash'
+[14.256s] INFO:colcon.colcon_core.shell:Creating package script '/home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin/package.zsh'
+[14.262s] Level 1:colcon.colcon_core.environment:create_file_with_runtime_dependencies(/home/paulw/GitLab/robobin/ros2/install/robobin/share/colcon-core/packages/robobin)
+[14.265s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop
+[14.268s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed
+[14.269s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0'
+[14.269s] DEBUG:colcon.colcon_core.event_reactor:joining thread
+[14.324s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.notify_send': Could not find 'notify-send'
+[14.325s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems
+[14.325s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems
+[14.325s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2'
+[14.438s] DEBUG:colcon.colcon_notification.desktop_notification.notify2:Failed to initialize notify2: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.Notifications was not provided by any .service files
+[14.438s] DEBUG:colcon.colcon_core.event_reactor:joined thread
+[14.440s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/paulw/GitLab/robobin/ros2/install/local_setup.ps1'
+[14.449s] INFO:colcon.colcon_core.shell:Creating prefix util module '/home/paulw/GitLab/robobin/ros2/install/_local_setup_util_ps1.py'
+[14.460s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/paulw/GitLab/robobin/ros2/install/setup.ps1'
+[14.468s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/paulw/GitLab/robobin/ros2/install/local_setup.sh'
+[14.473s] INFO:colcon.colcon_core.shell:Creating prefix util module '/home/paulw/GitLab/robobin/ros2/install/_local_setup_util_sh.py'
+[14.478s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/paulw/GitLab/robobin/ros2/install/setup.sh'
+[14.486s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/paulw/GitLab/robobin/ros2/install/local_setup.bash'
+[14.491s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/paulw/GitLab/robobin/ros2/install/setup.bash'
+[14.499s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/paulw/GitLab/robobin/ros2/install/local_setup.zsh'
+[14.505s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/paulw/GitLab/robobin/ros2/install/setup.zsh'
diff --git a/ros2/log/build_2024-11-14_15-20-34/robobin/command.log b/ros2/log/build_2024-11-14_15-20-34/robobin/command.log
new file mode 100644
index 00000000..64b7945c
--- /dev/null
+++ b/ros2/log/build_2024-11-14_15-20-34/robobin/command.log
@@ -0,0 +1,2 @@
+Invoking command in '/home/paulw/GitLab/robobin/ros2/src/robobin': PYTHONPATH=/home/paulw/GitLab/robobin/ros2/build/robobin/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated setup.py egg_info --egg-base ../../build/robobin build --build-base /home/paulw/GitLab/robobin/ros2/build/robobin/build install --record /home/paulw/GitLab/robobin/ros2/build/robobin/install.log --single-version-externally-managed install_data
+Invoked command in '/home/paulw/GitLab/robobin/ros2/src/robobin' returned '0': PYTHONPATH=/home/paulw/GitLab/robobin/ros2/build/robobin/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated setup.py egg_info --egg-base ../../build/robobin build --build-base /home/paulw/GitLab/robobin/ros2/build/robobin/build install --record /home/paulw/GitLab/robobin/ros2/build/robobin/install.log --single-version-externally-managed install_data
diff --git a/ros2/log/build_2024-11-14_15-20-34/robobin/stderr.log b/ros2/log/build_2024-11-14_15-20-34/robobin/stderr.log
new file mode 100644
index 00000000..e69de29b
diff --git a/ros2/log/build_2024-11-14_15-20-34/robobin/stdout.log b/ros2/log/build_2024-11-14_15-20-34/robobin/stdout.log
new file mode 100644
index 00000000..4675a79e
--- /dev/null
+++ b/ros2/log/build_2024-11-14_15-20-34/robobin/stdout.log
@@ -0,0 +1,35 @@
+running egg_info
+creating ../../build/robobin/robobin.egg-info
+writing ../../build/robobin/robobin.egg-info/PKG-INFO
+writing dependency_links to ../../build/robobin/robobin.egg-info/dependency_links.txt
+writing entry points to ../../build/robobin/robobin.egg-info/entry_points.txt
+writing requirements to ../../build/robobin/robobin.egg-info/requires.txt
+writing top-level names to ../../build/robobin/robobin.egg-info/top_level.txt
+writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+reading manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+running build
+running build_py
+creating /home/paulw/GitLab/robobin/ros2/build/robobin/build
+creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib
+creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+copying robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+copying robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+running install
+running install_lib
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py to __init__.cpython-312.pyc
+byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py to api_node.cpython-312.pyc
+running install_data
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages
+copying resource/robobin -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages
+copying package.xml -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin
+running install_egg_info
+Copying ../../build/robobin/robobin.egg-info to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info
+running install_scripts
+Installing api_node script to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/robobin
+writing list of installed files to '/home/paulw/GitLab/robobin/ros2/build/robobin/install.log'
diff --git a/ros2/log/build_2024-11-14_15-20-34/robobin/stdout_stderr.log b/ros2/log/build_2024-11-14_15-20-34/robobin/stdout_stderr.log
new file mode 100644
index 00000000..4675a79e
--- /dev/null
+++ b/ros2/log/build_2024-11-14_15-20-34/robobin/stdout_stderr.log
@@ -0,0 +1,35 @@
+running egg_info
+creating ../../build/robobin/robobin.egg-info
+writing ../../build/robobin/robobin.egg-info/PKG-INFO
+writing dependency_links to ../../build/robobin/robobin.egg-info/dependency_links.txt
+writing entry points to ../../build/robobin/robobin.egg-info/entry_points.txt
+writing requirements to ../../build/robobin/robobin.egg-info/requires.txt
+writing top-level names to ../../build/robobin/robobin.egg-info/top_level.txt
+writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+reading manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+running build
+running build_py
+creating /home/paulw/GitLab/robobin/ros2/build/robobin/build
+creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib
+creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+copying robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+copying robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+running install
+running install_lib
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py to __init__.cpython-312.pyc
+byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py to api_node.cpython-312.pyc
+running install_data
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index
+creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages
+copying resource/robobin -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages
+copying package.xml -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin
+running install_egg_info
+Copying ../../build/robobin/robobin.egg-info to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info
+running install_scripts
+Installing api_node script to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/robobin
+writing list of installed files to '/home/paulw/GitLab/robobin/ros2/build/robobin/install.log'
diff --git a/ros2/log/build_2024-11-14_15-20-34/robobin/streams.log b/ros2/log/build_2024-11-14_15-20-34/robobin/streams.log
new file mode 100644
index 00000000..66ea27d9
--- /dev/null
+++ b/ros2/log/build_2024-11-14_15-20-34/robobin/streams.log
@@ -0,0 +1,37 @@
+[7.631s] Invoking command in '/home/paulw/GitLab/robobin/ros2/src/robobin': PYTHONPATH=/home/paulw/GitLab/robobin/ros2/build/robobin/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated setup.py egg_info --egg-base ../../build/robobin build --build-base /home/paulw/GitLab/robobin/ros2/build/robobin/build install --record /home/paulw/GitLab/robobin/ros2/build/robobin/install.log --single-version-externally-managed install_data
+[9.748s] running egg_info
+[9.751s] creating ../../build/robobin/robobin.egg-info
+[9.896s] writing ../../build/robobin/robobin.egg-info/PKG-INFO
+[9.899s] writing dependency_links to ../../build/robobin/robobin.egg-info/dependency_links.txt
+[9.900s] writing entry points to ../../build/robobin/robobin.egg-info/entry_points.txt
+[9.902s] writing requirements to ../../build/robobin/robobin.egg-info/requires.txt
+[9.904s] writing top-level names to ../../build/robobin/robobin.egg-info/top_level.txt
+[9.904s] writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+[10.203s] reading manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+[10.209s] writing manifest file '../../build/robobin/robobin.egg-info/SOURCES.txt'
+[10.210s] running build
+[10.211s] running build_py
+[10.212s] creating /home/paulw/GitLab/robobin/ros2/build/robobin/build
+[10.214s] creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib
+[10.215s] creating /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+[10.216s] copying robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+[10.217s] copying robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin
+[10.218s] running install
+[10.275s] running install_lib
+[10.425s] creating /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+[10.426s] copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/__init__.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+[10.428s] copying /home/paulw/GitLab/robobin/ros2/build/robobin/build/lib/robobin/api_node.py -> /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin
+[10.432s] byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/__init__.py to __init__.cpython-312.pyc
+[10.435s] byte-compiling /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin/api_node.py to api_node.cpython-312.pyc
+[10.438s] running install_data
+[10.440s] creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index
+[10.441s] creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index
+[10.442s] creating /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages
+[10.443s] copying resource/robobin -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/ament_index/resource_index/packages
+[10.445s] copying package.xml -> /home/paulw/GitLab/robobin/ros2/install/robobin/share/robobin
+[10.446s] running install_egg_info
+[10.606s] Copying ../../build/robobin/robobin.egg-info to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages/robobin-0.0.0-py3.12.egg-info
+[10.617s] running install_scripts
+[11.688s] Installing api_node script to /home/paulw/GitLab/robobin/ros2/install/robobin/lib/robobin
+[11.691s] writing list of installed files to '/home/paulw/GitLab/robobin/ros2/build/robobin/install.log'
+[11.966s] Invoked command in '/home/paulw/GitLab/robobin/ros2/src/robobin' returned '0': PYTHONPATH=/home/paulw/GitLab/robobin/ros2/build/robobin/prefix_override:/usr/lib/python3/dist-packages/colcon_core/task/python/colcon_distutils_commands:/home/paulw/GitLab/robobin/ros2/install/robobin/lib/python3.12/site-packages:${PYTHONPATH} /usr/bin/python3 -W ignore:setup.py install is deprecated setup.py egg_info --egg-base ../../build/robobin build --build-base /home/paulw/GitLab/robobin/ros2/build/robobin/build install --record /home/paulw/GitLab/robobin/ros2/build/robobin/install.log --single-version-externally-managed install_data
diff --git a/ros2/log/latest b/ros2/log/latest
new file mode 120000
index 00000000..b57d247c
--- /dev/null
+++ b/ros2/log/latest
@@ -0,0 +1 @@
+latest_build
\ No newline at end of file
diff --git a/ros2/log/latest_build b/ros2/log/latest_build
new file mode 120000
index 00000000..477b5618
--- /dev/null
+++ b/ros2/log/latest_build
@@ -0,0 +1 @@
+build_2024-11-14_15-20-34
\ No newline at end of file
diff --git a/ros2/src/robobin/robobin/api_node.py b/ros2/src/robobin/robobin/api_node.py
new file mode 100644
index 00000000..2a718548
--- /dev/null
+++ b/ros2/src/robobin/robobin/api_node.py
@@ -0,0 +1,24 @@
+# robobin/api_node.py
+
+import rclpy
+from rclpy.node import Node
+
+class ApiNode(Node):
+    def __init__(self):
+        super().__init__('api_node')
+        self.get_logger().info("ApiNode has been started.")
+
+def main(args=None):
+    rclpy.init(args=args)
+    node = ApiNode()
+    try:
+        rclpy.spin(node)
+    except KeyboardInterrupt:
+        pass
+    finally:
+        node.destroy_node()
+        rclpy.shutdown()
+
+if __name__ == '__main__':
+    main()
+
diff --git a/ros2/src/robobin/setup.py b/ros2/src/robobin/setup.py
index d24076af..b7aa96e6 100644
--- a/ros2/src/robobin/setup.py
+++ b/ros2/src/robobin/setup.py
@@ -20,6 +20,7 @@ setup(
     tests_require=['pytest'],
     entry_points={
         'console_scripts': [
-        ],
+        'api_node = robobin.api_node:main',
+	],
     },
 )
-- 
GitLab