Skip to content

Enhance impedance control - #79

Merged
TimSchneider42 merged 0 commit into
TimSchneider42:masterfrom
nickswalker:enhance-impedance-control
Jul 13, 2026
Merged

Enhance impedance control#79
TimSchneider42 merged 0 commit into
TimSchneider42:masterfrom
nickswalker:enhance-impedance-control

Conversation

@nickswalker

@nickswalker nickswalker commented Mar 27, 2026

Copy link
Copy Markdown
Collaborator

Expand the impedance motion stack for both joint-space and Cartesian torque control. Adds tracking/reference-handle based impedance motions, introduces nullspace posture control for Cartesian impedance, adds joint-limit repulsion and shared torque safety utilities, and updates the Python API and docs accordingly.

Joint-space impedance

  • Add joint impedance motions with joint-limit repulsion.
  • Add joint impedance tracking via live reference updates.
  • Add optional joint friction compensation (off by default) for more transparent
    zero-stiffness kinesthetic teaching.
  • Add configuration-space error clipping and safety hardening.

Cartesian impedance

  • Refactor the Cartesian impedance API; rename the base class ImpedanceMotion
    CartesianImpedanceBase, now that there is a distinct JointImpedanceMotion.
  • Add tracking/moving Cartesian references.
  • Move target_type into fixed-target Cartesian impedance motions.
  • Add Cartesian nullspace posture control (with dynamic nullspace gains).
  • Add Cartesian impedance acceleration feedforward support.
  • Apply the same joint-limit repulsion, friction compensation as joint impedance, and task space error clipping.

