Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,10 @@ repos:
- id: check-xml
- id: check-yaml
- id: detect-private-key
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt
language: system
pass_filenames: false
22 changes: 22 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,28 @@
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"rust-analyzer.check.overrideCommand": [
"pixi",
"run",
"cargo",
"check",
"--quiet",
"--workspace",
"--message-format=json",
"--all-targets",
"--keep-going"
],
"rust-analyzer.cargo.buildScripts.overrideCommand": [
"pixi",
"run",
"cargo",
"check",
"--quiet",
"--workspace",
"--message-format=json",
"--all-targets",
"--keep-going"
],
"search.exclude": {
"build": true,
"install": true,
Expand Down
14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[workspace]
members = [
"src/bitbots_misc/bitbots_extrinsic_calibration",
"src/bitbots_navigation/bitbots_global_planner"
]

# Optional but recommended for modern Cargo
resolver = "2"

# We use a custom profile to keep colcon
# separate from "normal" rust building.
[profile.colcon]
inherits = "release"
debug = true
4,173 changes: 902 additions & 3,271 deletions pixi.lock

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ cmd = "colcon test --parallel-workers 1 --event-handlers console_direct+ --retur
[dependencies]
# Base dependencies
python = "==3.12.1, <3.13"
rust = ">=1.88"

# Patches
readline = ">=8.2.999" # This is needed because we want to install an empty readline package from our models channel that leads to the system version being used. Otherwise we might have a mismatch between bash (often accessed globally ignoring the env) and readline (provided by the env) breaking everything.

[feature.ros.dependencies]
# Misc dependencies for our ROS 2 packages
alsa-plugins = ">=1.2.12,<2"
clang = ">=21.1.0,<22" # Needed for r2r rust bindings generation
beartype = ">=0.22.6,<0.23"
breathe = ">=4.36.0,<5"
cbor2 = ">=5.9.0,<6"
Expand Down Expand Up @@ -175,9 +177,6 @@ bitbots_model_2023_04_04_philipp_yoeox_with_team_colors = ">=1.0.0,<2"
bitbots_model_2022_10_07_flo_torso21_yoeox = ">=1.0.0,<2"
tts-supertonic = ">=1.0.0,<2"

# Local packages
bitbots_rust_nav = { path = "src/bitbots_navigation/bitbots_rust_nav" }

# Patches
pillow = "<12" # this constraint is needed as yoeo specifies the 11 major version and otherwise uv fails to solve given the constrains from the conda ecosystem.
setuptools = "==68.1.2" # Pinning setuptools to avoid issues with colcon build
Expand Down Expand Up @@ -205,6 +204,10 @@ ros-jazzy-robot-localization = ">=3.8.3,<4"
# These are only needed on the robot


[activation.env]
CARGO_TARGET_DIR = "$PIXI_PROJECT_ROOT/build/cargo_target"


[feature.ros.activation.env]
#ROS_AUTOMATIC_DISCOVERY_RANGE = "LOCALHOST"
RCUTILS_COLORIZED_OUTPUT = "1"
Expand Down
6 changes: 6 additions & 0 deletions src/bitbots_misc/bitbots_cargo/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(bitbots_cargo)

find_package(ament_cmake REQUIRED)

ament_package(CONFIG_EXTRAS cmake/bitbots_cargo.cmake.in)
201 changes: 201 additions & 0 deletions src/bitbots_misc/bitbots_cargo/cmake/bitbots_cargo.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@

# Need at least 3.21 for IMPORTED_TARGETS property that we rely on.
# NOTE! Ubuntu 20.04 comes 3.16.3 by default, so to use this you need
# to update cmake. This can be done by adding the kitware apt repo:
# https://apt.kitware.com
Comment thread
Flova marked this conversation as resolved.
Outdated
cmake_minimum_required(VERSION "3.21")

# traverse dependencies for all message packages.
function(get_idl_deps OUT_PKG_DIRS PKG)
find_package(${PKG} REQUIRED)
target_link_libraries(dummy INTERFACE ${${PKG}_LIBRARIES})
include_directories(dummy ${${PKG}_INCLUDE_DIRS})

list(APPEND VISITED_TARGETS ${PKG})

# only keep track of packages that include idl files
set(PKG_DIRS "")
if(DEFINED ${PKG}_IDL_FILES)
list(APPEND PKG_DIRS ${${PKG}_DIR})
endif()

foreach(LIB ${${PKG}_DEPENDENCIES})
list(FIND VISITED_TARGETS ${LIB} VISITED)
if (${VISITED} EQUAL -1)
get_idl_deps(NEW_PKG_DIRS ${LIB})
list(APPEND PKG_DIRS ${NEW_PKG_DIRS})
list(REMOVE_DUPLICATES PKG_DIRS)
endif()
endforeach()
set(VISITED_TARGETS ${VISITED_TARGETS} PARENT_SCOPE)
set(${OUT_PKG_DIRS} ${PKG_DIRS} PARENT_SCOPE)
endfunction()

function(r2r_cargo)
# pretend that we want to compile c code to get all library paths etc...
add_library(dummy INTERFACE)

# traverse list of wanted packages to add dependencies
foreach(f ${ARGN})
find_package(${f} REQUIRED)
set(REC_PKG_DIRS "")
get_idl_deps(REC_PKG_DIRS ${f})
list(APPEND CMAKE_IDL_PACKAGES "${REC_PKG_DIRS}")
endforeach()

list(REMOVE_DUPLICATES CMAKE_IDL_PACKAGES)
string (REPLACE ";" ":" CMAKE_IDL_PACKAGES_STR "${CMAKE_IDL_PACKAGES}")
set(ENV{CMAKE_IDL_PACKAGES} ${CMAKE_IDL_PACKAGES_STR})

# On OSX colcon eats the DYLD_LIBRARY_PATH... so we need to add the rpaths
# manually...
set(RUSTFLAGS "")

# get imported libs
get_property(importTargets DIRECTORY "${CMAKE_SOURCE_DIR}" PROPERTY IMPORTED_TARGETS)

foreach(p ${importTargets})
get_property(_LIBLOC TARGET "${p}" PROPERTY LOCATION)
if(DEFINED _LIBLOC)
list(APPEND CMAKE_LIBRARIES "${_LIBLOC}")
get_filename_component(_PARENT "${_LIBLOC}" DIRECTORY)
if(IS_DIRECTORY ${_PARENT})
list(APPEND RUSTFLAGS "-C link-arg=-Wl,-rpath,${_PARENT}")
endif()
endif()
endforeach()

list(REMOVE_DUPLICATES RUSTFLAGS)
string (REPLACE ";" " " RUSTFLAGS_STR "${RUSTFLAGS}")
set(ENV{RUSTFLAGS} ${RUSTFLAGS_STR})

# get include paths
get_property(includeDirs DIRECTORY "${CMAKE_SOURCE_DIR}" PROPERTY INCLUDE_DIRECTORIES)
list(REMOVE_DUPLICATES includeDirs)
string (REPLACE ";" ":" CMAKE_INCLUDE_DIRS_STR "${includeDirs}")
set(ENV{CMAKE_INCLUDE_DIRS} ${CMAKE_INCLUDE_DIRS_STR})

add_custom_target(cargo_target ALL
COMMAND ${CMAKE_COMMAND} "-E" "env" "--unset=MAKEFLAGS" "--unset=MFLAGS" "RUSTFLAGS=$ENV{RUSTFLAGS}" "CMAKE_IDL_PACKAGES=$ENV{CMAKE_IDL_PACKAGES}" "CMAKE_INCLUDE_DIRS=$ENV{CMAKE_INCLUDE_DIRS}" "cargo" "build" "--profile" "colcon" "--quiet"
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
USES_TERMINAL
VERBATIM
)

if(BUILD_TESTING)
add_test(
NAME cargo_test
COMMAND ${CMAKE_COMMAND} "-E" "env" "--unset=MAKEFLAGS" "--unset=MFLAGS"
"RUSTFLAGS=$ENV{RUSTFLAGS}"
"CMAKE_IDL_PACKAGES=$ENV{CMAKE_IDL_PACKAGES}"
"CMAKE_INCLUDE_DIRS=$ENV{CMAKE_INCLUDE_DIRS}"
cargo test --package ${PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()

endfunction()

# Private helper: resolve the cargo workspace target directory.
function(_cargo_get_target_dir OUT_DIR)
execute_process(
COMMAND cargo metadata --no-deps --format-version=1
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE _METADATA_JSON
OUTPUT_STRIP_TRAILING_WHITESPACE)
string(JSON _TARGET_DIR GET "${_METADATA_JSON}" target_directory)
set(${OUT_DIR} "${_TARGET_DIR}" PARENT_SCOPE)
endfunction()

# Build a pyo3 Python extension and install it flat into site-packages so
# `import <package>` works after sourcing install/setup.bash.
#
# Usage: cargo_pyo3_extension([PACKAGE <cargo_crate_name>])
# PACKAGE defaults to ${PROJECT_NAME}
function(cargo_pyo3_extension)
cmake_parse_arguments(_ARGS "" "PACKAGE" "" ${ARGN})
if(NOT _ARGS_PACKAGE)
set(_ARGS_PACKAGE ${PROJECT_NAME})
endif()

find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
_cargo_get_target_dir(_CARGO_TARGET_DIR)

execute_process(
COMMAND ${Python3_EXECUTABLE} -c
"import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"
OUTPUT_VARIABLE _PYTHON_EXT_SUFFIX
OUTPUT_STRIP_TRAILING_WHITESPACE)

set(_PYTHON_INSTALL_DIR
lib/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages)

add_custom_target(cargo_${_ARGS_PACKAGE} ALL
COMMAND ${CMAKE_COMMAND} "-E" "env" "--unset=MAKEFLAGS" "--unset=MFLAGS"
"PYO3_PYTHON=${Python3_EXECUTABLE}"
cargo build --profile colcon --package ${_ARGS_PACKAGE}
--features pyo3/extension-module --quiet
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
USES_TERMINAL
VERBATIM
)

install(CODE "
file(COPY
\"${_CARGO_TARGET_DIR}/colcon/lib${_ARGS_PACKAGE}.so\"
DESTINATION \"\${CMAKE_INSTALL_PREFIX}/${_PYTHON_INSTALL_DIR}/\")
file(RENAME
\"\${CMAKE_INSTALL_PREFIX}/${_PYTHON_INSTALL_DIR}/lib${_ARGS_PACKAGE}.so\"
\"\${CMAKE_INSTALL_PREFIX}/${_PYTHON_INSTALL_DIR}/${_ARGS_PACKAGE}${_PYTHON_EXT_SUFFIX}\")
")

if(BUILD_TESTING)
add_test(
NAME cargo_test
COMMAND ${CMAKE_COMMAND} "-E" "env" "--unset=MAKEFLAGS" "--unset=MFLAGS"
"PYO3_PYTHON=${Python3_EXECUTABLE}"
cargo test --package ${_ARGS_PACKAGE} --features pyo3/extension-module
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
endfunction()

# Build a standalone Rust binary and install it to lib/${PROJECT_NAME}/ so
# it is launchable via `ros2 run ${PROJECT_NAME} <binary_name>`.
#
# Usage: cargo_binary(<binary_name> [PACKAGE <cargo_crate_name>])
# PACKAGE defaults to ${PROJECT_NAME}
function(cargo_binary BINARY_NAME)
cmake_parse_arguments(_ARGS "" "PACKAGE" "" ${ARGN})
if(NOT _ARGS_PACKAGE)
set(_ARGS_PACKAGE ${BINARY_NAME})
endif()

_cargo_get_target_dir(_CARGO_TARGET_DIR)

if(WIN32)
set(_SUFFIX ".exe")
else()
set(_SUFFIX "")
endif()

add_custom_target(cargo_${BINARY_NAME} ALL
COMMAND ${CMAKE_COMMAND} "-E" "env" "--unset=MAKEFLAGS" "--unset=MFLAGS"
cargo build --profile colcon --package ${_ARGS_PACKAGE} --quiet
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
USES_TERMINAL
VERBATIM
)

install(PROGRAMS ${_CARGO_TARGET_DIR}/colcon/${BINARY_NAME}${_SUFFIX}
DESTINATION lib/${PROJECT_NAME})

if(BUILD_TESTING)
add_test(
NAME cargo_test
COMMAND ${CMAKE_COMMAND} "-E" "env" "--unset=MAKEFLAGS" "--unset=MFLAGS"
cargo test --package ${_ARGS_PACKAGE}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
endfunction()
19 changes: 19 additions & 0 deletions src/bitbots_misc/bitbots_cargo/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>bitbots_cargo</name>
<version>1.0.0</version>
<description>CMake helper for Rust based Bit-Bots packages.</description>

<maintainer email="info@bit-bots.de">Hamburg Bit-Bots</maintainer>

<license>MIT</license>

<author email="info@bit-bots.de">Hamburg Bit-Bots</author>

<buildtool_depend>ament_cmake</buildtool_depend>

<export>
<build_type>ament_cmake</build_type>
</export>
</package>
66 changes: 29 additions & 37 deletions src/bitbots_misc/bitbots_extrinsic_calibration/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,48 +1,40 @@
cmake_minimum_required(VERSION 3.5)
project(bitbots_extrinsic_calibration)

# Add support for C++17
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 17)
find_package(ament_cmake REQUIRED)
find_package(bitbots_cargo REQUIRED)

# put ros package dependencies here.
r2r_cargo(
rcl # we need the c ros2 api
rcl_action # as of r2r 0.1.0, we also need the action api
rosgraph_msgs # for the Clock message
geometry_msgs
tf2_msgs)

# install binaries
if(WIN32)
set(SUFFIX ".exe")
else()
set(SUFFIX "")
endif()

# Build with release optimizations and debug symbols by default
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebug)
endif()
execute_process(
COMMAND cargo metadata --no-deps --format-version=1
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE CARGO_METADATA_JSON
OUTPUT_STRIP_TRAILING_WHITESPACE)

find_package(ament_cmake REQUIRED)
find_package(backward_ros REQUIRED)
find_package(bitbots_docs REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rot_conv REQUIRED)
find_package(std_msgs REQUIRED)
find_package(tf2 REQUIRED)
find_package(tf2_geometry_msgs REQUIRED)
find_package(tf2_ros REQUIRED)

add_compile_options(-Wall -Werror -Wno-unused)

add_executable(extrinsic_calibration src/extrinsic_calibration.cpp)

ament_target_dependencies(
extrinsic_calibration
ament_cmake
bitbots_docs
rclcpp
std_msgs
tf2
tf2_geometry_msgs
tf2_ros
rot_conv)

enable_bitbots_docs()

install(TARGETS extrinsic_calibration DESTINATION lib/${PROJECT_NAME})
# Extract "target_directory" from JSON
string(JSON CARGO_TARGET_DIR GET "${CARGO_METADATA_JSON}" target_directory)

install(DIRECTORY launch DESTINATION share/${PROJECT_NAME})
message(STATUS "Cargo target dir: ${CARGO_TARGET_DIR}")

install(PROGRAMS ${CARGO_TARGET_DIR}/colcon/${PROJECT_NAME}${SUFFIX}
DESTINATION lib/${PROJECT_NAME})

install(DIRECTORY launch DESTINATION share/${PROJECT_NAME})
install(DIRECTORY config DESTINATION share/${PROJECT_NAME})

# we need this for ros/colcon
ament_package()
Loading
Loading