diff --git a/.bazeliskrc b/.bazeliskrc new file mode 100644 index 0000000..b3fba73 --- /dev/null +++ b/.bazeliskrc @@ -0,0 +1 @@ +USE_BAZEL_VERSION=8.4.2 \ No newline at end of file diff --git a/.bazelrc b/.bazelrc index cd63c79..c182788 100644 --- a/.bazelrc +++ b/.bazelrc @@ -1,15 +1,25 @@ -# Default to an optimized build to match Drake. -build -c opt +# Default to an optimized build. +build --compilation_mode=opt -# Default build options to match Drake. +# Default build options. build --force_pic build --strip=never -build --strict_system_includes + +# Default test options. +build --test_output=errors +build --test_summary=terse # Use C++20. -# Bazel has two universes of command-line copts and linkopts: the "target" -# config (`--copt`) and the "host" aka "exec" config (`--host_copt`). -# Since franka_driver doesn't cross-compile, we want the two configs to be the same, -# so we should always set both flavors for all copts and linkopts. build --cxxopt=-std=c++20 -build --host_cxxopt=-std=c++20 \ No newline at end of file +build --host_cxxopt=-std=c++20 + +# https://github.com/bazelbuild/bazel/issues/1164 +build --action_env=CCACHE_DISABLE=1 + +# Use eigen, fmt, spdlog from the host OS via pkg-config, rather than bzlmod. +# It's okay to remove this line if you'd rather use bzlmod. For details, see: +# https://github.com/RobotLocomotion/drake/blob/master/tools/flags/BUILD.bazel +build --@drake//tools/flags:public_repo_default=pkgconfig + +# Try to import user-specific configuration local to workspace. +try-import %workspace%/user.bazelrc \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4c52b77..7a831c9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ bazel.log core *~ *.jlp +MODULE.bazel.lock +.claude/* \ No newline at end of file diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000..89ffc16 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,117 @@ +module(name = "drake_franka_driver") + +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "rules_cc", version = "0.2.9") +bazel_dep(name = "rules_python", version = "1.6.3") +bazel_dep(name = "gflags", version = "2.2.2") +bazel_dep(name = "rules_shell", version = "0.6.1") + +bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2", dev_dependency = True) + +# Pinocchio is required for libfranka v5 (FR3 robots) dynamics computations. +# Version 2.6.21 provides the rigid body dynamics needed by the modern libfranka API. +bazel_dep(name = "pinocchio", version = "2.6.21.bcr.4") + +# LCM (Lightweight Communications and Marshalling) for inter-process communication. +# Using a specific commit from the main branch for latest features. +LCM_COMMIT = "4f9f586e9fda1ab2d5e12427386226519f65b6de" + +bazel_dep(name = "lcm") +archive_override( + module_name = "lcm", + sha256 = "d2de73ea17993d3586eb9559b48ac3e35dd68064ad6abbdd3e0d4081e5b90685", + strip_prefix = "lcm-{}".format(LCM_COMMIT.lstrip("v")), + urls = [x.format(LCM_COMMIT) for x in [ + "https://github.com/lcm-proj/lcm/archive/{}.tar.gz", + ]], +) + +bazel_dep(name = "drake") + +# Drake version configuration. +DRAKE_COMMIT = "v1.45.0" + +DRAKE_CHECKSUM = "fd70210cbbe233b78bb6df2d8f42c7334ea15fca8833865322d788ab4eaf0c16" + +archive_override( + module_name = "drake", + sha256 = DRAKE_CHECKSUM, + strip_prefix = "drake-{}".format(DRAKE_COMMIT.lstrip("v")), + urls = [x.format(DRAKE_COMMIT) for x in [ + "https://github.com/RobotLocomotion/drake/archive/{}.tar.gz", + ]], +) + +# Use the host system /usr/bin/python3. +python_repository = use_repo_rule( + "@drake//tools/workspace/python:repository.bzl", + "python_repository", +) + +python_repository( + name = "python", + linux_interpreter_path = "/usr/bin/python3", + requirements_flavor = "build", +) + +register_toolchains("@python//:all") + +# Import Drake's public dependencies (deprecated pycodestyle, buildifier). +drake_dep_repositories = use_extension( + "@drake//tools/workspace:default.bzl", + "drake_dep_repositories", +) +use_repo( + drake_dep_repositories, + "buildifier", + "pycodestyle", +) + +# Import Drake's internal dependencies for linting tools. +internal_repositories = use_extension( + "@drake//tools/workspace:default.bzl", + "internal_repositories", +) +use_repo( + internal_repositories, + "cpplint_internal", + "pycodestyle_internal", + "styleguide_internal", +) + +# Create aliases for Drake dependencies that libfranka needs to access. +# Drake uses a flag-based system to switch between module and pkgconfig versions. +# We'll use Drake's eigen_repository to get the configured version. +eigen_repository = use_repo_rule( + "@drake//tools/workspace/eigen:repository.bzl", + "eigen_repository", +) + +eigen_repository(name = "eigen") + +# Import external dependencies for Franka robot control. +# This provides: +# - drake_models: Robot URDF/SDF models for visualization and simulation +# - libfranka_v4 (0.9.0): Control library for FE3 robots with firmware v4.x +# - libfranka_v5 (~0.15.0): Control library for FR3 robots with firmware v5.x +# - libfranka_common_v4/v5: Shared protocol definitions for each version +external_repos = use_extension( + "//tools/workspace:external_repositories.bzl", + "external_repositories", +) +use_repo( + external_repos, + "drake_models", + "libfranka_common_v4", + "libfranka_common_v5", + "libfranka_v4", + "libfranka_v5", +) + +# Poco repository (system library from /usr). +poco_repository = use_repo_rule( + "//tools/workspace/poco:repository.bzl", + "poco_repository", +) + +poco_repository(name = "poco") diff --git a/README.md b/README.md index 6837b3f..0af8a5f 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,20 @@ # Panda Arm - Franka Emika -This repository contains the application code used to communicate with the Franka Emika arm from Drake. +This repository contains the application code used to communicate with the Franka Emika arm from Drake. + +## Software Versions + +This driver supports both FR3 (newer) and FE3 (older) Franka robots: + +- **Drake**: v1.45.0 +- **libfranka v5** (~0.15.0): For FR3 robots with firmware v5.x +- **libfranka v4** (0.9.0): For FE3 robots with firmware v4.x +- **Pinocchio**: 2.6.21 (required for libfranka v5 dynamics) +- **LCM**: Latest from main branch ## Building the driver -Before you begin, install the prerequisite: +Before you begin, install the prerequisites: ``` -sudo apt install libgflags-dev +sudo apt install libgflags-dev libpoco-dev ``` To build, run `bazel build //...`. This will output two versions of @@ -29,8 +39,8 @@ To add a gripper, update the `models/add_franka_control.yaml` with the respectiv ## Links * [Website](https://www.franka.de/technology) -* [Franka Control Interface (FCI) Documentation](https://frankaemika.github.io/docs/) -* [`libfranka` API Docs](https://frankaemika.github.io/libfranka/) +* [Franka Control Interface (FCI) Documentation](https://frankarobotics.github.io/docs/) +* [`libfranka` API Docs](https://frankarobotics.github.io/libfranka/) * [Panda datasheet](https://s3-eu-central-1.amazonaws.com/franka-de-uploads/uploads/Datasheet-EN.pdf) ## Notes @@ -39,11 +49,11 @@ To add a gripper, update the `models/add_franka_control.yaml` with the respectiv * The FCI docs have excellent instructions for getting your network interface on Ubuntu set up. * There are two very distinct versions of Pandas: the FE3 (older) and FR3 (newer) -* There are three version to think about: firmware on the robot (we use -`v4.x`, and `v5.x`) and `libfranka` driver software on the host PC -(`0.8.0` for `v4.x` FE3, and `0.10.0` for `v5.x` FR3). +* There are three versions to think about: firmware on the robot (we use +`v4.x` and `v5.x`), `libfranka` driver software on the host PC +(0.9.0 for `v4.x` FE3, and ~0.15.0 for `v5.x` FR3), and the robot model itself. * You should see suffixes like `_v4` and `_v5` for relevant - libraries and binaries. + libraries and binaries throughout this codebase. * If you use the wrong driver, you should get an error like: terminate called after throwing an instance of 'franka::IncompatibleVersionException' diff --git a/WORKSPACE b/WORKSPACE deleted file mode 100644 index d2fe805..0000000 --- a/WORKSPACE +++ /dev/null @@ -1,71 +0,0 @@ -# -*- python -*- - -workspace(name = "drake_franka_driver") - -load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") - -(DRAKE_COMMIT, DRAKE_CHECKSUM) = ( - "v1.21.0", - "6571295843aff8e11620340739bf5eab7a25130f8f06667b2d3e6df85567509a", -) - -DRAKE_STRIP_PREFIX = "drake-1.21.0" -# If using commit vs. a tag, uncomment below. -# DRAKE_STRIP_PREFIX = "drake-v{}".format(DRAKE_COMMIT) - -# Before changing the COMMIT, temporarily uncomment the next line so that Bazel -# displays the suggested new value for the CHECKSUM. -# DRAKE_CHECKSUM = "0" * 64 - -# Or to build against a local checkout of Drake, at the bash prompt set an -# environment variable before building: -# export FRANKA_LOCAL_DRAKE_PATH=/home/user/stuff/drake - -# Load an environment variable. -load("//:environ.bzl", "environ_repository") - -environ_repository( - name = "environ", - vars = ["FRANKA_LOCAL_DRAKE_PATH"], -) - -load("@environ//:environ.bzl", "FRANKA_LOCAL_DRAKE_PATH") - -# This declares the `@drake` repository as an http_archive from github, -# iff FRANKA_LOCAL_DRAKE_PATH is unset. When it is set, this declares a -# `@drake_ignored` package which is never referenced, and thus is ignored. -http_archive( - name = "drake" if not FRANKA_LOCAL_DRAKE_PATH else "drake_ignored", - sha256 = DRAKE_CHECKSUM, - strip_prefix = DRAKE_STRIP_PREFIX, - urls = [x.format(DRAKE_COMMIT) for x in [ - "https://github.com/RobotLocomotion/drake/archive/{}.tar.gz", - ]], -) - -# This declares the `@drake` repository as a local directory, -# iff FRANKA_LOCAL_DRAKE_PATH is set. When it is unset, this declares a -# `@drake_ignored` package which is never referenced, and thus is ignored. -local_repository( - name = "drake" if FRANKA_LOCAL_DRAKE_PATH else "drake_ignored", - path = FRANKA_LOCAL_DRAKE_PATH, -) - -print("Using FRANKA_LOCAL_DRAKE_PATH={}".format(FRANKA_LOCAL_DRAKE_PATH)) if FRANKA_LOCAL_DRAKE_PATH else None # noqa - -load("@drake//tools/workspace:default.bzl", "add_default_workspace") -add_default_workspace() - - -load("@drake//tools/workspace:mirrors.bzl", "DEFAULT_MIRRORS") -load("//tools/workspace/libfranka_v4:repository.bzl", "libfranka_v4_repository") -load("//tools/workspace/libfranka_v5:repository.bzl", "libfranka_v5_repository") -load("//tools/workspace/libfranka_common_v4:repository.bzl", "libfranka_common_v4_repository") -load("//tools/workspace/libfranka_common_v5:repository.bzl", "libfranka_common_v5_repository") -load("//tools/workspace/poco:repository.bzl", "poco_repository") - -libfranka_v4_repository(name = "libfranka_v4", mirrors = DEFAULT_MIRRORS) -libfranka_v5_repository(name = "libfranka_v5", mirrors = DEFAULT_MIRRORS) -libfranka_common_v4_repository(name = "libfranka_common_v4", mirrors = DEFAULT_MIRRORS) -libfranka_common_v5_repository(name = "libfranka_common_v5", mirrors = DEFAULT_MIRRORS) -poco_repository(name = "poco") \ No newline at end of file diff --git a/environ.bzl b/environ.bzl index d20f4f9..6b4d4f2 100644 --- a/environ.bzl +++ b/environ.bzl @@ -1,11 +1,8 @@ -# -*- mode: python -*- -# vi: set ft=python : - # Write out a repository that contains: # - An empty BUILD file, to define a package. # - An environ.bzl file with variable assignments for each ENV_NAMES item. def _impl(repository_ctx): - vars = repository_ctx.attr._vars + vars = repository_ctx.attr.vars bzl_content = [] for key in vars: value = repository_ctx.os.environ.get(key, "") @@ -21,6 +18,8 @@ def _impl(repository_ctx): executable = False, ) +_string_list = attr.string_list() + def environ_repository(name = None, vars = []): """Provide specific environment variables for use in a WORKSPACE file. The `vars` are the environment variables to provide. @@ -33,9 +32,12 @@ def environ_repository(name = None, vars = []): rule = repository_rule( implementation = _impl, attrs = { - "_vars": attr.string_list(default = vars), + "vars": _string_list, }, local = True, environ = vars, ) - rule(name = name) \ No newline at end of file + rule( + name = name, + vars = vars, + ) diff --git a/franka-driver/BUILD.bazel b/franka-driver/BUILD.bazel index ed0fc4b..613e934 100644 --- a/franka-driver/BUILD.bazel +++ b/franka-driver/BUILD.bazel @@ -15,12 +15,12 @@ cc_binary( "@drake//multibody/plant", "@drake//multibody/parsing:parsing", "@gflags", - "@lcm", + "@lcm//lcm:lcm-static", "@libfranka_v5", ], data = [ "//models:franka_control_models", - "@drake//manipulation/models/franka_description:models", + "@drake_models//:franka_description", ], ) @@ -35,12 +35,12 @@ cc_binary( "@drake//multibody/plant", "@drake//multibody/parsing:parsing", "@gflags", - "@lcm", + "@lcm//lcm:lcm-static", "@libfranka_v4", ], data = [ "//models:franka_control_models", - "@drake//manipulation/models/franka_description:models", + "@drake_models//:franka_description", ], ) @@ -54,12 +54,12 @@ cc_binary( "@drake//lcmtypes:panda", "@drake//lcmtypes:schunk", "@gflags", - "@lcm", + "@lcm//lcm:lcm-static", "@libfranka_v5", ], data = [ "//models:franka_control_models", - "@drake//manipulation/models/franka_description:models", + "@drake_models//:franka_description", ], ) @@ -73,12 +73,12 @@ cc_binary( "@drake//lcmtypes:panda", "@drake//lcmtypes:schunk", "@gflags", - "@lcm", + "@lcm//lcm:lcm-static", "@libfranka_v4", ], data = [ "//models:franka_control_models", - "@drake//manipulation/models/franka_description:models", + "@drake_models//:franka_description", ], ) add_lint_tests() \ No newline at end of file diff --git a/franka-driver/franka_driver.cc b/franka-driver/franka_driver.cc index 0895ce1..606e607 100644 --- a/franka-driver/franka_driver.cc +++ b/franka-driver/franka_driver.cc @@ -380,9 +380,12 @@ class PandaDriver { DRAKE_THROW_UNLESS(command_->num_joint_position == 0); DRAKE_THROW_UNLESS(command_->num_joint_torque == 0); + // Check if command has expired (following drake-iiwa-driver pattern) + // We check time since receipt, not the message timestamp const int64_t now = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); - if (std::abs(now - command_->utime) > expire_usec_) { + std::chrono::system_clock::now().time_since_epoch()).count(); + const int64_t stale_utime = now - command_receipt_utime_; + if (stale_utime > expire_usec_) { drake::log()->warn("Resetting state velocity command to zero"); command_.reset(); command_prev_.reset(); @@ -432,9 +435,12 @@ class PandaDriver { DRAKE_THROW_UNLESS(command_->num_joint_velocity == 0); DRAKE_THROW_UNLESS(command_->num_joint_torque == 0); + // Check if command has expired (following drake-iiwa-driver pattern) + // We check time since receipt, not the message timestamp const int64_t now = std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count(); - if (std::abs(now - command_->utime) > expire_usec_) { + std::chrono::system_clock::now().time_since_epoch()).count(); + const int64_t stale_utime = now - command_receipt_utime_; + if (stale_utime > expire_usec_) { drake::log()->warn( "Leaving state position command at last known command"); command_.reset(); @@ -556,8 +562,8 @@ class PandaDriver { // Tested empirically. Still needs work! // TODO(eric.cousineau): Do more targeted testing using tools / // investigation from #9183. - kp.setConstant(1000.0); - kd.setConstant(45.0); + kp.setConstant(1000.0*FLAGS_torque_kp_scale); + kd.setConstant(45.0*FLAGS_torque_kd_scale); } else { SetGainsForJointStiffnessErrorToTorque(&kp, &kd); } @@ -685,6 +691,9 @@ class PandaDriver { const lcm::ReceiveBuffer*, const std::string&, const drake::lcmt_panda_command* command) { command_ = *command; + // Track receipt time (following drake-iiwa-driver pattern) + command_receipt_utime_ = std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count(); } void PublishRobotState(const franka::RobotState& state) { @@ -757,6 +766,7 @@ class PandaDriver { drake::lcmt_panda_status status_msg_{}; std::optional command_; std::optional command_prev_; + int64_t command_receipt_utime_{0}; Eigen::VectorXd coriolis_vector_; Eigen::MatrixXd inertia_matrix_; diff --git a/models/BUILD.bazel b/models/BUILD.bazel index 4d80b97..c1fbd84 100644 --- a/models/BUILD.bazel +++ b/models/BUILD.bazel @@ -2,9 +2,12 @@ filegroup( name = "franka_control_models", srcs = [ "add_franka_control.yaml", + "add_franka_control_with_frozen_hand.yaml", + "package.xml", + "panda_hand_frozen.urdf", ], data = [ - "@drake//manipulation/models/franka_description:models", + "@drake_models//:franka_description", ], visibility = ["//visibility:public"], ) \ No newline at end of file diff --git a/models/add_franka_control.yaml b/models/add_franka_control.yaml index b887a65..12e8436 100644 --- a/models/add_franka_control.yaml +++ b/models/add_franka_control.yaml @@ -1,7 +1,7 @@ directives: - add_model: name: panda - file: package://drake/manipulation/models/franka_description/urdf/panda_arm.urdf + file: package://drake_models/franka_description/urdf/panda_arm.urdf - add_weld: parent: world child: panda::panda_link0 \ No newline at end of file diff --git a/models/add_franka_control_with_frozen_hand.yaml b/models/add_franka_control_with_frozen_hand.yaml new file mode 100644 index 0000000..4825537 --- /dev/null +++ b/models/add_franka_control_with_frozen_hand.yaml @@ -0,0 +1,21 @@ +directives: +- add_model: + name: panda + file: package://drake_models/franka_description/urdf/panda_arm.urdf +- add_weld: + parent: world + child: panda::panda_link0 +- add_model: + name: panda_hand + file: package://driver_models/panda_hand_frozen.urdf + +- add_frame: + name: panda::hand_attach + X_PF: + base_frame: panda::panda_link8 + translation: [0, 0.00, 0.00] + rotation: !Rpy { deg: [0.0, 0.0, -45.0]} + +- add_weld: + parent: panda::hand_attach + child: panda_hand::panda_hand \ No newline at end of file diff --git a/models/package.xml b/models/package.xml new file mode 100644 index 0000000..e32b4ef --- /dev/null +++ b/models/package.xml @@ -0,0 +1,8 @@ + + + driver_models + 0.0.1 + Drake Franka driver model files + Your Name + TODO + \ No newline at end of file diff --git a/models/panda_hand_frozen.urdf b/models/panda_hand_frozen.urdf new file mode 100644 index 0000000..46b1967 --- /dev/null +++ b/models/panda_hand_frozen.urdf @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/lint/BUILD.bazel b/tools/lint/BUILD.bazel index 4de2499..749dc2b 100644 --- a/tools/lint/BUILD.bazel +++ b/tools/lint/BUILD.bazel @@ -2,25 +2,6 @@ load("//tools/lint:lint.bzl", "add_lint_tests") -py_binary( - name = "buildifier", - srcs = ["buildifier.py"], - data = ["//:.bazelproject"], - deps = ["@drake//tools/lint:buildifier"], -) - -py_binary( - name = "clang-format-includes", - testonly = 1, - srcs = ["clang_format_includes.py"], - data = [ - "//:.bazelproject", - "//:.clang-format", - ], - main = "clang_format_includes.py", - deps = [ - "@drake//tools/lint:clang-format-includes", - ], -) +exports_files(["buildifier.py"]) add_lint_tests() diff --git a/tools/lint/buildifier.py b/tools/lint/buildifier.py index 4145939..c1e7421 100644 --- a/tools/lint/buildifier.py +++ b/tools/lint/buildifier.py @@ -1,4 +1,34 @@ -from drake.tools.lint.buildifier import main +#!/usr/bin/env python3 +"""Wrapper script for buildifier that provides helpful error messages.""" + +import subprocess +import sys + +def main(): + # Find the actual buildifier binary (passed as first argument by Bazel) + if len(sys.argv) < 2: + print("Error: buildifier binary path not provided", file=sys.stderr) + return 1 + + buildifier_bin = sys.argv[1] + args = sys.argv[2:] + + # Run buildifier + result = subprocess.run([buildifier_bin] + args, capture_output=False) + + if result.returncode != 0: + # Print helpful message on failure + print("\n" + "="*80, file=sys.stderr) + print("BUILDIFIER FORMATTING FAILED", file=sys.stderr) + print("="*80, file=sys.stderr) + print("\nYour Bazel files need to be reformatted.", file=sys.stderr) + print("\nTo fix this, run:", file=sys.stderr) + print(" bazel run @buildifier_prebuilt//:buildifier -- -r $(pwd)", file=sys.stderr) + print("\nOr for a specific file:", file=sys.stderr) + print(" bazel run @buildifier_prebuilt//:buildifier -- path/to/file.bazel", file=sys.stderr) + print("\n" + "="*80 + "\n", file=sys.stderr) + + return result.returncode if __name__ == "__main__": - main(workspace_name="drake_franka_driver") + sys.exit(main()) \ No newline at end of file diff --git a/tools/lint/lint.bzl b/tools/lint/lint.bzl index 02c0635..1524156 100644 --- a/tools/lint/lint.bzl +++ b/tools/lint/lint.bzl @@ -1,3 +1,19 @@ -load("@drake//tools/lint:lint.bzl", drake_add_lint_tests = "add_lint_tests") +load("@rules_python//python:py_test.bzl", "py_test") -add_lint_tests = drake_add_lint_tests +def _bazel_lint(): + files = native.glob(["*.bazel", "*.bzl"], allow_empty = True) + if len(files) == 0: + return + buildifier = "@buildifier_prebuilt//:buildifier" + locations = ["$(locations %s)" % f for f in files] + py_test( + name = "buildifier_lint", + srcs = ["//tools/lint:buildifier.py"], + main = "buildifier.py", + data = files + [buildifier], + args = ["$(location %s)" % buildifier, "-mode=check"] + locations, + tags = ["buildifier_lint", "lint"], + ) + +def add_lint_tests(): + _bazel_lint() diff --git a/tools/workspace/BUILD.bazel b/tools/workspace/BUILD.bazel new file mode 100644 index 0000000..545d032 --- /dev/null +++ b/tools/workspace/BUILD.bazel @@ -0,0 +1,3 @@ +# Empty BUILD file to make this directory a package for module extensions. + +exports_files(["external_repositories.bzl"]) diff --git a/tools/workspace/drake_models/BUILD.bazel b/tools/workspace/drake_models/BUILD.bazel new file mode 100644 index 0000000..8820b79 --- /dev/null +++ b/tools/workspace/drake_models/BUILD.bazel @@ -0,0 +1,3 @@ +# Empty BUILD file to make this directory a package. + +exports_files(["repository.bzl"]) \ No newline at end of file diff --git a/tools/workspace/drake_models/repository.bzl b/tools/workspace/drake_models/repository.bzl new file mode 100644 index 0000000..f824fb8 --- /dev/null +++ b/tools/workspace/drake_models/repository.bzl @@ -0,0 +1,19 @@ +# -*- mode: python -*- +# vi: set ft=python : + +load( + "@drake//tools/workspace:github.bzl", + "github_archive", +) + +def drake_models_repository( + name, + mirrors = None): + github_archive( + name = name, + repository = "RobotLocomotion/models", + commit = "68e906556069eab9896f9006b6bf17a32b8b0f1d", + sha256 = "bad9de839fc61447cecaf2abc8f8df7afe77e5ab4fbdeb28d9cfec0a8338b1fa", + build_file = "@drake//tools/workspace/drake_models:package.BUILD.bazel", + mirrors = mirrors, + ) \ No newline at end of file diff --git a/tools/workspace/external_repositories.bzl b/tools/workspace/external_repositories.bzl new file mode 100644 index 0000000..15911e6 --- /dev/null +++ b/tools/workspace/external_repositories.bzl @@ -0,0 +1,23 @@ +# -*- mode: python -*- +# vi: set ft=python : + +"""Module extension for external dependencies.""" + +load("@drake//tools/workspace:mirrors.bzl", "DEFAULT_MIRRORS") +load("//tools/workspace/drake_models:repository.bzl", "drake_models_repository") +load("//tools/workspace/libfranka_v4:repository.bzl", "libfranka_v4_repository") +load("//tools/workspace/libfranka_v5:repository.bzl", "libfranka_v5_repository") +load("//tools/workspace/libfranka_common_v4:repository.bzl", "libfranka_common_v4_repository") +load("//tools/workspace/libfranka_common_v5:repository.bzl", "libfranka_common_v5_repository") + +def _external_repositories_impl(ctx): + """Implementation of the external_repositories module extension.""" + drake_models_repository(name = "drake_models", mirrors = DEFAULT_MIRRORS) + libfranka_v4_repository(name = "libfranka_v4", mirrors = DEFAULT_MIRRORS) + libfranka_v5_repository(name = "libfranka_v5", mirrors = DEFAULT_MIRRORS) + libfranka_common_v4_repository(name = "libfranka_common_v4", mirrors = DEFAULT_MIRRORS) + libfranka_common_v5_repository(name = "libfranka_common_v5", mirrors = DEFAULT_MIRRORS) + +external_repositories = module_extension( + implementation = _external_repositories_impl, +) \ No newline at end of file diff --git a/tools/workspace/libfranka_common_v4/repository.bzl b/tools/workspace/libfranka_common_v4/repository.bzl index 7cad7f6..2b66a25 100644 --- a/tools/workspace/libfranka_common_v4/repository.bzl +++ b/tools/workspace/libfranka_common_v4/repository.bzl @@ -11,7 +11,7 @@ def libfranka_common_v4_repository( mirrors = None): github_archive( name = name, - repository = "frankaemika/libfranka-common", + repository = "frankarobotics/libfranka-common", commit = "e6aa0fc210d93fe618bfd8956829a264d5476ba8", sha256 = "721fffe11c5dec6735e191c2f08e58de3828d05ea25c3901c1940cd30a226509", # noqa build_file = "//tools/workspace/libfranka_common_v4:package.BUILD.bazel", # noqa diff --git a/tools/workspace/libfranka_common_v5/repository.bzl b/tools/workspace/libfranka_common_v5/repository.bzl index 8b3ac12..b55a23e 100644 --- a/tools/workspace/libfranka_common_v5/repository.bzl +++ b/tools/workspace/libfranka_common_v5/repository.bzl @@ -12,8 +12,8 @@ def libfranka_common_v5_repository( github_archive( name = name, repository = "frankaemika/libfranka-common", - commit = "ea26b89aa302b1456c825fb622b414bb3b1013ce", - sha256 = "2f8c3dc6a63ab4bcb8ab770b4f39105a4a4fd64bdcd2c98755b7c51754be1ead", # noqa + commit = "cd38d0ec300b7e6864407d85d1e88e2fba31ccd5", + sha256 = "0696297f235dc63c014232acde602aa9ad59bf8630d5b9901b32ac79f4d2dee2", # noqa build_file = "//tools/workspace/libfranka_common_v5:package.BUILD.bazel", # noqa mirrors = mirrors, ) diff --git a/tools/workspace/libfranka_v4/repository.bzl b/tools/workspace/libfranka_v4/repository.bzl index c1000c1..3b4f701 100644 --- a/tools/workspace/libfranka_v4/repository.bzl +++ b/tools/workspace/libfranka_v4/repository.bzl @@ -9,9 +9,17 @@ load( def libfranka_v4_repository( name, mirrors = None): + """ + Provides libfranka v4 (0.9.0) for FE3 robots with firmware v4.x. + + This is the legacy version for older Panda robots. Use libfranka_v5 + for newer FR3 robots instead. + + Commit: c452ba20397cde846fe2e48d0be94b522ef88dac (v0.9.0 release) + """ github_archive( name = name, - repository = "frankaemika/libfranka", + repository = "frankarobotics/libfranka", commit = "c452ba20397cde846fe2e48d0be94b522ef88dac", sha256 = "f0616d01ef09aa1d5948d385a6cfe18c514bc6e0921e4fac97ada7262b8722e4", # noqa build_file = "//tools/workspace/libfranka_v4:package.BUILD.bazel", # noqa diff --git a/tools/workspace/libfranka_v5/package.BUILD.bazel b/tools/workspace/libfranka_v5/package.BUILD.bazel index 739b45b..5dd1ea2 100644 --- a/tools/workspace/libfranka_v5/package.BUILD.bazel +++ b/tools/workspace/libfranka_v5/package.BUILD.bazel @@ -8,12 +8,22 @@ cc_library( srcs = glob([ "src/*.h", "src/*.cpp", + "src/**/*.h", + "src/**/*.hpp", + "src/**/*.cpp", + ]), + hdrs = glob([ + "include/franka/*.h", + "include/franka/**/*.hpp", ]), - hdrs = glob(["include/franka/*.h"]), includes = ["include"], deps = [ "@eigen", "@libfranka_common_v5", + "@pinocchio", "@poco", ], + copts = [ + "-std=c++17", + ], ) diff --git a/tools/workspace/libfranka_v5/repository.bzl b/tools/workspace/libfranka_v5/repository.bzl index 4ff4d7d..34912e9 100644 --- a/tools/workspace/libfranka_v5/repository.bzl +++ b/tools/workspace/libfranka_v5/repository.bzl @@ -9,11 +9,21 @@ load( def libfranka_v5_repository( name, mirrors = None): + """ + Provides libfranka v5 (~0.15.0) for FR3 robots with firmware v5.x. + + This version includes: + - Support for FR3 robot hardware + - Pinocchio integration for dynamics + - Modern API with improved real-time control + + Commit: faaefaa0ff17a812b8a9bc4ac1ed7c353c46064d (post-0.15.0) + """ github_archive( name = name, - repository = "frankaemika/libfranka", - commit = "4f9e3cc666e42d267f1ab566869c4f4c552e5b57", - sha256 = "ba546b58ff211c7cc41cda2a2067ba200983e49304f5ddccf9dbbb55ebfef7a4", # noqa + repository = "frankarobotics/libfranka", + commit = "faaefaa0ff17a812b8a9bc4ac1ed7c353c46064d", + sha256 = "d733299b6a88762405cb56fce605d3f98ab2d78ecd6464ee1b255017e6ed903b", # noqa build_file = "//tools/workspace/libfranka_v5:package.BUILD.bazel", # noqa mirrors = mirrors, ) diff --git a/tools/workspace/poco/package.BUILD.bazel b/tools/workspace/poco/package.BUILD.bazel index 48eafab..cf4aadc 100644 --- a/tools/workspace/poco/package.BUILD.bazel +++ b/tools/workspace/poco/package.BUILD.bazel @@ -3,12 +3,19 @@ cc_library( name = "poco", - srcs = glob(["lib/libPoco*.so", "lib/*/libPoco*.so"]), + srcs = glob( + [ + "lib/libPoco*.so", + "lib/x86_64-linux-gnu/libPoco*.so", + "lib/aarch64-linux-gnu/libPoco*.so", + ], + allow_empty = True, + ), hdrs = glob([ "include/Poco/**/*.h", "include/Poco/*.h", ]), - includes = ["include/Poco"], + includes = ["include"], visibility = ["//visibility:public"], ) diff --git a/tools/workspace/poco/repository.bzl b/tools/workspace/poco/repository.bzl index e368ac1..cb1b8a4 100644 --- a/tools/workspace/poco/repository.bzl +++ b/tools/workspace/poco/repository.bzl @@ -1,10 +1,16 @@ # -*- mode: python -*- # vi: set ft=python : -def poco_repository( - name): - native.new_local_repository( - name = name, - path = "/usr", - build_file = "//tools/workspace/poco:package.BUILD.bazel", +def _poco_repository_impl(repository_ctx): + # Symlink the contents of /usr directly into the repository root + repository_ctx.symlink("/usr/include", "include") + repository_ctx.symlink("/usr/lib", "lib") + repository_ctx.symlink( + Label("//tools/workspace/poco:package.BUILD.bazel"), + "BUILD.bazel", ) + +poco_repository = repository_rule( + implementation = _poco_repository_impl, + local = True, +)