diff --git a/.gitignore b/.gitignore index 6195899..d5e242f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ build*/ *.pyo .ssh +artifacts/ downloads/ sstate-cache/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3fc3836 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,98 @@ +# This dockerfile allows you to build an environment for cross-compiling packages for the Jetson. +# It is based on the SDK generated by yocto. +# To be able to build this dockerfile, you have to run `bitbake mr-nadir-image -c populate_sdk` +# in a yocto environment. This will generate a .sh file in build/tmp/deploy/sdk/ which then +# can be used to build this dockerfile. +# +# THere are several fixes needed to make this work, for example the paths in some cmake files +# need to be fixed. This is done in the dockerfile. +# Additional yocto packages are added to the image in mr-nadir-image.bb (see meta-nadir/recipes-core/images/mr-nadir-image.bb) +# And there is a nadir-image-sdk-support package which adds some additional scripts to the SDK. +# +# To build: +# $ docker build . -t yocto-ros-cross-sdk:latest +# +# To run: +# $ docker run -it --rm -v $(pwd):/workdir yocto-ros-cross-sdk:latest +# +# Whre $(pwd) is the path to the root of the nadir-os repo. +# You can also pass a command to the docker run command. There is a script in the PATH called cross-build which +# allows you to build a single package. For example: +# $ docker run -it --rm -v $(pwd):/workdir yocto-ros-cross-sdk:latest cross-build nadir_commander + + + +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt update && \ + apt install -y \ + python3 \ + xz-utils \ + perl \ + findutils \ + file \ + vim \ + nano \ + git \ + less \ + sudo \ + wget \ + curl \ + \ + && \ + rm -rf /var/lib/apt/lists/* + + +# Copy the SDK +RUN mkdir -p /work/sdk +ARG CURRENT_DIR="." +COPY artifacts/tmp/deploy/sdk/ /work/sdk + +# Install the SDK +RUN sh /work/sdk/*-toolchain*.sh \ + -y -d /opt/sdk && \ + rm -rf /opt/sdk/sysroots/*-linux/usr/lib/openssl/ptest/test && \ + rm /work -rf + +# Fix paths in some cmake files +RUN cd /opt/sdk \ + echo "#!/bin/bash" > /tmp/fix_paths.sh && \ + echo "set -x" >> /tmp/fix_paths.sh && \ + echo ". /opt/sdk/environment-setup-*-linux*" >> /tmp/fix_paths.sh && \ + echo 'grep -rl "FIXMESTAGINGDIRHOST" /opt/sdk | xargs sed -i "s#FIXMESTAGINGDIRHOST#${OECORE_NATIVE_SYSROOT}#g"' >> /tmp/fix_paths.sh && \ + echo 'grep -rl "/usr/lib/libpython3.10.so" /opt/sdk | xargs sed -i "s#/.*/.*-linux.*/.*/recipe-sysroot/usr/lib/libpython3.10.so#${SDKTARGETSYSROOT}/usr/lib/libpython3.10.so#g"' >> /tmp/fix_paths.sh && \ + echo "set +x" >> /tmp/fix_paths.sh && \ + chmod +x /tmp/fix_paths.sh && \ + /tmp/fix_paths.sh && \ + rm /tmp/fix_paths.sh + + +# create entrypoint and cross-build script +RUN echo "#!/bin/bash" > /entrypoint.sh && \ + echo "source /opt/sdk/environment-setup-*-linux*" >> /entrypoint.sh && \ + echo "if [ -z \"\$1\" ]" >> /entrypoint.sh && \ + echo "then" >> /entrypoint.sh && \ + echo " . /opt/sdk/sysroots/x86_64-oesdk-linux/etc/profile.d/ros.sh" >> /entrypoint.sh && \ + echo " echo \"Welcome to the SDK build environment, you now can run colcon like normal.\"" >> /entrypoint.sh && \ + echo " echo \"We already called '. /opt/sdk/sysroots/x86_64-oesdk-linux/etc/profile.d/ros.sh' for you.\"" >> /entrypoint.sh && \ + echo " echo \"\"" >> /entrypoint.sh && \ + echo " exec bash" >> /entrypoint.sh && \ + echo " exit 0" >> /entrypoint.sh && \ + echo "fi" >> /entrypoint.sh && \ + echo "exec \"\$@\"" >> /entrypoint.sh && \ + chmod +x /entrypoint.sh + +# add user sdkbuild +RUN useradd -ms /bin/bash sdkbuild +# allow sudo without password +RUN echo "sdkbuild ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# RUN . /opt/sdk/environment-setup-*-linux && \ +# python3 -m ensurepip --upgrade && \ +# python3 -m pip install vcstool + +USER sdkbuild + +WORKDIR /workdir +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..3526fb3 --- /dev/null +++ b/Readme.md @@ -0,0 +1,54 @@ +# ROS2 SDK Demo Image + +This is an example of yocto ROS2 with a setup that can create an SDK for cross compilation. +It has been developed/tested with `MACHINE=raspberry4` but should be easy to adapt. + +## Building an SDK + +You will need build environment that is [setup to build yocto](https://docs.yoctoproject.org/4.0.13/brief-yoctoprojectqs/index.html#compatible-linux-distribution). +See below for an example using docker. + + git clone + cd yocto-ros2-sdk-demo + git submodule update --init + . ./layers/oe-init-build-env build + +Now you have a `build` directory, ready to go. +This is based on the `raspberry4` machine. + +## To build the sdk: + + bitbake ros2-demo-image -c do_populate_sdk + +The SDK install files are then available in `/artifacts/tmp/deploy/sdk/`. +This path is important, as the Dockerfile to create a build image is dependend on it. + +## Build a Docker image + + ./scripts/create-sdk-docker-latest.sh + +This will create a docker iamge named `yocto-ros-cross-sdk:latest`. + +## Run the build container: + + ./scripts/start-build-container.sh . + +This will start the build container with the SDK setup. +The parameter passed to the script `.` is the path that should be made available to `/workdir`. +This path can be outside the current directory. + +## Build the action_tutorials_cpp + +Inside the build container: + + cd /workdir/playground + colcon build + + +## Get your disk space back: + + rm -rf artifacts/tmp + +Get all your disk space back: + + rm -rf artifacts/* diff --git a/layers/.templateconf b/layers/.templateconf new file mode 100644 index 0000000..52527d7 --- /dev/null +++ b/layers/.templateconf @@ -0,0 +1,3 @@ +# This file is required by oe-setup-buildenv script +# but not used in this repository +TEMPLATECONF=${TEMPLATECONF:-meta-ros2-demo-image/conf/template-ros2-demo} \ No newline at end of file diff --git a/layers/meta-filesystems b/layers/meta-filesystems new file mode 120000 index 0000000..31b79db --- /dev/null +++ b/layers/meta-filesystems @@ -0,0 +1 @@ +../repos/meta-openembedded/meta-filesystems \ No newline at end of file diff --git a/layers/meta-networking b/layers/meta-networking new file mode 120000 index 0000000..9c86a7d --- /dev/null +++ b/layers/meta-networking @@ -0,0 +1 @@ +../repos/meta-openembedded/meta-networking \ No newline at end of file diff --git a/layers/meta-oe b/layers/meta-oe new file mode 120000 index 0000000..8cccc3e --- /dev/null +++ b/layers/meta-oe @@ -0,0 +1 @@ +../repos/meta-openembedded/meta-oe \ No newline at end of file diff --git a/layers/meta-poky b/layers/meta-poky new file mode 120000 index 0000000..e9781bf --- /dev/null +++ b/layers/meta-poky @@ -0,0 +1 @@ +../repos/poky/meta-poky \ No newline at end of file diff --git a/layers/meta-python b/layers/meta-python new file mode 120000 index 0000000..56a1dac --- /dev/null +++ b/layers/meta-python @@ -0,0 +1 @@ +../repos/meta-openembedded/meta-python \ No newline at end of file diff --git a/layers/meta-raspberypi b/layers/meta-raspberypi new file mode 120000 index 0000000..df8a48f --- /dev/null +++ b/layers/meta-raspberypi @@ -0,0 +1 @@ +../repos/meta-raspberypi \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/.templateconf b/layers/meta-ros2-demo-image/.templateconf new file mode 100644 index 0000000..23f8dbf --- /dev/null +++ b/layers/meta-ros2-demo-image/.templateconf @@ -0,0 +1 @@ +TEMPLATECONF=${TEMPLATECONF:-meta-mr-core/conf/template-$DISTRO} diff --git a/layers/meta-ros2-demo-image/conf/distro/mr-core._ b/layers/meta-ros2-demo-image/conf/distro/mr-core._ new file mode 100644 index 0000000..71ccaed --- /dev/null +++ b/layers/meta-ros2-demo-image/conf/distro/mr-core._ @@ -0,0 +1,67 @@ +DISTRO = "mr-core" +DISTRO_NAME = "Mission Robotics Core OE4Tegra Distro" +DISTRO_VERSION_BASE = "1.0.3" +DISTRO_VERSION = "${DISTRO_VERSION_BASE}+snapshot-${DATE}" +DISTRO_CODENAME = "kirkstone-l4t-r32.7" +SDK_VENDOR = "-tdsdk" +SDK_VERSION := "${@'${DISTRO_VERSION}'.replace('snapshot-${METADATA_REVISION}','snapshot')}" +SDK_VERSION[vardepvalue] = "${SDK_VERSION}" + +MAINTAINER = "OE4Tegra team " + +TARGET_VENDOR = "-oe4t" + +# New ${DISTRO}- setting for sanity checks. +# Increment version number (and the corresponding +# setting int the template bblayers.conf.sample file) +# each time the layer settings are changed. +REQUIRED_TD_BBLAYERS_CONF_VERSION = "${DISTRO}-7" + +LOCALCONF_VERSION = "2" + +TD_DEFAULT_DISTRO_FEATURES = "largefile opengl ptest multiarch wayland vulkan systemd pam virtualization" + +DISTRO_FEATURES ?= "${DISTRO_FEATURES_DEFAULT} ${TD_DEFAULT_DISTRO_FEATURES}" + +# Jetson platforms do not use linux-yocto, but for QEMU testing +# align with the poky distro. +PREFERRED_VERSION_linux-yocto ?= "5.15%" +PREFERRED_VERSION_linux-yocto-rt ?= "5.15%" + +# Gstreamer libraries are passed through to containers when using +# nvidia-docker, so our version of Gstreamer must match the one in +# the stock L4T/JetPack release. +require conf/include/gstreamer-1.14.conf + +SDK_NAME = "${DISTRO}-${TCLIBC}-${SDKMACHINE}-${IMAGE_BASENAME}-${TUNE_PKGARCH}-${MACHINE}" +SDKPATHINSTALL = "/opt/${DISTRO}/${SDK_VERSION}" + +TCLIBCAPPEND = "" + +PACKAGE_CLASSES ?= "package_rpm" + +SANITY_TESTED_DISTROS ?= " \ + ubuntu-18.04 \n \ + ubuntu-20.04 \n \ + ubuntu-22.04 \n \ + " + +# CUDA 10.2 requires gcc 8 +CUDA_GCCVERSION = "8.%" + +# Most NVIDIA-supplied services expect systemd +INIT_MANAGER = "systemd" + +INHERIT += "tegra-support-sanity" +ESDK_CLASS_INHERIT_DISABLE:append = " tegra-support-sanity" + +require conf/distro/include/no-static-libs.inc +require conf/distro/include/yocto-uninative.inc +require conf/distro/include/security_flags.inc +INHERIT += "uninative" + +BB_SIGNATURE_HANDLER ?= "OEEquivHash" +BB_HASHSERVE ??= "auto" + +LICENSE_FLAGS_ACCEPTED += "commercial_faad2" + diff --git a/layers/meta-ros2-demo-image/conf/layer.conf b/layers/meta-ros2-demo-image/conf/layer.conf new file mode 100644 index 0000000..d582ea6 --- /dev/null +++ b/layers/meta-ros2-demo-image/conf/layer.conf @@ -0,0 +1,23 @@ +# We have a conf and classes directory, append to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have a recipes directory, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb ${LAYERDIR}/recipes-*/*/*.bbappend ${LAYERDIR}/generated-recipes/*/*.bb" + +BBFILE_COLLECTIONS += "ros2-demo-iamge" +BBFILE_PATTERN_ros2-demo-iamge := "^${LAYERDIR}/" +BBFILE_PRIORITY_ros2-demo-iamge = "12" + +LAYERVERSION_ros2-demo-iamge = "1" + +LAYERDEPENDS_ros2-demo-iamge = " \ + core \ + meta-python \ + openembedded-layer \ + ros-common-layer \ + ros2-layer \ +" + +LAYERSERIES_COMPAT_ros2-demo-iamge = "${ROS_OE_RELEASE_SERIES}" + +require conf/ros-distro/include/iron/ros-distro.inc diff --git a/layers/meta-ros2-demo-image/conf/template-ros2-demo/bblayers.conf.sample b/layers/meta-ros2-demo-image/conf/template-ros2-demo/bblayers.conf.sample new file mode 100644 index 0000000..5e9a176 --- /dev/null +++ b/layers/meta-ros2-demo-image/conf/template-ros2-demo/bblayers.conf.sample @@ -0,0 +1,22 @@ +# Version of layers configuration, specific to +# each defined distro in the repository. +# Format: ${DISTRO}- +TD_BBLAYERS_CONF_VERSION = "mr-core-7" + +BBPATH = "${TOPDIR}" +BBFILES ?= "" + +BBLAYERS ?= " \ + ##OEROOT##/meta \ + ##OEROOT##/meta-poky \ + ##OEROOT##/meta-yocto-bsp \ + ##OEROOT##/meta-oe \ + ##OEROOT##/meta-python \ + ##OEROOT##/meta-networking \ + ##OEROOT##/meta-filesystems \ + ##OEROOT##/meta-raspberypi \ + ##OEROOT##/meta-ros-common \ + ##OEROOT##/meta-ros2 \ + ##OEROOT##/meta-ros2-iron \ + ##OEROOT##/meta-ros2-demo-image \ + " diff --git a/layers/meta-ros2-demo-image/conf/template-ros2-demo/conf-notes.txt b/layers/meta-ros2-demo-image/conf/template-ros2-demo/conf-notes.txt new file mode 100644 index 0000000..fa5a361 --- /dev/null +++ b/layers/meta-ros2-demo-image/conf/template-ros2-demo/conf-notes.txt @@ -0,0 +1,5 @@ +### Shell environment set up for builds. ### + +You can now run 'bitbake ' +Targets for building Mission Robotics Tegra images: + ros2-demo-image - basic image with no graphics diff --git a/layers/meta-ros2-demo-image/conf/template-ros2-demo/local.conf.sample b/layers/meta-ros2-demo-image/conf/template-ros2-demo/local.conf.sample new file mode 100644 index 0000000..b85cd95 --- /dev/null +++ b/layers/meta-ros2-demo-image/conf/template-ros2-demo/local.conf.sample @@ -0,0 +1,353 @@ +# +# This file is your local configuration file and is where all local user settings +# are placed. The comments in this file give some guide to the options a new user +# to the system might want to change but pretty much any configuration option can +# be set in this file. More adventurous users can look at +# local.conf.sample.extended which contains other examples of configuration which +# can be placed in this file but new users likely won't need any of them +# initially. +# +# Lines starting with the '#' character are commented out and in some cases the +# default values are provided as comments to show people example syntax. Enabling +# the option is a question of removing the # character and making any change to the +# variable as required. + +# +# Machine Selection +# +# You need to select a specific machine to target the build with. There are a selection +# of emulated machines available which can boot and run in the QEMU emulator: +# +#MACHINE ?= "qemuarm" +#MACHINE ?= "qemuarm64" +#MACHINE ?= "qemumips" +#MACHINE ?= "qemumips64" +#MACHINE ?= "qemuppc" +#MACHINE ?= "qemux86" +#MACHINE ?= "qemux86-64" +# +# There are also the following hardware board target machines included for +# demonstration purposes: +# +#MACHINE ?= "beaglebone-yocto" +#MACHINE ?= "genericx86" +#MACHINE ?= "genericx86-64" +#MACHINE ?= "edgerouter" +# +# This sets the default machine to be qemux86-64 if no other machine is selected: +MACHINE ??= "qemux86-64" + +# +# Where to place downloads +# +# During a first build the system will download many different source code tarballs +# from various upstream projects. This can take a while, particularly if your network +# connection is slow. These are all stored in DL_DIR. When wiping and rebuilding you +# can preserve this directory to speed up this part of subsequent builds. This directory +# is safe to share between multiple builds on the same machine too. +# +# The default is a downloads directory under TOPDIR which is the build directory. +# +# This is set further down in the ROS2-demo-image section +#DL_DIR ?= "${TOPDIR}/downloads" + +# +# Where to place shared-state files +# +# BitBake has the capability to accelerate builds based on previously built output. +# This is done using "shared state" files which can be thought of as cache objects +# and this option determines where those files are placed. +# +# You can wipe out TMPDIR leaving this directory intact and the build would regenerate +# from these files if no changes were made to the configuration. If changes were made +# to the configuration, only shared state files where the state was still valid would +# be used (done using checksums). +# +# The default is a sstate-cache directory under TOPDIR. +# +# This is set further down in the ROS2-demo-image section +#SSTATE_DIR ?= "${TOPDIR}/sstate-cache" + +# +# Where to place the build output +# +# This option specifies where the bulk of the building work should be done and +# where BitBake should place its temporary files and output. Keep in mind that +# this includes the extraction and compilation of many applications and the toolchain +# which can use Gigabytes of hard disk space. +# +# The default is a tmp directory under TOPDIR. +# +# This is set further down in the ROS2-demo-image section +#TMPDIR = "${TOPDIR}/tmp" + +# +# Default policy config +# +# The distribution setting controls which policy settings are used as defaults. +# The default value is fine for general Yocto project use, at least initially. +# Ultimately when creating custom policy, people will likely end up subclassing +# these defaults. +# +DISTRO ?= "poky" +# As an example of a subclass there is a "bleeding" edge policy configuration +# where many versions are set to the absolute latest code from the upstream +# source control systems. This is just mentioned here as an example, its not +# useful to most new users. +# DISTRO ?= "poky-bleeding" + +# +# Package Management configuration +# +# This variable lists which packaging formats to enable. Multiple package backends +# can be enabled at once and the first item listed in the variable will be used +# to generate the root filesystems. +# Options are: +# - 'package_deb' for debian style deb files +# - 'package_ipk' for ipk files are used by opkg (a debian style embedded package manager) +# - 'package_rpm' for rpm style packages +# E.g.: PACKAGE_CLASSES ?= "package_rpm package_deb package_ipk" +# We default to rpm: +PACKAGE_CLASSES ?= "package_rpm" + +# +# SDK target architecture +# +# This variable specifies the architecture to build SDK items for and means +# you can build the SDK packages for architectures other than the machine you are +# running the build on (i.e. building i686 packages on an x86_64 host). +# Supported values are i686, x86_64, aarch64 +#SDKMACHINE ?= "i686" + +# +# Extra image configuration defaults +# +# The EXTRA_IMAGE_FEATURES variable allows extra packages to be added to the generated +# images. Some of these options are added to certain image types automatically. The +# variable can contain the following options: +# "dbg-pkgs" - add -dbg packages for all installed packages +# (adds symbol information for debugging/profiling) +# "src-pkgs" - add -src packages for all installed packages +# (adds source code for debugging) +# "dev-pkgs" - add -dev packages for all installed packages +# (useful if you want to develop against libs in the image) +# "ptest-pkgs" - add -ptest packages for all ptest-enabled packages +# (useful if you want to run the package test suites) +# "tools-sdk" - add development tools (gcc, make, pkgconfig etc.) +# "tools-debug" - add debugging tools (gdb, strace) +# "eclipse-debug" - add Eclipse remote debugging support +# "tools-profile" - add profiling tools (oprofile, lttng, valgrind) +# "tools-testapps" - add useful testing tools (ts_print, aplay, arecord etc.) +# "debug-tweaks" - make an image suitable for development +# e.g. ssh root access has a blank password +# There are other application targets that can be used here too, see +# meta/classes/image.bbclass and meta/classes/core-image.bbclass for more details. +# We default to enabling the debugging tweaks. +EXTRA_IMAGE_FEATURES ?= "debug-tweaks" + +# +# Additional image features +# +# The following is a list of additional classes to use when building images which +# enable extra features. Some available options which can be included in this variable +# are: +# - 'buildstats' collect build statistics +USER_CLASSES ?= "buildstats" + +# +# Runtime testing of images +# +# The build system can test booting virtual machine images under qemu (an emulator) +# after any root filesystems are created and run tests against those images. It can also +# run tests against any SDK that are built. To enable this uncomment these lines. +# See classes/test{image,sdk}.bbclass for further details. +#IMAGE_CLASSES += "testimage testsdk" +#TESTIMAGE_AUTO:qemuall = "1" + +# +# Interactive shell configuration +# +# Under certain circumstances the system may need input from you and to do this it +# can launch an interactive shell. It needs to do this since the build is +# multithreaded and needs to be able to handle the case where more than one parallel +# process may require the user's attention. The default is iterate over the available +# terminal types to find one that works. +# +# Examples of the occasions this may happen are when resolving patches which cannot +# be applied, to use the devshell or the kernel menuconfig +# +# Supported values are auto, gnome, xfce, rxvt, screen, konsole (KDE 3.x only), none +# Note: currently, Konsole support only works for KDE 3.x due to the way +# newer Konsole versions behave +#OE_TERMINAL = "auto" +# By default disable interactive patch resolution (tasks will just fail instead): +PATCHRESOLVE = "noop" + +# +# Disk Space Monitoring during the build +# +# Monitor the disk space during the build. If there is less that 1GB of space or less +# than 100K inodes in any key build location (TMPDIR, DL_DIR, SSTATE_DIR), gracefully +# shutdown the build. If there is less than 100MB or 1K inodes, perform a hard halt +# of the build. The reason for this is that running completely out of space can corrupt +# files and damages the build in ways which may not be easily recoverable. +# It's necessary to monitor /tmp, if there is no space left the build will fail +# with very exotic errors. +BB_DISKMON_DIRS ??= "\ + STOPTASKS,${TMPDIR},1G,100K \ + STOPTASKS,${DL_DIR},1G,100K \ + STOPTASKS,${SSTATE_DIR},1G,100K \ + STOPTASKS,/tmp,100M,100K \ + HALT,${TMPDIR},100M,1K \ + HALT,${DL_DIR},100M,1K \ + HALT,${SSTATE_DIR},100M,1K \ + HALT,/tmp,10M,1K" + +# +# Shared-state files from other locations +# +# As mentioned above, shared state files are prebuilt cache data objects which can be +# used to accelerate build time. This variable can be used to configure the system +# to search other mirror locations for these objects before it builds the data itself. +# +# This can be a filesystem directory, or a remote url such as https or ftp. These +# would contain the sstate-cache results from previous builds (possibly from other +# machines). This variable works like fetcher MIRRORS/PREMIRRORS and points to the +# cache locations to check for the shared objects. +# NOTE: if the mirror uses the same structure as SSTATE_DIR, you need to add PATH +# at the end as shown in the examples below. This will be substituted with the +# correct path within the directory structure. +#SSTATE_MIRRORS ?= "\ +#file://.* https://someserver.tld/share/sstate/PATH;downloadfilename=PATH \ +#file://.* file:///some/local/dir/sstate/PATH" + +# +# Yocto Project SState Mirror +# +# The Yocto Project has prebuilt artefacts available for its releases, you can enable +# use of these by uncommenting the following lines. This will mean the build uses +# the network to check for artefacts at the start of builds, which does slow it down +# equally, it will also speed up the builds by not having to build things if they are +# present in the cache. It assumes you can download something faster than you can build it +# which will depend on your network. +# Note: For this to work you also need hash-equivalence passthrough to the matching server +# +#BB_HASHSERVE_UPSTREAM = "hashserv.yocto.io:8687" +#SSTATE_MIRRORS ?= "file://.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH" + +# +# Qemu configuration +# +# By default native qemu will build with a builtin VNC server where graphical output can be +# seen. The line below enables the SDL UI frontend too. +PACKAGECONFIG:append:pn-qemu-system-native = " sdl" +# By default libsdl2-native will be built, if you want to use your host's libSDL instead of +# the minimal libsdl built by libsdl2-native then uncomment the ASSUME_PROVIDED line below. +#ASSUME_PROVIDED += "libsdl2-native" + +# You can also enable the Gtk UI frontend, which takes somewhat longer to build, but adds +# a handy set of menus for controlling the emulator. +#PACKAGECONFIG:append:pn-qemu-system-native = " gtk+" + +# +# Hash Equivalence +# +# Enable support for automatically running a local hash equivalence server and +# instruct bitbake to use a hash equivalence aware signature generator. Hash +# equivalence improves reuse of sstate by detecting when a given sstate +# artifact can be reused as equivalent, even if the current task hash doesn't +# match the one that generated the artifact. +# +# A shared hash equivalent server can be set with ":" format +# +#BB_HASHSERVE = "auto" +#BB_SIGNATURE_HANDLER = "OEEquivHash" + +# +# Memory Resident Bitbake +# +# Bitbake's server component can stay in memory after the UI for the current command +# has completed. This means subsequent commands can run faster since there is no need +# for bitbake to reload cache files and so on. Number is in seconds, after which the +# server will shut down. +# +#BB_SERVER_TIMEOUT = "60" + +# CONF_VERSION is increased each time build/conf/ changes incompatibly and is used to +# track the version of this file when it was generated. This can safely be ignored if +# this doesn't mean anything to you. +CONF_VERSION = "2" + + +# -------------------- +# ROS2-demo-image +# +# ROS-ADDITIONS-BEGIN +# ^^^^^^^^^^^^^^^^^^^ + +# The major version is incremented whenever a change is made on the wiki page. Increment the minor version whenever you add or +# change a setting in this file. +ROS_LOCAL_CONF_SETTINGS_VERSION := "3.0" + +# +DISTRO ?= "ros2-iron" + +# The list of supported values of MACHINE is found in the Machines[] array in the .mcf file for the selected configuration. +# Use ?= so that a value set in the environment will override the one set here. +MACHINE ?= "raspberrypi4" +# MACHINE = "qemux86-64" + +ROS_DISTRO_VERSION_APPEND ?= "+$4.0.13" + +# These two are only used in the additions to conf/local.conf below: +ROS_OE_RELEASE_SERIES_SUFFIX ?= "-${ROS_OE_RELEASE_SERIES}" + + +# We store all the artifacts in ${TOPDIR}../artifacts +# Because of a bug in OpenEmbedded, can not be a symlink. +ARTIFACTS_DIR ?= "${@os.path.abspath('${TOPDIR}/../artifacts')}" + +# Set the directories where downloads, shared-state, and the output from the build are placed to be on the separate disk. +DL_DIR ?= "${ARTIFACTS_DIR}/downloads" +SSTATE_DIR ?= "${ARTIFACTS_DIR}/sstate-cache${ROS_OE_RELEASE_SERIES_SUFFIX}" +# TMPDIR is weakly assigned in conf/bitbake.conf before it includes conf/local.conf => must use '=' here: +TMPDIR = "${ARTIFACTS_DIR}/tmp" +# Don't add the libc variant suffix to TMPDIR. +TCLIBCAPPEND := "" + +# As recommended by https://www.yoctoproject.org/docs/latest/mega-manual/mega-manual.html#var-BB_NUMBER_THREADS +# and https://www.yoctoproject.org/docs/latest/mega-manual/mega-manual.html#var-PARALLEL_MAKE: +BB_NUMBER_THREADS ?= "${@min(int(bb.utils.cpu_count()), 20)}" +PARALLEL_MAKE ?= "-j ${BB_NUMBER_THREADS}" + +# Reduce the size of the build artifacts by removing the working files under TMPDIR/work. Comment this out to preserve them +# (see https://www.yoctoproject.org/docs/latest/mega-manual/mega-manual.html#ref-classes-rm-work). +INHERIT += "rm_work" + +DISTRO_FEATURES:append = " x11 opengl vulkan " + +# For ffmpeg +LICENSE_FLAGS_ACCEPTED = " commercial_ffmpeg commercial_x264 commercial " +LICENSE_FLAGS_ACCEPTED += "commercial_ffmpeg commercial_x264" + +# Any other additions to the file go here. + +# EXTRA_IMAGE_FEATURES is just one of the many settings that can be placed in this file. You can find them all by searching +# https://www.yoctoproject.org/docs/latest/mega-manual/mega-manual.html#ref-variables-glossary for "local.conf". + +# Uncomment to allow "root" to ssh into the device. Not needed for images with webOS OSE because it implicitly adds this +# feature. +# EXTRA_IMAGE_FEATURES += "ssh-server-dropbear" + +# Uncomment to include the package management utilities in the image ("opkg", by default). Not needed for images with +# webOS OSE because it implicitly adds this feature. +# EXTRA_IMAGE_FEATURES += "package-management" + +# Uncomment to have all interactive shells implicitly source "setup.sh" (ROS 1) or "ros_setup.sh" (ROS 2). +# EXTRA_IMAGE_FEATURES += "ros-implicit-workspace" + +# Uncomment to display additional useful variables in the build configuration output. +# require conf/distro/include/ros-useful-buildcfg-vars.inc + +# vvvvvvvvvvvvvvvvv +# ROS-ADDITIONS-END diff --git a/layers/meta-ros2-demo-image/recipes-ros2-demo/images/ros2-demo-image.bb b/layers/meta-ros2-demo-image/recipes-ros2-demo/images/ros2-demo-image.bb new file mode 100644 index 0000000..0d8835f --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-ros2-demo/images/ros2-demo-image.bb @@ -0,0 +1,126 @@ +DESCRIPTION = "Mission Robotics Nadir OS image" +LICENSE = "MIT" + +inherit core-image +inherit ros2_image +require ros2-demo.inc +inherit python3-dir + + +DEPENDS += " util-linux-native " + +# THis is probably a hack, but I don't know where to get /opt/sdk from +SDKNATIVE="/opt/sdk/sysroots/${SDK_SYS}" + +SDK_SUPPORT = " \ + nativesdk-ros2-demo-image-sdk-support \ +" + +# There are probably packages in these lists that aren't needed, feel free to use only what you need. +TOOLCHAIN_HOST_TASK:append = " \ + ${SDK_SUPPORT} \ + \ + nativesdk-make \ + nativesdk-cmake \ + nativesdk-ament-cppcheck \ + nativesdk-ament-cppcheck \ + nativesdk-ament-copyright \ + nativesdk-ament-uncrustify \ + nativesdk-ament-cpplint \ + nativesdk-ament-cmake \ + nativesdk-ament-flake8 \ + nativesdk-ament-pep257 \ + \ + nativesdk-python3-dateutil \ + nativesdk-python3-docutils \ + nativesdk-python3-numpy \ + nativesdk-python3-lark-parser \ + nativesdk-python3-jinja2 \ + nativesdk-python3-typeguard \ + nativesdk-python3-distlib \ + nativesdk-python3-colcon-common-extensions \ + \ + nativesdk-rosidl-generator-type-description \ + nativesdk-rosidl-parser \ + nativesdk-rosidl-adapter \ + nativesdk-rosidl-generator-cpp \ + nativesdk-rosidl-typesupport-c \ + nativesdk-rosidl-typesupport-cpp \ + nativesdk-rosidl-typesupport-fastrtps-c \ + nativesdk-rosidl-generator-py \ + nativesdk-rosidl-pycommon \ + nativesdk-rpyutils \ + nativesdk-libusb1 \ + nativesdk-libusb-compat \ + nativesdk-protobuf \ + nativesdk-protobuf-compiler \ + nativesdk-python3-lxml \ + nativesdk-rclpy \ + nativesdk-fastcdr \ + \ + nativesdk-ros2cli \ + nativesdk-ros2cli-common-extensions \ + nativesdk-ros-workspace \ + nativesdk-ros-workspace-implicitworkspace \ + \ +" + +TOOLCHAIN_TARGET_TASK:append = " \ + ament-cmake \ + foonathan-memory-staticdev \ + fastcdr \ + geographiclib-staticdev \ + geographiclib-tools \ + libusb1 \ + libusb-compat \ + nlohmann-json \ + python3-numpy \ + python3-future \ + diagnostic-msgs \ + sensor-msgs \ + nav-msgs \ + action-tutorials-interfaces \ + rclcpp-action \ + ${TOOLCHAIN_AMENT_PACKAGES} \ +" + +TOOLCHAIN_AMENT_PACKAGES = "\ + ament-package \ + ament-lint \ + ament-lint-auto \ + ament-cmake \ + ament-cmake-auto \ + ament-cmake-catch2 \ + ament-cmake-copyright \ + ament-cmake-core \ + ament-cmake-cppcheck \ + ament-cmake-cpplint \ + ament-cmake-export-definitions \ + ament-cmake-export-dependencies \ + ament-cmake-export-include-directories \ + ament-cmake-export-interfaces \ + ament-cmake-export-libraries \ + ament-cmake-export-link-flags \ + ament-cmake-export-targets \ + ament-cmake-flake8 \ + ament-cmake-gen-version-h \ + ament-cmake-gmock \ + ament-cmake-google-benchmark \ + ament-cmake-gtest \ + ament-cmake-include-directories \ + ament-cmake-libraries \ + ament-cmake-lint-cmake \ + ament-cmake-mypy \ + ament-cmake-pclint \ + ament-cmake-pep257 \ + ament-cmake-pycodestyle \ + ament-cmake-pyflakes \ + ament-cmake-pytest \ + ament-cmake-python \ + ament-cmake-ros \ + ament-cmake-target-dependencies \ + ament-cmake-test \ + ament-cmake-uncrustify \ + ament-cmake-version \ + ament-cmake-xmllint \ +" \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-ros2-demo/images/ros2-demo.inc b/layers/meta-ros2-demo-image/recipes-ros2-demo/images/ros2-demo.inc new file mode 100644 index 0000000..91d6446 --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-ros2-demo/images/ros2-demo.inc @@ -0,0 +1,169 @@ +inherit ros_distro_${ROS_DISTRO} +inherit ${ROS_DISTRO_TYPE}_image + +ROS_WORLD_SKIP_GROUPS:append = " \ + connext \ +" +SKIP_RECIPE[rmw-connextdds-common] = "Not supported on ${TARGET_ARCH}" + +# TOOLCHAIN_HOST_TASK:append = " nativesdk-packagegroup-cuda-sdk-host" + +IMAGE_INSTALL:append = " \ + ros-base \ + python3-fcntl \ + \ + fastcdr \ + fastrtps-cmake-module \ + fastrtps \ + \ + rosidl-parser \ + rosidl-runtime-c \ + rosidl-runtime-cpp \ + \ + ros2cli \ + python3-packaging \ + python3-logging \ + ros2run \ + ros2topic \ + ros2service \ + ros2param \ + ros2action \ + ros2lifecycle \ + ros2component \ + ros2node \ + ros2launch \ + ros2multicast \ + rclpy \ + rpyutils \ + ros2pkg \ + ament-index-python \ + launch \ + launch-ros \ + python3 \ + python3-lark-parser \ + python3-numpy \ + rosidl-runtime-py \ + osrf-pycommon \ + \ + demo-nodes-cpp \ + demo-nodes-cpp-rosnative \ + demo-nodes-py \ +" + + +X_ROS_SYSROOT_BUILD_DEPENDENCIES:append = " \ + fastcdr \ + fastrtps-cmake-module \ + fastrtps \ + git \ + gmock-vendor \ + gtest-vendor \ + pkgconfig \ + python-cmake-module \ + python3-catkin-pkg \ + python3-empy \ + python3 \ + python3-nose \ + python3-pytest \ + rcutils \ + rmw-implementation-cmake \ + ament-lint-auto \ + ament-cmake-auto \ + ament-cmake-core \ + ament-cmake-cppcheck \ + ament-cmake-cpplint \ + ament-cmake-export-definitions \ + ament-cmake-export-dependencies \ + ament-cmake-export-include-directories \ + ament-cmake-export-interfaces \ + ament-cmake-export-libraries \ + ament-cmake-export-link-flags \ + ament-cmake-export-targets \ + ament-cmake-gmock \ + ament-cmake-gtest \ + ament-cmake-include-directories \ + ament-cmake-libraries \ + ament-cmake \ + ament-cmake-pytest \ + ament-cmake-python \ + ament-cmake-ros \ + ament-cmake-target-dependencies \ + ament-cmake-test \ + ament-cmake-version \ + ament-cmake-uncrustify \ + ament-cmake-flake8 \ + ament-cmake-pep257 \ + ament-copyright \ + ament-cpplint \ + ament-flake8 \ + ament-index-python \ + ament-lint-cmake \ + ament-mypy \ + ament-package \ + ament-pclint \ + ament-pep257 \ + ament-pycodestyle \ + ament-pyflakes \ + ament-uncrustify \ + ament-xmllint \ + cmake \ + eigen3-cmake-module \ + rosidl-cmake \ + rosidl-default-generators \ + rosidl-generator-c \ + rosidl-generator-cpp \ + rosidl-generator-dds-idl \ + rosidl-generator-py \ + rosidl-parser \ + rosidl-runtime-c \ + rosidl-runtime-cpp \ + rosidl-typesupport-c \ + rosidl-typesupport-cpp \ + rosidl-typesupport-fastrtps-cpp \ + rosidl-typesupport-interface \ + rosidl-typesupport-introspection-c \ + rosidl-typesupport-introspection-cpp \ + foonathan-memory-vendor \ + libyaml-vendor \ +" + +X_IMAGE_INSTALL:append = " \ + examples-rclcpp-minimal-action-client \ + examples-rclcpp-minimal-action-server \ + examples-rclcpp-minimal-client \ + examples-rclcpp-minimal-composition \ + examples-rclcpp-minimal-publisher \ + examples-rclcpp-minimal-service \ + examples-rclcpp-minimal-subscriber \ + examples-rclcpp-minimal-timer \ + examples-rclcpp-multithreaded-executor \ + examples-rclpy-executors \ + examples-rclpy-minimal-action-client \ + examples-rclpy-minimal-action-server \ + examples-rclpy-minimal-client \ + examples-rclpy-minimal-publisher \ + examples-rclpy-minimal-service \ + examples-rclpy-minimal-subscriber \ + demo-nodes-cpp \ + demo-nodes-cpp-rosnative \ + demo-nodes-py \ + cyclonedds \ + rmw-cyclonedds-cpp \ + tmux \ + python3-argcomplete \ + glibc-utils \ + localedef \ + rt-tests \ + stress \ + \ + opencv-staticdev \ + lttng-tools lttng-modules lttng-ust \ + libstdc++ \ + libstdc++-dev \ + libnvvpi1 \ + libnvvpi1-dev \ +" + + +IMAGE_LINGUAS = "en-us" +GLIBC_GENERATE_LOCALES = "en_US.UTF-8" diff --git a/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/files/cmake-sdk.cmake b/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/files/cmake-sdk.cmake new file mode 100644 index 0000000..e8a4c13 --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/files/cmake-sdk.cmake @@ -0,0 +1,5 @@ +set( CMAKE_FIND_ROOT_PATH_MODE_PACKAGE BOTH ) +set( ROS_PYTHON_VERSION 3 ) +SET( ROS_DISTRO iron ) +# SET( CMAKE_SYSTEM_PROCESSOR aarch64 ) # geographiclib needs this and it would be overriden by the toolchain file +# set( NADIR_CROSS_COMPILE ON ) \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/files/environment.d-sdk.sh b/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/files/environment.d-sdk.sh new file mode 100644 index 0000000..3b940c4 --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/files/environment.d-sdk.sh @@ -0,0 +1,12 @@ + +export PYTHONPATH="${OECORE_NATIVE_SYSROOT}/usr/lib/python3.10/site-packages:${SDKTARGETSYSROOT}/usr/lib/python3.10/site-packages" +export AMENT_PREFIX_PATH=${OECORE_NATIVE_SYSROOT}/usr:${SDKTARGETSYSROOT}/usr +export ROS_PYTHON_VERSION=3 +export ROS_DISTRO=iron + +# if file sdk.cmake exists, then we are in the SDK +if [ -f ${OECORE_NATIVE_SYSROOT}/environment-setup.d/sdk.cmake ]; then + echo "Moving cmake config." + mkdir -p ${OECORE_NATIVE_SYSROOT}/usr/share/cmake/OEToolchainConfig.cmake.d + mv ${OECORE_NATIVE_SYSROOT}/environment-setup.d/sdk.cmake ${OECORE_NATIVE_SYSROOT}/usr/share/cmake/OEToolchainConfig.cmake.d/ +fi \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/ros2-demo-image-sdk-support_1.0.0.bb b/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/ros2-demo-image-sdk-support_1.0.0.bb new file mode 100644 index 0000000..9c90cfd --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-sdk/sdk-support/ros2-demo-image-sdk-support_1.0.0.bb @@ -0,0 +1,25 @@ +LICENSE = "CLOSED" + +inherit toolchain-scripts + +SRC_URI:append:class-nativesdk = " \ + file://environment.d-sdk.sh \ + file://cmake-sdk.cmake \ +" +do_install:append:class-nativesdk() { + + mkdir -p ${D}${SDKPATHNATIVE}/environment-setup.d + install -m 644 ${WORKDIR}/environment.d-sdk.sh ${D}${SDKPATHNATIVE}/environment-setup.d/sdk.sh + + mkdir -p ${D}${SDKPATHNATIVE}/usr/share/cmake/OEToolchainConfig.cmake.d + install -m 644 ${WORKDIR}/cmake-sdk.cmake ${D}${SDKPATHNATIVE}/usr/share/cmake/OEToolchainConfig.cmake.d/sdk.cmake + install -m 644 ${WORKDIR}/cmake-sdk.cmake ${D}${SDKPATHNATIVE}/environment-setup.d/sdk.cmake + # ln -s ${D}${SDKPATHTARGET}/lib/ld-*.so* ${D}/lib/ +} + +BBCLASSEXTEND =+ "nativesdk" + +FILES:${PN}:append:class-nativesdk = " \ + ${SDKPATHNATIVE}/environment-setup.d/ \ + ${SDKPATHNATIVE}/usr/share/cmake/OEToolchainConfig.cmake.d/sdk.cmake \ +" \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-support/python/python3-distlib_%.bbappend b/layers/meta-ros2-demo-image/recipes-support/python/python3-distlib_%.bbappend new file mode 100644 index 0000000..c25ac76 --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-support/python/python3-distlib_%.bbappend @@ -0,0 +1,17 @@ +# Later version of distlib doesn't have a setup.py. +# This is a workaround for that. + +do_configure:prepend() { + cat > ${S}/setup.py <<-EOF +from setuptools import setup + +setup( + name="${PYPI_PACKAGE}", + version="${PV}", + license="${LICENSE}", + packages=[ + 'distlib', + ], +) +EOF +} \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-support/python/python3-lark-parser_%.bbappend b/layers/meta-ros2-demo-image/recipes-support/python/python3-lark-parser_%.bbappend new file mode 100644 index 0000000..021d530 --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-support/python/python3-lark-parser_%.bbappend @@ -0,0 +1 @@ +BBCLASSEXTEND += " nativesdk " \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-support/python/python3-netifaces_%.bbappend b/layers/meta-ros2-demo-image/recipes-support/python/python3-netifaces_%.bbappend new file mode 100644 index 0000000..48dcd2c --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-support/python/python3-netifaces_%.bbappend @@ -0,0 +1,2 @@ +# Needed for nativesdk-ros2cli to work. +BBCLASSEXTEND += " nativesdk " \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-support/ros2/ros2cli-common-extensions_%.bbappend b/layers/meta-ros2-demo-image/recipes-support/ros2/ros2cli-common-extensions_%.bbappend new file mode 100644 index 0000000..021d530 --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-support/ros2/ros2cli-common-extensions_%.bbappend @@ -0,0 +1 @@ +BBCLASSEXTEND += " nativesdk " \ No newline at end of file diff --git a/layers/meta-ros2-demo-image/recipes-support/ros2/ros2cli_%.bbappend b/layers/meta-ros2-demo-image/recipes-support/ros2/ros2cli_%.bbappend new file mode 100644 index 0000000..65f43ba --- /dev/null +++ b/layers/meta-ros2-demo-image/recipes-support/ros2/ros2cli_%.bbappend @@ -0,0 +1,3 @@ +BBCLASSEXTEND += " nativesdk " + +RDEPENDS:${PN}:class-nativesdk:remove = " ${PN}-dev" \ No newline at end of file diff --git a/layers/meta-yocto-bsp b/layers/meta-yocto-bsp new file mode 120000 index 0000000..310eb02 --- /dev/null +++ b/layers/meta-yocto-bsp @@ -0,0 +1 @@ +../repos/poky/meta-yocto-bsp \ No newline at end of file diff --git a/playground/.gitignore b/playground/.gitignore new file mode 100644 index 0000000..182e46a --- /dev/null +++ b/playground/.gitignore @@ -0,0 +1,3 @@ +build +log +install diff --git a/playground/action_tutorials_cpp/CMakeLists.txt b/playground/action_tutorials_cpp/CMakeLists.txt new file mode 100644 index 0000000..dcf9eec --- /dev/null +++ b/playground/action_tutorials_cpp/CMakeLists.txt @@ -0,0 +1,67 @@ +cmake_minimum_required(VERSION 3.8) +project(action_tutorials_cpp) + +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(action_tutorials_interfaces REQUIRED) +find_package(rclcpp REQUIRED) +find_package(rclcpp_action REQUIRED) +find_package(rclcpp_components REQUIRED) + +add_library(action_client SHARED + src/fibonacci_action_client.cpp) +target_include_directories(action_client PRIVATE + $ + $) +target_compile_definitions(action_client + PRIVATE "ACTION_TUTORIALS_CPP_BUILDING_DLL") +ament_target_dependencies(action_client + "action_tutorials_interfaces" + "rclcpp" + "rclcpp_action" + "rclcpp_components") +rclcpp_components_register_node(action_client PLUGIN "action_tutorials_cpp::FibonacciActionClient" EXECUTABLE fibonacci_action_client) +install(TARGETS + action_client + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) + + +add_library(action_server SHARED + src/fibonacci_action_server.cpp) +target_include_directories(action_server PRIVATE + $ + $) +target_compile_definitions(action_server + PRIVATE "ACTION_TUTORIALS_CPP_BUILDING_DLL") +ament_target_dependencies(action_server + "action_tutorials_interfaces" + "rclcpp" + "rclcpp_action" + "rclcpp_components") +rclcpp_components_register_node(action_server PLUGIN "action_tutorials_cpp::FibonacciActionServer" EXECUTABLE fibonacci_action_server) +install(TARGETS + action_server + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) + + +if(BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + # the following line skips the linter which checks for copyrights + # comment the line when a copyright and license is added to all source files + set(ament_cmake_copyright_FOUND TRUE) + # the following line skips cpplint (only works in a git repo) + # comment the line when this package is in a git repo and when + # a copyright and license is added to all source files + set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif() + +ament_package() diff --git a/playground/action_tutorials_cpp/include/action_tutorials_cpp/visibility_control.h b/playground/action_tutorials_cpp/include/action_tutorials_cpp/visibility_control.h new file mode 100644 index 0000000..04d7f5d --- /dev/null +++ b/playground/action_tutorials_cpp/include/action_tutorials_cpp/visibility_control.h @@ -0,0 +1,44 @@ +#ifndef ACTION_TUTORIALS_CPP__VISIBILITY_CONTROL_H_ +#define ACTION_TUTORIALS_CPP__VISIBILITY_CONTROL_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef __GNUC__ + #define ACTION_TUTORIALS_CPP_EXPORT __attribute__ ((dllexport)) + #define ACTION_TUTORIALS_CPP_IMPORT __attribute__ ((dllimport)) + #else + #define ACTION_TUTORIALS_CPP_EXPORT __declspec(dllexport) + #define ACTION_TUTORIALS_CPP_IMPORT __declspec(dllimport) + #endif + #ifdef ACTION_TUTORIALS_CPP_BUILDING_DLL + #define ACTION_TUTORIALS_CPP_PUBLIC ACTION_TUTORIALS_CPP_EXPORT + #else + #define ACTION_TUTORIALS_CPP_PUBLIC ACTION_TUTORIALS_CPP_IMPORT + #endif + #define ACTION_TUTORIALS_CPP_PUBLIC_TYPE ACTION_TUTORIALS_CPP_PUBLIC + #define ACTION_TUTORIALS_CPP_LOCAL +#else + #define ACTION_TUTORIALS_CPP_EXPORT __attribute__ ((visibility("default"))) + #define ACTION_TUTORIALS_CPP_IMPORT + #if __GNUC__ >= 4 + #define ACTION_TUTORIALS_CPP_PUBLIC __attribute__ ((visibility("default"))) + #define ACTION_TUTORIALS_CPP_LOCAL __attribute__ ((visibility("hidden"))) + #else + #define ACTION_TUTORIALS_CPP_PUBLIC + #define ACTION_TUTORIALS_CPP_LOCAL + #endif + #define ACTION_TUTORIALS_CPP_PUBLIC_TYPE +#endif + +#ifdef __cplusplus +} +#endif + +#endif // ACTION_TUTORIALS_CPP__VISIBILITY_CONTROL_H_ diff --git a/playground/action_tutorials_cpp/package.xml b/playground/action_tutorials_cpp/package.xml new file mode 100644 index 0000000..0848967 --- /dev/null +++ b/playground/action_tutorials_cpp/package.xml @@ -0,0 +1,23 @@ + + + + action_tutorials_cpp + 0.0.0 + TODO: Package description + sdkbuild + TODO: License declaration + + ament_cmake + + action_tutorials_interfaces + rclcpp + rclcpp_action + rclcpp_components + + ament_lint_auto + ament_lint_common + + + ament_cmake + + diff --git a/playground/action_tutorials_cpp/src/fibonacci_action_client.cpp b/playground/action_tutorials_cpp/src/fibonacci_action_client.cpp new file mode 100644 index 0000000..e070772 --- /dev/null +++ b/playground/action_tutorials_cpp/src/fibonacci_action_client.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include + +#include "action_tutorials_interfaces/action/fibonacci.hpp" + +#include "rclcpp/rclcpp.hpp" +#include "rclcpp_action/rclcpp_action.hpp" +#include "rclcpp_components/register_node_macro.hpp" + +namespace action_tutorials_cpp +{ +class FibonacciActionClient : public rclcpp::Node +{ +public: + using Fibonacci = action_tutorials_interfaces::action::Fibonacci; + using GoalHandleFibonacci = rclcpp_action::ClientGoalHandle; + + explicit FibonacciActionClient(const rclcpp::NodeOptions & options) + : Node("fibonacci_action_client", options) + { + this->client_ptr_ = rclcpp_action::create_client( + this, + "fibonacci"); + + this->timer_ = this->create_wall_timer( + std::chrono::milliseconds(500), + std::bind(&FibonacciActionClient::send_goal, this)); + } + + void send_goal() + { + using namespace std::placeholders; + + this->timer_->cancel(); + + if (!this->client_ptr_->wait_for_action_server()) { + RCLCPP_ERROR(this->get_logger(), "Action server not available after waiting"); + rclcpp::shutdown(); + } + + auto goal_msg = Fibonacci::Goal(); + goal_msg.order = 10; + + RCLCPP_INFO(this->get_logger(), "Sending goal"); + + auto send_goal_options = rclcpp_action::Client::SendGoalOptions(); + auto callback = std::bind(&FibonacciActionClient::goal_response_callback, this, _1); + send_goal_options.goal_response_callback = callback; + + send_goal_options.feedback_callback = + std::bind(&FibonacciActionClient::feedback_callback, this, _1, _2); + send_goal_options.result_callback = + std::bind(&FibonacciActionClient::result_callback, this, _1); + this->client_ptr_->async_send_goal(goal_msg, send_goal_options); + } + +private: + rclcpp_action::Client::SharedPtr client_ptr_; + rclcpp::TimerBase::SharedPtr timer_; + + void goal_response_callback(GoalHandleFibonacci::SharedPtr goal_handle) + { + // auto goal_handle = future.get(); + if (!goal_handle) { + RCLCPP_ERROR(this->get_logger(), "Goal was rejected by server"); + } else { + RCLCPP_INFO(this->get_logger(), "Goal accepted by server, waiting for result"); + } + } + + void feedback_callback( + GoalHandleFibonacci::SharedPtr, + const std::shared_ptr feedback) + { + std::stringstream ss; + ss << "Next number in sequence received: "; + for (auto number : feedback->partial_sequence) { + ss << number << " "; + } + RCLCPP_INFO(this->get_logger(), ss.str().c_str()); + } + + void result_callback(const GoalHandleFibonacci::WrappedResult & result) + { + switch (result.code) { + case rclcpp_action::ResultCode::SUCCEEDED: + break; + case rclcpp_action::ResultCode::ABORTED: + RCLCPP_ERROR(this->get_logger(), "Goal was aborted"); + return; + case rclcpp_action::ResultCode::CANCELED: + RCLCPP_ERROR(this->get_logger(), "Goal was canceled"); + return; + default: + RCLCPP_ERROR(this->get_logger(), "Unknown result code"); + return; + } + std::stringstream ss; + ss << "Result received: "; + for (auto number : result.result->sequence) { + ss << number << " "; + } + RCLCPP_INFO(this->get_logger(), ss.str().c_str()); + rclcpp::shutdown(); + } +}; // class FibonacciActionClient + +} // namespace action_tutorials_cpp + +RCLCPP_COMPONENTS_REGISTER_NODE(action_tutorials_cpp::FibonacciActionClient) diff --git a/playground/action_tutorials_cpp/src/fibonacci_action_server.cpp b/playground/action_tutorials_cpp/src/fibonacci_action_server.cpp new file mode 100644 index 0000000..599532d --- /dev/null +++ b/playground/action_tutorials_cpp/src/fibonacci_action_server.cpp @@ -0,0 +1,100 @@ +#include +#include +#include + +#include "action_tutorials_interfaces/action/fibonacci.hpp" +#include "rclcpp/rclcpp.hpp" +#include "rclcpp_action/rclcpp_action.hpp" +#include "rclcpp_components/register_node_macro.hpp" + +#include "action_tutorials_cpp/visibility_control.h" + +namespace action_tutorials_cpp +{ +class FibonacciActionServer : public rclcpp::Node +{ +public: + using Fibonacci = action_tutorials_interfaces::action::Fibonacci; + using GoalHandleFibonacci = rclcpp_action::ServerGoalHandle; + + ACTION_TUTORIALS_CPP_PUBLIC + explicit FibonacciActionServer(const rclcpp::NodeOptions & options = rclcpp::NodeOptions()) + : Node("fibonacci_action_server", options) + { + using namespace std::placeholders; + + this->action_server_ = rclcpp_action::create_server( + this, + "fibonacci", + std::bind(&FibonacciActionServer::handle_goal, this, _1, _2), + std::bind(&FibonacciActionServer::handle_cancel, this, _1), + std::bind(&FibonacciActionServer::handle_accepted, this, _1)); + } + +private: + rclcpp_action::Server::SharedPtr action_server_; + + rclcpp_action::GoalResponse handle_goal( + const rclcpp_action::GoalUUID & uuid, + std::shared_ptr goal) + { + RCLCPP_INFO(this->get_logger(), "Received goal request with order %d", goal->order); + (void)uuid; + return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE; + } + + rclcpp_action::CancelResponse handle_cancel( + const std::shared_ptr goal_handle) + { + RCLCPP_INFO(this->get_logger(), "Received request to cancel goal"); + (void)goal_handle; + return rclcpp_action::CancelResponse::ACCEPT; + } + + void handle_accepted(const std::shared_ptr goal_handle) + { + using namespace std::placeholders; + // this needs to return quickly to avoid blocking the executor, so spin up a new thread + std::thread{std::bind(&FibonacciActionServer::execute, this, _1), goal_handle}.detach(); + } + + void execute(const std::shared_ptr goal_handle) + { + RCLCPP_INFO(this->get_logger(), "Executing goal"); + rclcpp::Rate loop_rate(1); + const auto goal = goal_handle->get_goal(); + auto feedback = std::make_shared(); + auto & sequence = feedback->partial_sequence; + sequence.push_back(0); + sequence.push_back(1); + auto result = std::make_shared(); + + for (int i = 1; (i < goal->order) && rclcpp::ok(); ++i) { + // Check if there is a cancel request + if (goal_handle->is_canceling()) { + result->sequence = sequence; + goal_handle->canceled(result); + RCLCPP_INFO(this->get_logger(), "Goal canceled"); + return; + } + // Update sequence + sequence.push_back(sequence[i] + sequence[i - 1]); + // Publish feedback + goal_handle->publish_feedback(feedback); + RCLCPP_INFO(this->get_logger(), "Publish feedback"); + + loop_rate.sleep(); + } + + // Check if goal is done + if (rclcpp::ok()) { + result->sequence = sequence; + goal_handle->succeed(result); + RCLCPP_INFO(this->get_logger(), "Goal succeeded"); + } + } +}; // class FibonacciActionServer + +} // namespace action_tutorials_cpp + +RCLCPP_COMPONENTS_REGISTER_NODE(action_tutorials_cpp::FibonacciActionServer) diff --git a/repos/bitbake b/repos/bitbake deleted file mode 120000 index e3b8047..0000000 --- a/repos/bitbake +++ /dev/null @@ -1 +0,0 @@ -poky/bitbake \ No newline at end of file diff --git a/repos/meta-ros b/repos/meta-ros index 83f8e1a..a6a0b3c 160000 --- a/repos/meta-ros +++ b/repos/meta-ros @@ -1 +1 @@ -Subproject commit 83f8e1a17f8a7164f5f8c8f062991eb05438497e +Subproject commit a6a0b3ca8431a79b317d8be082290b2ceb806f11 diff --git a/repos/poky b/repos/poky index 09def30..e51bf55 160000 --- a/repos/poky +++ b/repos/poky @@ -1 +1 @@ -Subproject commit 09def309f91929f47c6cce386016ccb777bd2cfc +Subproject commit e51bf557f596c4da38789a948a3228ba11455e3c diff --git a/scripts/create-sdk-docker-latest.sh b/scripts/create-sdk-docker-latest.sh new file mode 100755 index 0000000..63fa86d --- /dev/null +++ b/scripts/create-sdk-docker-latest.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +docker build . -t yocto-ros-cross-sdk:latest --build-arg="CURRENT_DIR=$(pwd)" \ No newline at end of file diff --git a/scripts/start-build-container.sh b/scripts/start-build-container.sh new file mode 100755 index 0000000..febb1ab --- /dev/null +++ b/scripts/start-build-container.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +CONTAINER="yocto-ros-cross-sdk:latest" + +# check if we have a parameter, if so, assign it to CURRENT_DIR +if [ -n "$1" ]; then + CURRENT_DIR=$1 + # check if the path is relative, if so, make it absolute + if [[ $CURRENT_DIR != /* ]]; then + CURRENT_DIR="$(pwd)/$CURRENT_DIR" + fi +else + CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/" +fi + +echo "Starting with '/workdir' set to: ${CURRENT_DIR}" +echo "" + +docker run \ + -it --rm \ + -v $(pwd):/workdir \ + ${CONTAINER} +