diff --git a/README.md b/README.md
index 018616e..eb9f568 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ Ref: https://docs.ros.org/en/foxy/Tutorials/Beginner-Client-Libraries/Creating-A
cd ~
```
-4. Go to src folder in your workspace
+4. Go to src folder in your workspace. Change my_name_ws accordingly
```shell script
cd my_name_ws/src/
@@ -55,6 +55,65 @@ sudo rosdep init
rosdep update
```
+5. Open VSCode, got to the menu and select file, an then select open folder and select our workspace in home. This show our workspace in the VScode explorer
+
+6. In a terminal go to your workspace
+
+```shell script
+colcon build
+```
+
+7. Sourve the overlay according to your distro
+
+```shell script
+source /opt/ros/foxy/setup.bash
+```
+8.
+
+```shell script
+. install/local_setup.bash
+```
+
+
+## Virtual Environment Setup in Linux
+
+https://docs.ros.org/en/foxy/How-To-Guides/Using-Python-Packages.html
+
+```shell script
+sudo apt install python3-pip
+```
+
+```shell script
+sudo apt install python3-virtualenv
+```
+### Make a virtual env and activate it
+
+From your workspace directory run this command
+
+```shell script
+virtualenv -p python3 ./venv
+```
+```shell script
+source ./venv/bin/activate
+```
+
+Make sure that colcon doesn’t try to build the venv
+```shell script
+touch ./venv/COLCON_IGNORE
+```
+
+
+Next, install the Python packages that you want in your virtual environment:
+
+if any requirement file is in the src folder, then install them for command line
+
+```shell script
+pip install -r src/requirements.txt
+```
+
+Now you can build your workspace and run your python node that depends on packages installed in your virtual environment.
+
+
## Source Control Recommendations
@@ -66,3 +125,29 @@ rosdep update
BUENOS DIAS :)
+ADIOS
+hola willy
+HOla reyes
+
+feliz cumpleaños willy
+
+GOLFITO
+
+
+
+
+
+AMIGO BLESS CHIMBA
+Paso por ti a las 2 ve arreglandote ;)
+De medallo vea pues
+JH
+
+Feliz cumpleaños willito :)
+Que rompa la piñata no
+que la rompa raulito no
+que la rompa carlitos no
+que la rompa WIllyto
+SIUUU
+
+Hola chamito
+hi
diff --git a/henry_pkg/henry_pkg/__init__.py b/henry_pkg/henry_pkg/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/henry_pkg/henry_pkg/fis.py b/henry_pkg/henry_pkg/fis.py
new file mode 100644
index 0000000..cebfbda
--- /dev/null
+++ b/henry_pkg/henry_pkg/fis.py
@@ -0,0 +1,33 @@
+import numpy as np
+import skfuzzy as fuzz
+from skfuzzy import control as ctrl
+
+# New Antecedent/Consequent objects hold universe variables and membership
+# functions
+quality = ctrl.Antecedent(np.arange(0, 11, 1), 'quality')
+service = ctrl.Antecedent(np.arange(0, 11, 1), 'service')
+tip = ctrl.Consequent(np.arange(0, 26, 1), 'tip')
+
+# Auto-membership function population is possible with .automf(3, 5, or 7)
+quality.automf(3)
+service.automf(3)
+
+# Custom membership functions can be built interactively with a familiar,
+# Pythonic API
+tip['low'] = fuzz.trimf(tip.universe, [0, 0, 13])
+tip['medium'] = fuzz.trimf(tip.universe, [0, 13, 25])
+tip['high'] = fuzz.trimf(tip.universe, [13, 25, 25])
+
+rule1 = ctrl.Rule(quality['poor'] | service['poor'], tip['low'])
+rule2 = ctrl.Rule(service['average'], tip['medium'])
+rule3 = ctrl.Rule(service['good'] | quality['good'], tip['high'])
+
+rule1.view()
+
+tipping_ctrl = ctrl.ControlSystem([rule1, rule2, rule3])
+
+def main(args=None):
+ print()
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/henry_pkg/henry_pkg/my_pub.py b/henry_pkg/henry_pkg/my_pub.py
new file mode 100644
index 0000000..fff0ae1
--- /dev/null
+++ b/henry_pkg/henry_pkg/my_pub.py
@@ -0,0 +1,39 @@
+import rclpy
+from rclpy.node import Node
+
+from std_msgs.msg import String
+
+
+class MinimalPublisher(Node):
+
+ def __init__(self):
+ super().__init__('minimal_publisher')
+ self.publisher_ = self.create_publisher(String, 'topic', 10)
+ timer_period = 0.5 # seconds
+ self.timer = self.create_timer(timer_period, self.timer_callback)
+ self.i = 0
+
+ def timer_callback(self):
+ msg = String()
+ msg.data = 'Hello World: %d' % self.i
+ self.publisher_.publish(msg)
+ self.get_logger().info('Publishing: "%s"' % msg.data)
+ self.i += 1
+
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ minimal_publisher = MinimalPublisher()
+
+ rclpy.spin(minimal_publisher)
+
+ # Destroy the node explicitly
+ # (optional - otherwise it will be done automatically
+ # when the garbage collector destroys the node object)
+ minimal_publisher.destroy_node()
+ rclpy.shutdown()
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/henry_pkg/henry_pkg/server.py b/henry_pkg/henry_pkg/server.py
new file mode 100644
index 0000000..cfd482f
--- /dev/null
+++ b/henry_pkg/henry_pkg/server.py
@@ -0,0 +1,55 @@
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Image
+from lolito_interfaces.srv import CaptureImage
+
+
+class ImageCaptureServer(Node):
+ def __init__(self):
+ super().__init__('image_capture_server')
+ self.srv = self.create_service(CaptureImage, 'capture_image', self.capture_image_callback)
+
+ def capture_image_callback(self, request, response):
+ # Aquí es donde capturamos la imagen y la enviamos como respuesta
+ image = self.capture_image()
+ response.image = image
+ return response
+
+ def capture_image(self):
+ # En este ejemplo, utilizamos la biblioteca OpenCV para capturar la imagen
+ import cv2
+
+ # Capturamos la imagen de la cámara web
+ cap = cv2.VideoCapture(0)
+ _, frame = cap.read()
+
+ # Convertimos la imagen capturada a un mensaje ROS
+ msg = Image()
+ msg.header.frame_id = 'camera'
+ msg.encoding = 'bgr8'
+ msg.height, msg.width, _ = frame.shape
+ msg.step = 3 * msg.width
+ msg.data = frame.tobytes()
+
+ # Liberamos la cámara web
+ cap.release()
+
+ return msg
+
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ node = ImageCaptureServer()
+
+ try:
+ rclpy.spin(node)
+ except KeyboardInterrupt:
+ pass
+
+ node.destroy_node()
+ rclpy.shutdown()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/henry_pkg/package.xml b/henry_pkg/package.xml
new file mode 100644
index 0000000..abad098
--- /dev/null
+++ b/henry_pkg/package.xml
@@ -0,0 +1,30 @@
+
+
+
+ henry_pkg
+ 0.0.0
+ TODO: Package description
+ roncanciovl
+ Apache License 2.0
+
+ rclpy
+ std_msgs
+ sensor_msgs
+ example_interfaces
+
+ rosidl_default_generators
+ rosidl_default_runtime
+ rosidl_interface_packages
+
+
+
+ ament_copyright
+
+ ament_flake8
+ ament_pep257
+ python3-pytest
+
+
+ ament_python
+
+
diff --git a/henry_pkg/resource/henry_pkg b/henry_pkg/resource/henry_pkg
new file mode 100644
index 0000000..e69de29
diff --git a/henry_pkg/setup.cfg b/henry_pkg/setup.cfg
new file mode 100644
index 0000000..6beb4db
--- /dev/null
+++ b/henry_pkg/setup.cfg
@@ -0,0 +1,4 @@
+[develop]
+script-dir=$base/lib/henry_pkg
+[install]
+install-scripts=$base/lib/henry_pkg
diff --git a/henry_pkg/setup.py b/henry_pkg/setup.py
new file mode 100644
index 0000000..a3dc297
--- /dev/null
+++ b/henry_pkg/setup.py
@@ -0,0 +1,27 @@
+from setuptools import setup
+
+package_name = 'henry_pkg'
+
+setup(
+ name=package_name,
+ version='0.0.0',
+ packages=[package_name],
+ data_files=[
+ ('share/ament_index/resource_index/packages',
+ ['resource/' + package_name]),
+ ('share/' + package_name, ['package.xml']),
+ ],
+ install_requires=['setuptools'],
+ zip_safe=True,
+ maintainer='roncanciovl',
+ maintainer_email='henryroncanciovelandia@gmail.com',
+ description='TODO: Package description',
+ license='Apache License 2.0',
+ tests_require=['pytest'],
+ entry_points={
+ 'console_scripts': [
+ 'talker = henry_pkg.my_pub:main',
+ 'imageServer = henry_pkg.server:main',
+ ],
+ },
+)
diff --git a/henry_pkg/test/test_copyright.py b/henry_pkg/test/test_copyright.py
new file mode 100644
index 0000000..cc8ff03
--- /dev/null
+++ b/henry_pkg/test/test_copyright.py
@@ -0,0 +1,23 @@
+# Copyright 2015 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_copyright.main import main
+import pytest
+
+
+@pytest.mark.copyright
+@pytest.mark.linter
+def test_copyright():
+ rc = main(argv=['.', 'test'])
+ assert rc == 0, 'Found errors'
diff --git a/henry_pkg/test/test_flake8.py b/henry_pkg/test/test_flake8.py
new file mode 100644
index 0000000..27ee107
--- /dev/null
+++ b/henry_pkg/test/test_flake8.py
@@ -0,0 +1,25 @@
+# Copyright 2017 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_flake8.main import main_with_errors
+import pytest
+
+
+@pytest.mark.flake8
+@pytest.mark.linter
+def test_flake8():
+ rc, errors = main_with_errors(argv=[])
+ assert rc == 0, \
+ 'Found %d code style errors / warnings:\n' % len(errors) + \
+ '\n'.join(errors)
diff --git a/henry_pkg/test/test_pep257.py b/henry_pkg/test/test_pep257.py
new file mode 100644
index 0000000..b234a38
--- /dev/null
+++ b/henry_pkg/test/test_pep257.py
@@ -0,0 +1,23 @@
+# Copyright 2015 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_pep257.main import main
+import pytest
+
+
+@pytest.mark.linter
+@pytest.mark.pep257
+def test_pep257():
+ rc = main(argv=['.', 'test'])
+ assert rc == 0, 'Found code style errors / warnings'
diff --git a/install/.colcon_install_layout b/install/.colcon_install_layout
new file mode 100644
index 0000000..3aad533
--- /dev/null
+++ b/install/.colcon_install_layout
@@ -0,0 +1 @@
+isolated
diff --git a/install/COLCON_IGNORE b/install/COLCON_IGNORE
new file mode 100644
index 0000000..e69de29
diff --git a/install/_local_setup_util_ps1.py b/install/_local_setup_util_ps1.py
new file mode 100644
index 0000000..98348ee
--- /dev/null
+++ b/install/_local_setup_util_ps1.py
@@ -0,0 +1,404 @@
+# 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}"'
+FORMAT_STR_REMOVE_LEADING_SEPARATOR = ''
+FORMAT_STR_REMOVE_TRAILING_SEPARATOR = ''
+
+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
+ 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/install/_local_setup_util_sh.py b/install/_local_setup_util_sh.py
new file mode 100644
index 0000000..35c017b
--- /dev/null
+++ b/install/_local_setup_util_sh.py
@@ -0,0 +1,404 @@
+# 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}"'
+FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi'
+FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi'
+
+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
+ 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/install/henry_pkg/share/ament_index/resource_index/packages/henry_pkg b/install/henry_pkg/share/ament_index/resource_index/packages/henry_pkg
new file mode 100644
index 0000000..e69de29
diff --git a/install/henry_pkg/share/henry_pkg/hook/ament_prefix_path.dsv b/install/henry_pkg/share/henry_pkg/hook/ament_prefix_path.dsv
new file mode 100644
index 0000000..79d4c95
--- /dev/null
+++ b/install/henry_pkg/share/henry_pkg/hook/ament_prefix_path.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;AMENT_PREFIX_PATH;
diff --git a/install/henry_pkg/share/henry_pkg/hook/ament_prefix_path.ps1 b/install/henry_pkg/share/henry_pkg/hook/ament_prefix_path.ps1
new file mode 100644
index 0000000..26b9997
--- /dev/null
+++ b/install/henry_pkg/share/henry_pkg/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/install/henry_pkg/share/henry_pkg/hook/ament_prefix_path.sh b/install/henry_pkg/share/henry_pkg/hook/ament_prefix_path.sh
new file mode 100644
index 0000000..f3041f6
--- /dev/null
+++ b/install/henry_pkg/share/henry_pkg/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/install/henry_pkg/share/henry_pkg/package.xml b/install/henry_pkg/share/henry_pkg/package.xml
new file mode 100644
index 0000000..abad098
--- /dev/null
+++ b/install/henry_pkg/share/henry_pkg/package.xml
@@ -0,0 +1,30 @@
+
+
+
+ henry_pkg
+ 0.0.0
+ TODO: Package description
+ roncanciovl
+ Apache License 2.0
+
+ rclpy
+ std_msgs
+ sensor_msgs
+ example_interfaces
+
+ rosidl_default_generators
+ rosidl_default_runtime
+ rosidl_interface_packages
+
+
+
+ ament_copyright
+
+ ament_flake8
+ ament_pep257
+ python3-pytest
+
+
+ ament_python
+
+
diff --git a/install/local_setup.bash b/install/local_setup.bash
new file mode 100644
index 0000000..efd5f8c
--- /dev/null
+++ b/install/local_setup.bash
@@ -0,0 +1,107 @@
+# 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"
+ # 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_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 "Execute generated script:"
+ echo "<<<"
+ echo "${_colcon_ordered_commands}"
+ echo ">>>"
+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/install/local_setup.ps1 b/install/local_setup.ps1
new file mode 100644
index 0000000..6f68c8d
--- /dev/null
+++ b/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/install/local_setup.sh b/install/local_setup.sh
new file mode 100644
index 0000000..1a672e4
--- /dev/null
+++ b/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/willy/class_ws/src/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/install/local_setup.zsh b/install/local_setup.zsh
new file mode 100644
index 0000000..f7a8d90
--- /dev/null
+++ b/install/local_setup.zsh
@@ -0,0 +1,120 @@
+# 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"
+ # 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
+ continue
+ fi
+ # keep non-duplicate values
+ _all_values="$_all_values:$_item"
+ done
+ unset _item
+ # 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 "Execute generated script:"
+ echo "<<<"
+ echo "${_colcon_ordered_commands}"
+ echo ">>>"
+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/install/setup.bash b/install/setup.bash
new file mode 100644
index 0000000..b19cab0
--- /dev/null
+++ b/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/foxy"
+_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/install/setup.ps1 b/install/setup.ps1
new file mode 100644
index 0000000..412726f
--- /dev/null
+++ b/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/foxy\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/install/setup.sh b/install/setup.sh
new file mode 100644
index 0000000..13f5caf
--- /dev/null
+++ b/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/willy/class_ws/src/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/foxy"
+_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/install/setup.zsh b/install/setup.zsh
new file mode 100644
index 0000000..a98672a
--- /dev/null
+++ b/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/foxy"
+_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/install/willy_pkg/share/ament_index/resource_index/packages/willy_pkg b/install/willy_pkg/share/ament_index/resource_index/packages/willy_pkg
new file mode 100644
index 0000000..e69de29
diff --git a/install/willy_pkg/share/willy_pkg/hook/ament_prefix_path.dsv b/install/willy_pkg/share/willy_pkg/hook/ament_prefix_path.dsv
new file mode 100644
index 0000000..79d4c95
--- /dev/null
+++ b/install/willy_pkg/share/willy_pkg/hook/ament_prefix_path.dsv
@@ -0,0 +1 @@
+prepend-non-duplicate;AMENT_PREFIX_PATH;
diff --git a/install/willy_pkg/share/willy_pkg/hook/ament_prefix_path.ps1 b/install/willy_pkg/share/willy_pkg/hook/ament_prefix_path.ps1
new file mode 100644
index 0000000..26b9997
--- /dev/null
+++ b/install/willy_pkg/share/willy_pkg/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/install/willy_pkg/share/willy_pkg/hook/ament_prefix_path.sh b/install/willy_pkg/share/willy_pkg/hook/ament_prefix_path.sh
new file mode 100644
index 0000000..f3041f6
--- /dev/null
+++ b/install/willy_pkg/share/willy_pkg/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/install/willy_pkg/share/willy_pkg/package.xml b/install/willy_pkg/share/willy_pkg/package.xml
new file mode 100644
index 0000000..642b823
--- /dev/null
+++ b/install/willy_pkg/share/willy_pkg/package.xml
@@ -0,0 +1,33 @@
+
+
+
+ willy_pkg
+ 0.0.0
+ TODO: Package description
+ willy
+ Apache License 2.0
+
+
+ cv_bridge
+ cv_bridge
+ image_transport
+ image_transport
+ sensor_msgs
+ sensor_msgs
+ OpenCV
+ OpenCV
+ rclpy
+ std_msgs
+ros2launch
+ ament_copyright
+ ament_flake8
+ ament_pep257
+ python3-pytest
+
+
+ ament_python
+
+
+
+
+
diff --git a/install/willy_pkg/share/willy_pkg/python_parameters_launch.py b/install/willy_pkg/share/willy_pkg/python_parameters_launch.py
new file mode 100644
index 0000000..7c0f66b
--- /dev/null
+++ b/install/willy_pkg/share/willy_pkg/python_parameters_launch.py
@@ -0,0 +1,16 @@
+from launch import LaunchDescription
+from launch_ros.actions import Node
+
+def generate_launch_description():
+ return LaunchDescription([
+ Node(
+ package='willy_pkg',
+ executable='lineal_speed',
+ name='Siuu',
+ output='screen',
+ emulate_tty=True,
+ parameters=[
+ {'Radio': 0.10}
+ ]
+ )
+ ])
\ No newline at end of file
diff --git a/log/COLCON_IGNORE b/log/COLCON_IGNORE
new file mode 100644
index 0000000..e69de29
diff --git a/log/latest b/log/latest
new file mode 120000
index 0000000..b57d247
--- /dev/null
+++ b/log/latest
@@ -0,0 +1 @@
+latest_build
\ No newline at end of file
diff --git a/log/latest_build b/log/latest_build
new file mode 120000
index 0000000..ea846f5
--- /dev/null
+++ b/log/latest_build
@@ -0,0 +1 @@
+build_2023-03-16_09-06-58
\ No newline at end of file
diff --git a/lolito_interfaces/CMakeLists.txt b/lolito_interfaces/CMakeLists.txt
new file mode 100644
index 0000000..aef6e8c
--- /dev/null
+++ b/lolito_interfaces/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 3.5)
+project(lolito_interfaces)
+
+# Default to C99
+if(NOT CMAKE_C_STANDARD)
+ set(CMAKE_C_STANDARD 99)
+endif()
+
+# Default to C++14
+if(NOT CMAKE_CXX_STANDARD)
+ set(CMAKE_CXX_STANDARD 14)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ add_compile_options(-Wall -Wextra -Wpedantic)
+endif()
+
+# find dependencies
+find_package(ament_cmake REQUIRED)
+find_package(sensor_msgs REQUIRED)
+find_package(rosidl_default_generators REQUIRED)
+
+rosidl_generate_interfaces(${PROJECT_NAME}
+ "srv/CaptureImage.srv"
+ DEPENDENCIES sensor_msgs # Add packages that above messages depend on, in this case geometry_msgs for Sphere.msg
+)
+# uncomment the following section in order to fill in
+# further dependencies manually.
+# find_package( REQUIRED)
+
+ament_export_dependencies(rosidl_default_runtime)
+
+if(BUILD_TESTING)
+ find_package(ament_lint_auto REQUIRED)
+ # the following line skips the linter which checks for copyrights
+ # uncomment the line when a copyright and license is not present in all source files
+ #set(ament_cmake_copyright_FOUND TRUE)
+ # the following line skips cpplint (only works in a git repo)
+ # uncomment the line when this package is not in a git repo
+ #set(ament_cmake_cpplint_FOUND TRUE)
+ ament_lint_auto_find_test_dependencies()
+endif()
+
+ament_package()
diff --git a/lolito_interfaces/package.xml b/lolito_interfaces/package.xml
new file mode 100644
index 0000000..d5e7244
--- /dev/null
+++ b/lolito_interfaces/package.xml
@@ -0,0 +1,26 @@
+
+
+
+ lolito_interfaces
+ 0.0.0
+ TODO: Package description
+ roncanciovl
+ TODO: License declaration
+ ament_cmake
+ sensor_msgs
+
+ rosidl_default_generators
+
+ rosidl_default_runtime
+
+ rosidl_interface_packages
+
+
+
+ ament_lint_auto
+ ament_lint_common
+
+
+ ament_cmake
+
+
diff --git a/lolito_interfaces/srv/CaptureImage.srv b/lolito_interfaces/srv/CaptureImage.srv
new file mode 100644
index 0000000..dee9850
--- /dev/null
+++ b/lolito_interfaces/srv/CaptureImage.srv
@@ -0,0 +1,3 @@
+bool req
+---
+sensor_msgs/Image image
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..a504033
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,76 @@
+action-tutorials-py==0.9.4
+ament-copyright==0.9.7
+ament-cppcheck==0.9.7
+ament-cpplint==0.9.7
+ament-flake8==0.9.7
+ament-index-python==1.1.0
+ament-lint==0.9.7
+ament-lint-cmake==0.9.7
+ament-package==0.9.5
+ament-pep257==0.9.7
+ament-uncrustify==0.9.7
+ament-xmllint==0.9.7
+demo-nodes-py==0.9.4
+domain-coordinator==0.9.2
+examples-rclpy-executors==0.9.4
+examples-rclpy-minimal-action-client==0.9.4
+examples-rclpy-minimal-action-server==0.9.4
+examples-rclpy-minimal-client==0.9.4
+examples-rclpy-minimal-publisher==0.9.4
+examples-rclpy-minimal-service==0.9.4
+examples-rclpy-minimal-subscriber==0.9.4
+henry-pkg==0.0.0
+launch==0.10.10
+launch-ros==0.11.7
+launch-testing==0.10.10
+launch-testing-ros==0.11.7
+launch-xml==0.10.10
+launch-yaml==0.10.10
+networkx==3.0
+numpy==1.24.2
+osrf-pycommon==0.1.11
+quality-of-service-demo-py==0.9.4
+ros2action==0.9.12
+ros2bag==0.3.9
+ros2cli==0.9.12
+ros2component==0.9.12
+ros2doctor==0.9.12
+ros2interface==0.9.12
+ros2launch==0.11.7
+ros2lifecycle==0.9.12
+ros2multicast==0.9.12
+ros2node==0.9.12
+ros2param==0.9.12
+ros2pkg==0.9.12
+ros2run==0.9.12
+ros2service==0.9.12
+ros2topic==0.9.12
+rosidl-runtime-py==0.9.1
+rpyutils==0.2.0
+rqt==1.1.2
+rqt-action==0.4.9
+rqt-console==1.1.2
+rqt-graph==1.1.3
+rqt-gui==1.1.2
+rqt-gui-py==1.1.2
+rqt-moveit==1.0.1
+rqt-msg==1.0.5
+rqt-plot==1.1.1
+rqt-publisher==1.3.0
+rqt-py-console==1.0.2
+rqt-reconfigure==1.0.8
+rqt-robot-dashboard==0.5.8
+rqt-robot-monitor==1.0.5
+rqt-robot-steering==1.0.0
+rqt-runtime-monitor==1.0.0
+rqt-service-caller==1.0.5
+rqt-shell==1.0.2
+rqt-srv==1.0.3
+rqt-tf-tree==1.0.2
+rqt-top==1.0.2
+rqt-topic==1.3.0
+scikit-fuzzy==0.4.2
+scipy==1.10.1
+sros2==0.9.5
+teleop-twist-keyboard==2.3.2
+topic-monitor==0.9.4
diff --git a/willy_pkg/launch/python_parameters_launch.py b/willy_pkg/launch/python_parameters_launch.py
new file mode 100644
index 0000000..7c0f66b
--- /dev/null
+++ b/willy_pkg/launch/python_parameters_launch.py
@@ -0,0 +1,16 @@
+from launch import LaunchDescription
+from launch_ros.actions import Node
+
+def generate_launch_description():
+ return LaunchDescription([
+ Node(
+ package='willy_pkg',
+ executable='lineal_speed',
+ name='Siuu',
+ output='screen',
+ emulate_tty=True,
+ parameters=[
+ {'Radio': 0.10}
+ ]
+ )
+ ])
\ No newline at end of file
diff --git a/willy_pkg/package.xml b/willy_pkg/package.xml
new file mode 100644
index 0000000..cc6c72f
--- /dev/null
+++ b/willy_pkg/package.xml
@@ -0,0 +1,35 @@
+
+
+
+ willy_pkg
+ 0.0.0
+ TODO: Package description
+ willy
+ Apache License 2.0
+
+
+ cv_bridge
+ cv_bridge
+ image_transport
+ image_transport
+ sensor_msgs
+ sensor_msgs
+ OpenCV
+ OpenCV
+ rclpy
+ std_msgs
+ros2launch
+ ament_copyright
+ ament_flake8
+ ament_pep257
+ python3-pytest
+
+ lolito_interfaces
+ sensor_msgs
+
+ ament_python
+
+
+
+
+
diff --git a/willy_pkg/resource/willy_pkg b/willy_pkg/resource/willy_pkg
new file mode 100644
index 0000000..e69de29
diff --git a/willy_pkg/setup.cfg b/willy_pkg/setup.cfg
new file mode 100644
index 0000000..bf24026
--- /dev/null
+++ b/willy_pkg/setup.cfg
@@ -0,0 +1,4 @@
+[develop]
+script-dir=$base/lib/willy_pkg
+[install]
+install-scripts=$base/lib/willy_pkg
diff --git a/willy_pkg/setup.py b/willy_pkg/setup.py
new file mode 100644
index 0000000..e08a3f3
--- /dev/null
+++ b/willy_pkg/setup.py
@@ -0,0 +1,33 @@
+from setuptools import setup
+import os
+from glob import glob
+
+package_name = 'willy_pkg'
+
+setup(
+ name=package_name,
+ version='0.0.0',
+ packages=[package_name],
+ data_files=[
+ (os.path.join('share', package_name), glob('launch/*launch.[pxy][yma]*')),
+ ('share/ament_index/resource_index/packages',
+ ['resource/' + package_name]),
+ ('share/' + package_name, ['package.xml']),
+ ],
+ install_requires=['setuptools'],
+ zip_safe=True,
+ maintainer='willy',
+ maintainer_email='wrojaszabala@gmail.com',
+ description='TODO: Package description',
+ license='Apache License 2.0',
+ tests_require=['pytest'],
+ entry_points={
+ 'console_scripts': [
+ 'talker = willy_pkg.publisher_member_function:main',
+ 'listener = willy_pkg.subscriber_member_function:main',
+ 'lineal_speed = willy_pkg.lineal_speed:main',
+ 'client = willy_pkg.Client_photo:main',
+ 'server = willy_pkg.Server_photo:main'
+ ],
+},
+)
\ No newline at end of file
diff --git a/willy_pkg/test/test_copyright.py b/willy_pkg/test/test_copyright.py
new file mode 100644
index 0000000..cc8ff03
--- /dev/null
+++ b/willy_pkg/test/test_copyright.py
@@ -0,0 +1,23 @@
+# Copyright 2015 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_copyright.main import main
+import pytest
+
+
+@pytest.mark.copyright
+@pytest.mark.linter
+def test_copyright():
+ rc = main(argv=['.', 'test'])
+ assert rc == 0, 'Found errors'
diff --git a/willy_pkg/test/test_flake8.py b/willy_pkg/test/test_flake8.py
new file mode 100644
index 0000000..27ee107
--- /dev/null
+++ b/willy_pkg/test/test_flake8.py
@@ -0,0 +1,25 @@
+# Copyright 2017 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_flake8.main import main_with_errors
+import pytest
+
+
+@pytest.mark.flake8
+@pytest.mark.linter
+def test_flake8():
+ rc, errors = main_with_errors(argv=[])
+ assert rc == 0, \
+ 'Found %d code style errors / warnings:\n' % len(errors) + \
+ '\n'.join(errors)
diff --git a/willy_pkg/test/test_pep257.py b/willy_pkg/test/test_pep257.py
new file mode 100644
index 0000000..b234a38
--- /dev/null
+++ b/willy_pkg/test/test_pep257.py
@@ -0,0 +1,23 @@
+# Copyright 2015 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ament_pep257.main import main
+import pytest
+
+
+@pytest.mark.linter
+@pytest.mark.pep257
+def test_pep257():
+ rc = main(argv=['.', 'test'])
+ assert rc == 0, 'Found code style errors / warnings'
diff --git a/willy_pkg/willy_pkg/Client_photo.py b/willy_pkg/willy_pkg/Client_photo.py
new file mode 100644
index 0000000..7f04ed9
--- /dev/null
+++ b/willy_pkg/willy_pkg/Client_photo.py
@@ -0,0 +1,51 @@
+#Create a node client to send a message and visualize the image reception
+# Path: src/willy_pkg/willy_pkg/probar.py
+# Compare this snippet from src/willy_pkg/willy_pkg/foto_cliente.py:
+
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Image
+from lolito_interfaces.srv import CaptureImage
+
+class ImageCaptureClient(Node):
+ def __init__(self):
+ super().__init__('willy_cliente')
+ self.client = self.create_client(CaptureImage, 'capture_image')
+ while not self.client.wait_for_service(timeout_sec=1.0):
+ self.get_logger().info('Waiting for the capture_image service...')
+ self.req = CaptureImage.Request()
+
+ def send_request(self):
+ self.future = self.client.call_async(self.req)
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ node = ImageCaptureClient()
+
+ node.send_request()
+
+ while rclpy.ok():
+ rclpy.spin_once(node)
+ if node.future.done():
+ try:
+ response = node.future.result()
+ except Exception as e:
+ node.get_logger().info(
+ 'Service call failed %r' % (e,))
+ else:
+ node.get_logger().info('Received image')
+ # Visualizamos la imagen recibida
+ import cv2
+ import numpy as np
+ frame = np.frombuffer(response.image.data, dtype=np.uint8).reshape(response.image.height, response.image.width, -1)
+ cv2.imshow('Image', frame)
+ cv2.waitKey(0)
+ cv2.destroyAllWindows()
+ break
+
+ node.destroy_node()
+ rclpy.shutdown()
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/willy_pkg/willy_pkg/Server_photo.py b/willy_pkg/willy_pkg/Server_photo.py
new file mode 100644
index 0000000..c4580da
--- /dev/null
+++ b/willy_pkg/willy_pkg/Server_photo.py
@@ -0,0 +1,58 @@
+#Create a node server to receive a message and capture photo and send to client
+# Path: src/willy_pkg/willy_pkg/probar.py
+# Compare this snippet from src/willy_pkg/willy_pkg/foto_servidor.py:
+
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Image
+from lolito_interfaces.srv import CaptureImage
+
+class ImageCaptureServer(Node):
+ def __init__(self):
+ super().__init__('willy_server')
+ self.srv = self.create_service(CaptureImage, 'capture_image', self.capture_image_callback)
+
+ def capture_image_callback(self, request, response):
+ # Aquí es donde capturamos la imagen y la enviamos como respuesta
+ image = self.capture_image()
+ response.image = image
+ return response
+
+ def capture_image(self):
+ # En este ejemplo, utilizamos la biblioteca OpenCV para capturar la imagen
+ import cv2
+
+ # Capturamos la imagen de la cámara web
+ cap = cv2.VideoCapture(0)
+ _, frame = cap.read()
+
+ # Convertimos la imagen capturada a un mensaje ROS
+ msg = Image()
+ msg.header.frame_id = 'camera'
+ msg.encoding = 'bgr8'
+ msg.height, msg.width, _ = frame.shape
+ msg.step = 3 * msg.width
+ msg.data = frame.tobytes()
+
+ # Liberamos la cámara web
+ cap.release()
+
+ return msg
+
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ node = ImageCaptureServer()
+
+ try:
+ rclpy.spin(node)
+ except KeyboardInterrupt:
+ pass
+
+ node.destroy_node()
+ rclpy.shutdown()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/willy_pkg/willy_pkg/__init__.py b/willy_pkg/willy_pkg/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/willy_pkg/willy_pkg/foto_cliente.py b/willy_pkg/willy_pkg/foto_cliente.py
new file mode 100644
index 0000000..cea0911
--- /dev/null
+++ b/willy_pkg/willy_pkg/foto_cliente.py
@@ -0,0 +1,55 @@
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Image
+from lolito_interfaces.srv import CaptureImage
+
+
+class ImageCaptureServer(Node):
+ def __init__(self):
+ super().__init__('willy_envia')
+ self.srv = self.create_service(CaptureImage, 'capture_image', self.capture_image_callback)
+
+ def capture_image_callback(self, request, response):
+ # Aquí es donde capturamos la imagen y la enviamos como respuesta
+ image = self.capture_image()
+ response.image = image
+ return response
+
+ def capture_image(self):
+ # En este ejemplo, utilizamos la biblioteca OpenCV para capturar la imagen
+ import cv2
+
+ # Capturamos la imagen de la cámara web
+ cap = cv2.VideoCapture(0)
+ _, frame = cap.read()
+
+ # Convertimos la imagen capturada a un mensaje ROS
+ msg = Image()
+ msg.header.frame_id = 'camera'
+ msg.encoding = 'bgr8'
+ msg.height, msg.width, _ = frame.shape
+ msg.step = 3 * msg.width
+ msg.data = frame.tobytes()
+
+ # Liberamos la cámara web
+ cap.release()
+
+ return msg
+
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ node = ImageCaptureServer()
+
+ try:
+ rclpy.spin(node)
+ except KeyboardInterrupt:
+ pass
+
+ node.destroy_node()
+ rclpy.shutdown()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/willy_pkg/willy_pkg/jh.jpg b/willy_pkg/willy_pkg/jh.jpg
new file mode 100644
index 0000000..8c76a20
Binary files /dev/null and b/willy_pkg/willy_pkg/jh.jpg differ
diff --git a/willy_pkg/willy_pkg/lineal_speed.py b/willy_pkg/willy_pkg/lineal_speed.py
new file mode 100644
index 0000000..bc27755
--- /dev/null
+++ b/willy_pkg/willy_pkg/lineal_speed.py
@@ -0,0 +1,39 @@
+import rclpy
+from rclpy.node import Node
+from std_msgs.msg import String
+
+class MyNode(Node):
+
+ def __init__(self):
+ super().__init__('willypoder')
+ self.declare_parameter('Radio', 0.10)
+ sub_topic = self.get_parameter('Radio').value
+ self.publisher_ = self.create_publisher(String, 'lineal_speed', 10)
+ self.subscription = self.create_subscription(
+ String,
+ 'RPM',
+ self.listener_callback,
+ 10)
+ self.subscription # prevent unused variable warning
+
+ def listener_callback(self, msg):
+ #self.get_logger().info('I heard: "%s"' % msg.data)
+ Radio = self.get_parameter('Radio').value
+
+ numin=(float(msg.data)/60)*2*3.141516*Radio
+ print(numin)
+ msg.data=str(numin)
+ self.publisher_.publish(msg)
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ my_node = MyNode()
+
+ rclpy.spin(my_node)
+
+ my_node.destroy_node()
+ rclpy.shutdown()
+
+if __name__ == '__main__':
+ main()
diff --git a/willy_pkg/willy_pkg/publisher_member_function.py b/willy_pkg/willy_pkg/publisher_member_function.py
new file mode 100644
index 0000000..71d3586
--- /dev/null
+++ b/willy_pkg/willy_pkg/publisher_member_function.py
@@ -0,0 +1,41 @@
+#!usr/bin/env python 3
+
+import rclpy
+from rclpy.node import Node
+
+from std_msgs.msg import String
+
+
+class MinimalPublisher(Node):
+
+ def __init__(self):
+ super().__init__('minimal_publisher')
+ self.publisher_ = self.create_publisher(String, 'topic', 10)
+ timer_period = 0.5 # seconds
+ self.timer = self.create_timer(timer_period, self.timer_callback)
+ self.i = 0
+
+ def timer_callback(self):
+ msg = String()
+ msg.data = 'Hola blesssssssss %d' % self.i
+ self.publisher_.publish(msg)
+ self.get_logger().info('Publishing: "%s"' % msg.data)
+ self.i += 1
+
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ minimal_publisher = MinimalPublisher()
+
+ rclpy.spin(minimal_publisher)
+
+ # Destroy the node explicitly
+ # (optional - otherwise it will be done automatically
+ # when the garbage collector destroys the node object)
+ minimal_publisher.destroy_node()
+ rclpy.shutdown()
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/willy_pkg/willy_pkg/subscriber_member_function.py b/willy_pkg/willy_pkg/subscriber_member_function.py
new file mode 100644
index 0000000..f2241ef
--- /dev/null
+++ b/willy_pkg/willy_pkg/subscriber_member_function.py
@@ -0,0 +1,41 @@
+#!usr/bin/env python 3
+import rclpy
+from rclpy.node import Node
+import math
+
+from std_msgs.msg import String
+
+
+class MinimalSubscriber(Node):
+
+ def __init__(self):
+ super().__init__('lineal_speed')
+ self.subscription = self.create_subscription(
+ String,
+ 'topic',
+ self.listener_callback,
+ 10)
+ self.subscription # prevent unused variable warning
+
+ def listener_callback(self, msg):
+ self.get_logger().info('I heard: "%s"' % msg.data)
+
+
+
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ minimal_subscriber = MinimalSubscriber()
+
+ rclpy.spin(minimal_subscriber)
+
+ # Destroy the node explicitly
+ # (optional - otherwise it will be done automatically
+ # when the garbage collector destroys the node object)
+ minimal_subscriber.destroy_node()
+ rclpy.shutdown()
+
+
+if __name__ == '__main__':
+ main()
\ No newline at end of file
diff --git a/willy_pkg/willy_pkg/subscriber_photo.py b/willy_pkg/willy_pkg/subscriber_photo.py
new file mode 100644
index 0000000..cfd482f
--- /dev/null
+++ b/willy_pkg/willy_pkg/subscriber_photo.py
@@ -0,0 +1,55 @@
+import rclpy
+from rclpy.node import Node
+from sensor_msgs.msg import Image
+from lolito_interfaces.srv import CaptureImage
+
+
+class ImageCaptureServer(Node):
+ def __init__(self):
+ super().__init__('image_capture_server')
+ self.srv = self.create_service(CaptureImage, 'capture_image', self.capture_image_callback)
+
+ def capture_image_callback(self, request, response):
+ # Aquí es donde capturamos la imagen y la enviamos como respuesta
+ image = self.capture_image()
+ response.image = image
+ return response
+
+ def capture_image(self):
+ # En este ejemplo, utilizamos la biblioteca OpenCV para capturar la imagen
+ import cv2
+
+ # Capturamos la imagen de la cámara web
+ cap = cv2.VideoCapture(0)
+ _, frame = cap.read()
+
+ # Convertimos la imagen capturada a un mensaje ROS
+ msg = Image()
+ msg.header.frame_id = 'camera'
+ msg.encoding = 'bgr8'
+ msg.height, msg.width, _ = frame.shape
+ msg.step = 3 * msg.width
+ msg.data = frame.tobytes()
+
+ # Liberamos la cámara web
+ cap.release()
+
+ return msg
+
+
+def main(args=None):
+ rclpy.init(args=args)
+
+ node = ImageCaptureServer()
+
+ try:
+ rclpy.spin(node)
+ except KeyboardInterrupt:
+ pass
+
+ node.destroy_node()
+ rclpy.shutdown()
+
+
+if __name__ == '__main__':
+ main()