Shared / API

  • Runtime-adjustable impedance gains and damping via reference handles.
  • Add TorqueStop for cleanly ending impedance motions.
  • Expand README/API docs for the impedance motion interfaces (previously the
    ImpedanceMotion types weren't documented at all).

Examples

  • joint_impedance_tracker.py, cartesian_impedance_tracker.py

Opening to see if anyone has feedback.

@TimSchneider42

Copy link
Copy Markdown
Owner

Hi,

I think this PR adds some really important functionality, but I will need some time to review it. I will get back to you once I have taken a look at it. Thank you very much for the PR, though!

Best,
Tim

@nickswalker

nickswalker commented Mar 28, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for your willingness to take a look! Here are the two new Python examples running on an FR3.

manual_guidance_joint_impedance.py demonstrates setting joint 6 to be very stiff while leaving the others compliant (a la franka_interactive_controllers), which can sometimes be useful when doing kinesthetic teaching

trim.B82E2E43-2B00-4CC8-8B18-B52AE9AD1165.MOV

cartesian_virtual_fixture.py demonstrates a Python-side loop updating the cartesian reference for the cartesian impedance controller, allowing the user to push the robot along a vertical axis, and resisting all other motion.

trim.247AD8D4-340B-481A-AF0C-A6783A8653C9.MOV

@nickswalker
nickswalker force-pushed the enhance-impedance-control branch from f0e71ab to e776619 Compare March 28, 2026 01:12
@nickswalker
nickswalker marked this pull request as ready for review March 28, 2026 01:13
@Asunatan

Copy link
Copy Markdown

Hello, thank you for sharing this work—the impedance control shown in the video looks very smooth and promising.

I'm relatively new to robotics and have been evaluating open-source Python libraries for controlling the Franka Emika Panda. Currently, I'm using Deoxys, but I've observed noticeable jitter when performing impedance control, which affects trajectory tracking and force adjustment. I've also looked at FrankaPy, but it doesn't seem to provide a dedicated impedance control interface. Given the performance your library demonstrates, I'm very much looking forward to it…

@Brunch-Life

Copy link
Copy Markdown

It's quite a good feature! I'm using it to use gello control franka use joint implance control!

@Brunch-Life

Copy link
Copy Markdown

waiting for this to be approved!

@nickswalker

Copy link
Copy Markdown
Collaborator Author

I set the fork to compile and release wheels in the meantime: https://github.com/nickswalker/franky/releases
Also added 0.21.1 libfranka builds, as those are what the videos were recorded with.

@TimSchneider42

Copy link
Copy Markdown
Owner

Hey guys,

Sorry for the delay in merging this. I am currently super busy as I am pushing for NeurIPS (deadline is on the 6th of May). I cannot promise to merge this before the deadline, as I would like to review it thoroughly. However, I will try my best to do it as soon as I can.

Best,
Tim

@nickswalker
nickswalker force-pushed the enhance-impedance-control branch 2 times, most recently from f168fd3 to 46852c7 Compare April 17, 2026 03:36
@hugohadfield

Copy link
Copy Markdown

Really looking forward to seeing this land!

Brunch-Life added a commit to Brunch-Life/franky that referenced this pull request May 13, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>
Brunch-Life added a commit to Brunch-Life/franky that referenced this pull request May 13, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>
nickswalker pushed a commit to nickswalker/franky that referenced this pull request May 13, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>
@TimSchneider42

Copy link
Copy Markdown
Owner

Sorry to keep you waiting for so long. I will have some time next week to review the code and merge the PR.

nickswalker pushed a commit to nickswalker/franky that referenced this pull request May 23, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>
@nickswalker
nickswalker force-pushed the enhance-impedance-control branch from cdc7abb to 5b433be Compare May 25, 2026 03:55
@nickswalker

Copy link
Copy Markdown
Collaborator Author

We've been using the JointImpedenceTracker in 0 stiffness for collecting kinesthetic demonstrations lately and noticed that the joints aren't quite transparent. Went ahead and incorporated a simple friction compensation feedforward term (off by default), as I expect this will be a common use case.

@TimSchneider42
TimSchneider42 force-pushed the master branch 2 times, most recently from 76b2e71 to 7eff7f0 Compare June 25, 2026 11:05
@nickswalker
nickswalker force-pushed the enhance-impedance-control branch 2 times, most recently from 48e909b to 38229e7 Compare June 26, 2026 00:49
nickswalker pushed a commit to nickswalker/franky that referenced this pull request Jun 26, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>
nickswalker pushed a commit to nickswalker/franky that referenced this pull request Jun 26, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>
@nickswalker
nickswalker force-pushed the enhance-impedance-control branch from 38229e7 to f6b338b Compare June 28, 2026 20:37
nickswalker added a commit to nickswalker/franky that referenced this pull request Jun 28, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>

# Conflicts:
#	.github/workflows/build_wheels.yml
@nickswalker
nickswalker force-pushed the enhance-impedance-control branch from f6b338b to 361ef4e Compare June 28, 2026 20:48
nickswalker added a commit to nickswalker/franky that referenced this pull request Jun 28, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>

# Conflicts:
#	.github/workflows/build_wheels.yml
nickswalker added a commit to nickswalker/franky that referenced this pull request Jul 7, 2026
The fork's release_wheels workflow produces a wheel with the same
file name and version (1.1.3) as the upstream franky-control on PyPI.
When users run `pip install --find-links <fork release> franky-control`,
pip sees both sources and may pick the upstream PyPI wheel -- which is
missing the enhance-impedance-control changes (PR TimSchneider42#79).

Patch VERSION in CI to '1.1.3+impedance.libfranka.<ver>' so the
produced wheel carries a PEP 440 local-version label that does not
exist on PyPI. pip then prefers the local-label wheel from this
fork unambiguously.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Brunch-Life <brunchlife@hotmail.com>

# Conflicts:
#	.github/workflows/build_wheels.yml
@TimSchneider42
TimSchneider42 force-pushed the master branch 4 times, most recently from 343c4ab to 87bf057 Compare July 7, 2026 16:08
@nickswalker
nickswalker force-pushed the enhance-impedance-control branch 2 times, most recently from effad6f to 03cc84e Compare July 8, 2026 01:11
@nickswalker

nickswalker commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator Author

I've done some characterization of the tracking error for a simple Lissajous:

trim.8134BB07-6CD7-4ED5-A20F-9CD1B2D1E48B.MOV

Tracking error at different stiffnesses, trajectory speeds (as percentage of max cartesian or joint vel), with and without friction compensation:

tracking_metrics_cartesian tracking_metrics_joint_ik_hybrid

These controllers have quite some surface area, which might make it hard to be confident that they're ready to go. I think some further examples that exercise them might help with this? This tracker example covers the basic python usage of the trackers with stiffness gains, friction params, inertial feedforward terms. But there's currently nothing that exercises the cartesian nullspace tasks or the simpler non-tracker motions...

@TimSchneider42

Copy link
Copy Markdown
Owner

Hey @nickswalker, just a quick heads-up. I merged your changes into the master branch yesterday and added some refactoring. Unfortunately, I don't have time today to give you a full summary of my changes. Just want to let you know that with your recent edits, we are running danger to diverge. I will have more time to look into this on Monday and give you a full account of my refactoring.

Btw, would you consider becoming a co-maintainer of franky? I think I could use some support, and I really appreciate the effort you have already put into this project!

@nickswalker nickswalker closed this Jul 9, 2026
@nickswalker
nickswalker force-pushed the enhance-impedance-control branch from 03cc84e to 7c6a3c6 Compare July 9, 2026 13:29
@nickswalker nickswalker reopened this Jul 9, 2026
@nickswalker
nickswalker force-pushed the enhance-impedance-control branch 2 times, most recently from 9ccdee7 to 2707962 Compare July 9, 2026 18:28
@nickswalker

nickswalker commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator Author

Thanks for doing the merge! Happy to help maintain.

I rebased on your refactoring. The remaining items are not as important as what has already been merged:

  • Changed the cartesian interface to accept full stiffness/damping matrices, as I see that most comparable implementations support this
  • Add cartesian gain shaping to the joint impedance controller. Fairly close copy of the implementation in fairo's Polymetis. This lets one eek out slightly better trajectory tracking performance by running IK before hand then running with both q and cartesian reference (second set of plots from above).
  • Manipulability nullspace task
  • A motion for stopping under torque control (parallel to the other stopmotions)
  • A raft of ~one line fixes in the last few commits

@nickswalker

Copy link
Copy Markdown
Collaborator Author

It seems that the new TorqueStopMotion hangs forever in the sim tests. Perhaps the semantics for motion termination are different for torque motions than position/velocity motions in the robot/libfranka protocol.

@TimSchneider42

Copy link
Copy Markdown
Owner

Maybe you already saw, but here is a brief summary of my changes:

  • Replaced the double-buffered lock-free handles with a triple-buffered scheme, because the former had a race condition (I saw later that you also fixed that in a separate commit)
  • Made these buffers private and changed the API to just have a method on the motion for setting new gains/references
  • Removed ExponentialImpedanceMotion because I think it does not really serve a purpose anymore, and aligned the implementation of Cartesian and joint impedance controllers a bit.
  • Dropped EIGEN_MAKE_ALIGNED_OPERATOR_NEW because c++17 and upwards do not need it anymore.
  • Added type hints to tracker.py
  • Moved the tutorial into a separate file as the README was getting very long by this point. Though I think we need to improve the documentation format at some point.

I will look into the TorqueStopMotion issue now.

@TimSchneider42
TimSchneider42 merged commit 2707962 into TimSchneider42:master Jul 13, 2026
31 of 36 checks passed
@TimSchneider42

Copy link
Copy Markdown
Owner

@nickswalker, I just merged the remaining changes. The TorqueStopMotion issue was caused by a problem inside franky-sim which is now fixed.

If you are happy with the state of the code as it is, I think we can soon release it to PyPi.

Again, thanks a lot for the PR!

@nickswalker
nickswalker deleted the enhance-impedance-control branch July 13, 2026 17:20
@nickswalker

Copy link
Copy Markdown
Collaborator Author

Great! The library users in our lab will be exercising these controllers and the desk API changes throughout the week, so I'd deem it releasable if they don't run into problems.

@TimSchneider42

Copy link
Copy Markdown
Owner

Sounds good to me

@TimSchneider42

Copy link
Copy Markdown
Owner

@nickswalker, bit of a random question, but would you be fine with switching franky to an MIT license? I would like to lower the legal barriers to using this library as much as possible, and I think now would be a good time for updating the license.

@nickswalker

Copy link
Copy Markdown
Collaborator Author

Yes, I would endorse the next version being released under a permissive license. A quick look at git blame and it seems that the only other substantial contribution came from the original author. My understanding is we'd need their permission to change the license of code that they own the copyright to. Perhaps you could tag him in a new issue to obtain his consent?

@hugohadfield

Copy link
Copy Markdown

It would be extremely helpful to release this package under a more permissive license mostly because legal review inside companies (even for research only code) can sometimes be extremely slow for anything other than MIT licensed code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Smooth 30 Hz joint position control (jerky motion and gripper interference) Franky and Torque control and Libfranka?

5 participants