Skip to content

build(deps): bump the python group across 1 directory with 68 updates#2870

Open
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/uv/python-a6c608c5c6
Open

build(deps): bump the python group across 1 directory with 68 updates#2870
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/uv/python-a6c608c5c6

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jul 11, 2026

Copy link
Copy Markdown
Contributor

Bumps the python group with 66 updates in the / directory:

Package From To
pin 3.8.0 4.0.0
pydantic 2.12.5 2.13.4
packaging 25.0 26.2
plum-dispatch 2.5.7 2.9.0
structlog 25.5.0 26.1.0
opencv-contrib-python 4.13.0.92 5.0.0.93
pydantic-settings 2.12.0 2.14.2
textual 3.7.1 8.2.8
terminaltexteffects 0.12.2 0.15.0
typer 0.23.1 0.26.8
numba 0.63.1 0.66.0
rerun-sdk 0.32.0 0.33.1
protobuf 6.33.5 7.35.1
cryptography 46.0.5 49.0.0
python-multipart 0.0.27 0.0.32
ipykernel 7.2.0 7.3.0
timm 1.0.24 1.0.27
open-clip-torch 3.2.0 3.3.0
gdown 6.0.0 6.1.0
tensorboard 2.20.0 2.21.0
xarm-python-sdk 1.17.3 1.18.4
portal 3.7.4 3.8.1
pyarrow 23.0.0 24.0.0
langchain-core 1.3.3 1.4.8
langchain-openai 1.1.6 1.3.3
langchain-huggingface 1.2.0 1.2.2
langchain-ollama 1.0.1 1.1.0
ollama 0.6.1 0.6.2
fastapi 0.129.0 0.139.0
sse-starlette 3.2.0 3.4.5
uvicorn 0.40.0 0.50.0
soundfile 0.13.1 0.14.0
ultralytics 8.4.14 8.4.87
pillow 12.2.0 12.3.0
lap 0.5.12 0.5.13
transformers[torch] 4.53.3 5.13.0
moondream 0.2.0 1.3.0
omegaconf 2.3.0 2.3.1
hydra-core 1.3.2 1.3.3
cyclonedds 0.10.5 11.0.1
mcap 1.3.1 1.4.0
pyrealsense2-extended 2.58.1.10581.post1 2.58.2.10647.post1
matplotlib 3.10.8 3.10.9
onnxruntime 1.24.1 1.24.3
cupy-cuda12x 13.6.0 14.1.1
onnxruntime-gpu 1.24.1 1.24.3
mujoco 3.5.0 3.10.0
gtsam-extended 4.3a1.post1 4.3a1.post202607020747
reportlab 4.5.0 5.0.0
ruff 0.14.3 0.15.20
torch 2.10.0 2.12.1
pytest 8.3.5 9.1.1
pytest-asyncio 0.26.0 1.4.0
pytest-mock 3.15.0 3.15.1
pytest-env 1.1.5 1.6.0
coverage 7.13.4 7.15.0
pre-commit 4.2.0 4.6.0
py-spy 0.4.1 0.4.2
maturin 1.13.3 1.14.1
python-lsp-ruff 2.3.0 2.3.1
mypy 1.19.0 2.1.0
ipython 8.38.0 8.39.0
python-socketio 5.16.1 5.16.3
types-pyyaml 6.0.12.20250915 6.0.12.20260518
types-reportlab 4.5.0.20260509 4.5.1.20260521
types-requests 2.32.4.20260107 2.33.0.20260518

Updates pin from 3.8.0 to 4.0.0

Changelog

Sourced from pin's changelog.

[4.0.0] - 2026-04-13

Highlights

  • lcaba algorithm:
    • Compute forward dynamics for constrained system with closed kinematics loops
    • Python example here
  • New constraint API:
    • PointContactConstraintModelTpl, PointAnchorConstraintModelTpl, FrameAnchorConstraintModelTpl, JointLimitConstraintModelTpl and JointFrictionConstraintModelTpl constraint models
    • Each constraint model is associated to its own constraint data
    • Variants ConstraintModelTpl/ConstraintDataTpl encapsulate all constraints models and data
    • Delassus operator API: DelassusOperatorDenseTpl, DelassusOperatorSparseTpl, DelassusOperatorCholeskyExpressionTpl, DelassusOperatorRigidBodyTpl
    • These operators are tightly linked to the new constraints API All these operators compute the same mathematical operator $J M^{-1} J^T$ ($J$ is the constraints jacobian, $M^{-1}$ is the inverse of the mass matrix), but with different algorithms and internal optimizations
  • ADMMConstraintSolverTpl and PGSConstraintSolverTpl algorithms:
    • Solve constrained dynamics expressed with the new constraint API
    • Python examples here and here. These examples show how to use each constraint model, how to build a constraint problem, how to compute the associated Delassus operator and how to solve it
  • New header convention
    • Introduce omnibus headers:
      • pinocchio/math.hpp
      • pinocchio/spatial.hpp
      • pinocchio/mutlibody.hpp
      • ...

Added

  • Add lcaba algorithm in pinocchio/algorithm/loop-constrained-aba.hpp
    • Compute forward dynamics for constrained system with closed kinematics loops
  • Add computeJointMinimalOrdering in pinocchio/constraints.hpp
    • Compute joint processing order for lcaba
  • Add new constraint API in pinocchio/constraints.hpp
    • PointContactConstraintModel: models a unilateral contact constraint with coulomb friction cone
    • PointAnchorConstraintModel: models a point-wise equality constraint (bilateral constraint)
    • FrameAnchorConstraintModel: models a frame-wise equality constraint (bilateral constraint)
    • JointLimitConstraintModel: models a component-wise joint limit lower/upper bound constraint
    • JointFrictionConstraintModel: models a component-wise joint friction lower/upper bound constraint
  • Add new Delassus API in pinocchio/algorithm/delassus.hpp
  • Add ADMMConstraintSolverTpl in pinocchio/algorithm/solvers/admm-solver.hpp
    • Solve constrained dynamics using an ADMM algorithm
  • Add PGSConstraintSolverTpl in pinocchio/algorithm/solvers/pgs-solver.hpp
    • Solve constrained dynamics using a projected Gauss Siedel algorithm
  • Add new functions in pinocchio/multibody/liegroup.hpp
    • tangentMap: transforms a configuration variation into a small variation expressed in the parametric space
    • tangentMapProduct and tangentMapTransport: apply tangentMap while exploiting sparsity
  • Add mimic joint support for all Lie group related algorithms
  • Add new methods to JointModelBase:
    • jointQrows and jointQcols that make selections of size NQ
    • jointQVMap that make selections of size NQ x NV
    • lieGroup that returns the Lie group instance associated to a joint

... (truncated)

Commits

Updates pydantic from 2.12.5 to 2.13.4

Release notes

Sourced from pydantic's releases.

v2.13.4 2026-05-06

v2.13.4 (2026-05-06)

What's Changed

Packaging

Fixes

Full Changelog: pydantic/pydantic@v2.13.3...v2.13.4

v2.13.3 2026-04-20

v2.13.3 (2026-04-20)

What's Changed

Fixes

Full Changelog: pydantic/pydantic@v2.13.2...v2.13.3

v2.13.2 2026-04-17

v2.13.2 (2026-04-17)

What's Changed

Fixes

  • Fix ValidationInfo.field_name missing with model_validate_json() by @​Viicos in #13084

Full Changelog: pydantic/pydantic@v2.13.1...v2.13.2

v2.13.1 2026-04-15

v2.13.1 (2026-04-15)

What's Changed

Fixes

Full Changelog: pydantic/pydantic@v2.13.0...v2.13.1

v2.13.0 2026-04-13

... (truncated)

Changelog

Sourced from pydantic's changelog.

v2.13.4 (2026-05-06)

GitHub release

What's Changed

Packaging

Fixes

v2.13.3 (2026-04-20)

GitHub release

What's Changed

Fixes

v2.13.2 (2026-04-17)

GitHub release

What's Changed

Fixes

  • Fix ValidationInfo.field_name missing with model_validate_json() by @​Viicos in #13084

v2.13.1 (2026-04-15)

GitHub release

What's Changed

Fixes

v2.13.0 (2026-04-13)

GitHub release

The highlights of the v2.13 release are available in the blog post.

... (truncated)

Commits
  • cf67d4b Fix linting
  • f0d8a21 Prepare release v2.13.4
  • 5e3fe1d Check for pydantic tag pattern in CI
  • 7f9edcc Document tagging conventions
  • b46a0c9 Adapt pydantic-core linker flags on macOS
  • 50629c8 Update to PyPy 7.3.22
  • 8522ebb Preserve RootModel core metadata
  • a37f3af Adapt MISSING sentinel test to work with unreleased typing_extensions ver...
  • 909259a Remove Logfire example in documentation
  • 2c4174c Bump libc from 0.2.155 to 0.2.185
  • Additional commits viewable in compare view

Updates packaging from 25.0 to 26.2

Release notes

Sourced from packaging's releases.

26.2

What's Changed

Fixes:

Documentation:

Internal:

New Contributors

Full Changelog: pypa/packaging@26.1...26.2

26.1

Features:

Behavior adaptations:

... (truncated)

Changelog

Sourced from packaging's changelog.

26.2 - 2026-04-24


Fixes:
  • Fix incorrect sysconfig var name for pyemscripten in (:pull:1160)
  • Make Version, Specifier, SpecifierSet, Tag, Marker, and Requirement pickle-safe
    and backward-compatible with pickles created in 25.0-26.1 (including references to the removed
    packaging._structures module) (:pull:1163, :pull:1168, :pull:1170, :pull:1171)
  • Re-export ExceptionGroup in metadata for now in (:pull:1164)

Documentation:

  • Add errors section and fix missing details in (:pull:1159)
  • Document our property-based test suite in (:pull:1167)
  • Fix a DirectUrl typo in (:pull:1169)
  • Add example of is_unsatisfiable in (:pull:1166)

Internal:

  • Enable the auditor persona on zizmor in (:pull:1158)
  • Test new pickle guarantees in (:pull:1174)
  • Use new native ReadTheDocs uv integration in (:pull:1175)

26.1 - 2026-04-14

Features:

  • PEP 783: add handling for Emscripten wheel tags in (:pull:804) (old name used in implementation, fixed in next release)
  • PEP 803: add handling for the abi3.abi3t free-threading tag in (:pull:1099)
  • PEP 735: add packaging.dependency_groups module, based on the dependency-groups package in (:pull:1065)
  • Add the packaging.direct_url module in (:pull:944)
  • Add the packaging.errors module in (:pull:1071)
  • Add SpecifierSet.is_unsatisfiable using ranges (new internals that will be expanded in future versions) in (:pull:1119)
  • Add create_compatible_tags_selector to select compatible tags in (:pull:1110)
  • Add a key argument to SpecifierSet.filter() in (:pull:1068)
  • Support & and | for Marker's in (:pull:1146)
  • Normalize Version.__replace__ and add Version.from_parts in (:pull:1078)
  • Add an option to validate compressed tag set sort order in parse_wheel_filename in (:pull:1150)

Behavior adaptations:

  • Narrow exclusion of pre-releases for <V.postN to match spec in (:pull:1140)
  • Narrow exclusion of post-releases for >V to match spec in (:pull:1141)
  • Rename format_full_version to _format_full_version to make it visibly private in (:pull:1125)
  • Restrict local version to ASCII in (:pull:1102)

Pylock (PEP 751) updates:

... (truncated)

Commits

Updates plum-dispatch from 2.5.7 to 2.9.0

Release notes

Sourced from plum-dispatch's releases.

v2.9.0

  • Support union aliases in Python 3.14 and later (@​nstarman).

v2.8.0

Starting this release, Plum will be available on PyPI as both plum-dispatch and plum.

v2.7.1

  • Add faithful keyword to ModuleType.

v2.7.0

Note: All imports should now go through plum directly! That is, not plum.signature.Signature, but plum.Signature. Please do open an issue if this release breaks something that shouldn't break.

Changes:

v2.6.1

This release features numerous very helpful contributions and improvements by @​nstarman!

  • Use dependency groups (#195).
  • Treat typing_extensions as standard library and make more use of it (#226 and #232).
  • Complete deprecation cycles (#230 and #236).
  • Turn various arguments into positional-only (#229).
  • Remove unnecessary path manipulation (#233).
  • Rework tests with a dispatch fixture (#234).
  • Avoid using a deprecated NumPy module (#231).
  • Drops support for Python 3.9 (#228).
  • Import exports from methods.py (#237).
  • Fixes an incorrect overload (#238).
  • Use nox for testing (#235 and #240).

#228 also fixes an important bug to do with the handling of unions (CC @​davidwyld).

v2.6.0

  • Add keyword argument condition to ModuleType.

v2.5.8

  • Fix precedence keyword argument (thanks @​nstarman!).
  • Fix complex method override.
  • Drop support for Python 8 and use e.g. list instead of typing.List (thanks @​nstarman!).
Commits
  • 485380d Minor style and linter changes
  • 28f5a4a Minor style changes
  • b85f8e7 Remove duplicate sections
  • 863138d Enable py3.14 and deprecate some alias functionality (#225)
  • ad54d37 build(deps-dev): bump uv from 0.9.16 to 0.11.6 (#265)
  • 562f3e2 build(deps-dev): bump pytest from 9.0.2 to 9.0.3 (#267)
  • 6b239db build(deps): bump cryptography from 46.0.6 to 46.0.7 (#264)
  • 0ddc2db Potential fix for code scanning alert no. 3: Workflow does not contain permis...
  • d4581ce Potential fix for code scanning alert no. 2: Workflow does not contain permis...
  • 3dd2386 Potential fix for code scanning alert no. 8: Workflow does not contain permis...
  • Additional commits viewable in compare view

Updates structlog from 25.5.0 to 26.1.0

Release notes

Sourced from structlog's releases.

26.1.0

Highlights

Given how long this release took, it's pretty thicc with nice things all over the board! Apologies for the long release cycle; it's been a victim of the slopocalypse and me trying to navigate my way thru the new normal. Extra big thanks to my sponsors for not abandoning me in these unironically trying times. ❤️

Full changelog below!

Special Thanks

This release would not be possible without my generous sponsors! Thank you to all of you making sustainable maintenance possible! If you would like to join them, go to https://github.com/sponsors/hynek and check out the sweet perks!

Above and Beyond

Variomedia AG (@variomedia), Tidelift (@tidelift), Kraken Tech (@kraken-tech), Klaviyo (@klaviyo), Privacy Solutions GmbH (@privacy-solutions), FilePreviews (@filepreviews), Ecosystems (@ecosyste-ms), TestMu AI Open Source Office (Formerly LambdaTest) (@LambdaTest-Inc), GitHub (@github), Doist (@Doist), Daniel Fortunov (@asqui), and Kevin P. Fleming (@kpfleming).

Maintenance Sustainers

Buttondown (@buttondown), Christopher Dignam (@chdsbd), Magnus Watn (@magnuswatn), David Cramer (@dcramer), Rivo Laks (@rivol), Polar (@polarsource), Mike Fiedler (@miketheman), Duncan Hill (@cricalix), Colin Marquardt (@cmarqu), Pieter Swinkels (@swinkels), Nick Libertini (@libertininick), Brian M. Dennis (@crossjam), Al Sweigart (@asweigart), Celebrity News AG (@celebritynewsag), The Westervelt Company (@westerveltco), Sławomir Ehlert (@slafs), Mostafa Khalil (@khadrawy), Filip Mularczyk (@mukiblejlok), Thomas Klinger (@thmsklngr), Andreas Poehlmann (@ap--), August Trapper Bigelow (@atbigelow), Carlton Gibson (@carltongibson), and Roboflow (@roboflow).

Full Changelog

Removed

  • Python 3.8 and 3.9 support.

Deprecated

  • Support for better-exceptions is deprecated and will be removed within a year. Use our Rich integration or copy-paste the one line of code you need. #802

Added

  • Python 3.15 support. #813

  • structlog.dev.rich_monochrome_traceback for Rich-based monochrome exception rendering and add support for it throughout structlog.dev.ConsoleRenderer when the user asks for no colors. #794

  • structlog.BytesLogger now has a name attribute which allows you to use it with the structlog.stdlib.add_logger_name() processor without using the standard library integration. #786

  • structlog.processors.CallsiteParameterAdder now supports CallsiteParameter.QUAL_MODULE that adds the qualified import name of the module of the callsite, or __main__ if the module is the entry point. This is only available for structlog-originated events since the standard library has no equivalent (except for the convention of setting the logger's name to __name__). #812

  • structlog.stdlib.BoundLogger now has is_enabled_for() and get_effective_level() methods that are snake_case aliases for its isEnabledFor() and getEffectiveLevel() methods. This makes it more compatible with the native structlog.typing.FilteringBoundLogger, so you can swap configurations without changing your call sites. #818

Changed

  • structlog.dev.ConsoleRenderer does not warn anymore when the exception key has a rendered value despite having a fancy formatter configured. #790

... (truncated)

Changelog

Sourced from structlog's changelog.

26.1.0 - 2026-06-06

Removed

  • Python 3.8 and 3.9 support.

Deprecated

  • Support for better-exceptions is deprecated and will be removed within a year. Use our Rich integration or copy-paste the one line of code you need. #802

Added

  • Python 3.15 support. #813

  • structlog.dev.rich_monochrome_traceback for Rich-based monochrome exception rendering and add support for it throughout structlog.dev.ConsoleRenderer when the user asks for no colors. #794

  • structlog.BytesLogger now has a name attribute which allows you to use it with the structlog.stdlib.add_logger_name() processor without using the standard library integration. #786

  • structlog.processors.CallsiteParameterAdder now supports CallsiteParameter.QUAL_MODULE that adds the qualified import name of the module of the callsite, or __main__ if the module is the entry point. This is only available for structlog-originated events since the standard library has no equivalent (except for the convention of setting the logger's name to __name__). #812

  • structlog.stdlib.BoundLogger now has is_enabled_for() and get_effective_level() methods that are snake_case aliases for its isEnabledFor() and getEffectiveLevel() methods. This makes it more compatible with the native structlog.typing.FilteringBoundLogger, so you can swap configurations without changing your call sites. #818

Changed

  • structlog.dev.ConsoleRenderer does not warn anymore when the exception key has a rendered value despite having a fancy formatter configured. #790

Fixed

  • structlog.BytesLogger, structlog.PrintLogger, and structlog.WriteLogger now hold weak references to the files they use for output. This prevents their leakage in long-running processes that open many logfiles, such as task executors that create a per-task BytesLogger or WriteLogger. #807

  • structlog.WriteLogger is usable after unpickling. #787

  • structlog.processors.CallsiteParameterAdder now reports the calling thread's id and name for async log methods, instead of the thread from the executor pool that runs the underlying sync logger.

... (truncated)

Commits

Updates opencv-contrib-python from 4.13.0.92 to 5.0.0.93

Release notes

Sourced from opencv-contrib-python's releases.

5.0.0.93

OpenCV 5.0.0 released!

OpenCV 5.0.0 overview: https://opencv.org/opencv-5 OpenCV 4.x -> 5.x migration guide: https://github.com/opencv/opencv/wiki/OpenCV-4-to-5-migration

Commits

Updates pydantic-settings from 2.12.0 to 2.14.2

Release notes

Sourced from pydantic-settings's releases.

v2.14.2

What's Changed

This is a security patch release.

Security

Fixes GHSA-4xgf-cpjx-pc3j: NestedSecretsSettingsSource with secrets_nested_subdir=True could follow a symbolic link inside secrets_dir pointing outside it, reading out-of-tree files into settings values and bypassing the secrets_dir_max_size cap. Affected versions: >= 2.12.0, < 2.14.2.

Full Changelog: pydantic/pydantic-settings@v2.14.1...v2.14.2

v2.14.1

What's Changed

Full Changelog: pydantic/pydantic-settings@v2.14.0...v2.14.1

v2.14.0

What's Changed

... (truncated)

Commits
  • d703bd7 Prepare release 2.14.2 (#890)
  • e95c30b Prepare release 2.14.1 (#859)
  • 0c87345 Fix field named cls conflicting with classmethod parameter (#858)
  • 7bd0072 Bump the python-packages group with 2 updates (#856)
  • b03e573 Bump the github-actions group with 3 updates (#853)
  • eaa3b43 Bump the python-packages group with 5 updates (#854)
  • 9f95615 Bump the python-packages group with 4 updates (#850)
  • 8916bee Prepare release 2.14.0 (#848)
  • 39e551c Fix CLI descriptions lost under python -OO by falling back to `json_schema_...
  • 9ed7f48 Bump the python-packages group with 4 updates (#847)
  • Additional commits viewable in compare view

Updates textual from 3.7.1 to 8.2.8

Release notes

Sourced from textual's releases.

The more super release

Fixes for extended key processing, and a crash bug for clicking the screen padding area.

[8.2.8] - 2026-06-30

Fixed

Changed

The more Kitty Release

This release adds additional support for the Kitty key protocol. Which enables some additional keys on some terminals. Additionally, Textual will report modifier keys as separate key events.

Additionally there are a few more shortcuts to the Text Area.

This release sponsored by Mistral AI. See release notes for detail.

[8.2.7] - 2026-05-19

Added

  • Added support for Kitty key protocol "Report all keys as escape codes" which enabled alt+backspace on Warp Textualize/textual#6544
  • Added support for detecting separate modifier keys for terminals that support the Kitty key protocol Textualize/textual#6544
  • Added TEXTUAL_DISABLE_KITTY_KEY env var to disable Kitty key protocol support (debug aid). Textualize/textual#6544

Changed

  • Undo/redo/copy/cut/paste in TextArea will now work with cmd+ on supported terminals Textualize/textual#6543
  • In TextArea, ctrl+u will now delete a newline if the cursor is at the start Textualize/textual#6543
  • in TextArea alt+delete is now bound to delete word right Textualize/textual#6543
  • Text opacity applied to an ansi theme will now set the dim attribute if the opacity is < 50%

Bumps the python group with 66 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [pin](https://github.com/cmake-wheel/pinocchio) | `3.8.0` | `4.0.0` |
| [pydantic](https://github.com/pydantic/pydantic) | `2.12.5` | `2.13.4` |
| [packaging](https://github.com/pypa/packaging) | `25.0` | `26.2` |
| [plum-dispatch](https://github.com/beartype/plum) | `2.5.7` | `2.9.0` |
| [structlog](https://github.com/hynek/structlog) | `25.5.0` | `26.1.0` |
| [opencv-contrib-python](https://github.com/opencv/opencv-python) | `4.13.0.92` | `5.0.0.93` |
| [pydantic-settings](https://github.com/pydantic/pydantic-settings) | `2.12.0` | `2.14.2` |
| [textual](https://github.com/Textualize/textual) | `3.7.1` | `8.2.8` |
| [terminaltexteffects](https://github.com/ChrisBuilds/terminaltexteffects) | `0.12.2` | `0.15.0` |
| [typer](https://github.com/fastapi/typer) | `0.23.1` | `0.26.8` |
| [numba](https://github.com/numba/numba) | `0.63.1` | `0.66.0` |
| [rerun-sdk](https://github.com/rerun-io/rerun) | `0.32.0` | `0.33.1` |
| [protobuf](https://github.com/protocolbuffers/protobuf) | `6.33.5` | `7.35.1` |
| [cryptography](https://github.com/pyca/cryptography) | `46.0.5` | `49.0.0` |
| [python-multipart](https://github.com/Kludex/python-multipart) | `0.0.27` | `0.0.32` |
| [ipykernel](https://github.com/ipython/ipykernel) | `7.2.0` | `7.3.0` |
| [timm](https://github.com/huggingface/pytorch-image-models) | `1.0.24` | `1.0.27` |
| [open-clip-torch](https://github.com/mlfoundations/open_clip) | `3.2.0` | `3.3.0` |
| [gdown](https://github.com/wkentaro/gdown) | `6.0.0` | `6.1.0` |
| [tensorboard](https://github.com/tensorflow/tensorboard) | `2.20.0` | `2.21.0` |
| [xarm-python-sdk](https://github.com/xArm-Developer/xArm-Python-SDK) | `1.17.3` | `1.18.4` |
| [portal](https://github.com/danijar/portal) | `3.7.4` | `3.8.1` |
| [pyarrow](https://github.com/apache/arrow) | `23.0.0` | `24.0.0` |
| [langchain-core](https://github.com/langchain-ai/langchain) | `1.3.3` | `1.4.8` |
| [langchain-openai](https://github.com/langchain-ai/langchain) | `1.1.6` | `1.3.3` |
| [langchain-huggingface](https://github.com/langchain-ai/langchain) | `1.2.0` | `1.2.2` |
| [langchain-ollama](https://github.com/langchain-ai/langchain) | `1.0.1` | `1.1.0` |
| [ollama](https://github.com/ollama/ollama-python) | `0.6.1` | `0.6.2` |
| [fastapi](https://github.com/fastapi/fastapi) | `0.129.0` | `0.139.0` |
| [sse-starlette](https://github.com/sysid/sse-starlette) | `3.2.0` | `3.4.5` |
| [uvicorn](https://github.com/Kludex/uvicorn) | `0.40.0` | `0.50.0` |
| [soundfile](https://github.com/bastibe/python-soundfile) | `0.13.1` | `0.14.0` |
| [ultralytics](https://github.com/ultralytics/ultralytics) | `8.4.14` | `8.4.87` |
| [pillow](https://github.com/python-pillow/Pillow) | `12.2.0` | `12.3.0` |
| [lap](https://github.com/gatagat/lap) | `0.5.12` | `0.5.13` |
| [transformers[torch]](https://github.com/huggingface/transformers) | `4.53.3` | `5.13.0` |
| [moondream](https://github.com/vikhyat/moondream) | `0.2.0` | `1.3.0` |
| [omegaconf](https://github.com/omry/omegaconf) | `2.3.0` | `2.3.1` |
| [hydra-core](https://github.com/facebookresearch/hydra) | `1.3.2` | `1.3.3` |
| [cyclonedds](https://github.com/eclipse-cyclonedds/cyclonedds-python) | `0.10.5` | `11.0.1` |
| [mcap](https://github.com/foxglove/mcap) | `1.3.1` | `1.4.0` |
| [pyrealsense2-extended](https://github.com/realsenseai/librealsense) | `2.58.1.10581.post1` | `2.58.2.10647.post1` |
| [matplotlib](https://github.com/matplotlib/matplotlib) | `3.10.8` | `3.10.9` |
| [onnxruntime](https://github.com/microsoft/onnxruntime) | `1.24.1` | `1.24.3` |
| [cupy-cuda12x](https://github.com/cupy/cupy) | `13.6.0` | `14.1.1` |
| [onnxruntime-gpu](https://github.com/microsoft/onnxruntime) | `1.24.1` | `1.24.3` |
| [mujoco](https://github.com/google-deepmind/mujoco) | `3.5.0` | `3.10.0` |
| [gtsam-extended](https://gtsam.org/) | `4.3a1.post1` | `4.3a1.post202607020747` |
| [reportlab](https://www.reportlab.com/) | `4.5.0` | `5.0.0` |
| [ruff](https://github.com/astral-sh/ruff) | `0.14.3` | `0.15.20` |
| [torch](https://github.com/pytorch/pytorch) | `2.10.0` | `2.12.1` |
| [pytest](https://github.com/pytest-dev/pytest) | `8.3.5` | `9.1.1` |
| [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) | `0.26.0` | `1.4.0` |
| [pytest-mock](https://github.com/pytest-dev/pytest-mock) | `3.15.0` | `3.15.1` |
| [pytest-env](https://github.com/pytest-dev/pytest-env) | `1.1.5` | `1.6.0` |
| [coverage](https://github.com/coveragepy/coveragepy) | `7.13.4` | `7.15.0` |
| [pre-commit](https://github.com/pre-commit/pre-commit) | `4.2.0` | `4.6.0` |
| [py-spy](https://github.com/benfred/py-spy) | `0.4.1` | `0.4.2` |
| [maturin](https://github.com/pyo3/maturin) | `1.13.3` | `1.14.1` |
| [python-lsp-ruff](https://github.com/python-lsp/python-lsp-ruff) | `2.3.0` | `2.3.1` |
| [mypy](https://github.com/python/mypy) | `1.19.0` | `2.1.0` |
| [ipython](https://github.com/ipython/ipython) | `8.38.0` | `8.39.0` |
| [python-socketio](https://github.com/miguelgrinberg/python-socketio) | `5.16.1` | `5.16.3` |
| [types-pyyaml](https://github.com/python/typeshed) | `6.0.12.20250915` | `6.0.12.20260518` |
| [types-reportlab](https://github.com/python/typeshed) | `4.5.0.20260509` | `4.5.1.20260521` |
| [types-requests](https://github.com/python/typeshed) | `2.32.4.20260107` | `2.33.0.20260518` |



Updates `pin` from 3.8.0 to 4.0.0
- [Release notes](https://github.com/cmake-wheel/pinocchio/releases)
- [Changelog](https://github.com/cmake-wheel/pinocchio/blob/cmeel/CHANGELOG.md)
- [Commits](https://github.com/cmake-wheel/pinocchio/commits)

Updates `pydantic` from 2.12.5 to 2.13.4
- [Release notes](https://github.com/pydantic/pydantic/releases)
- [Changelog](https://github.com/pydantic/pydantic/blob/main/HISTORY.md)
- [Commits](pydantic/pydantic@v2.12.5...v2.13.4)

Updates `packaging` from 25.0 to 26.2
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](pypa/packaging@25.0...26.2)

Updates `plum-dispatch` from 2.5.7 to 2.9.0
- [Release notes](https://github.com/beartype/plum/releases)
- [Commits](beartype/plum@v2.5.7...v2.9.0)

Updates `structlog` from 25.5.0 to 26.1.0
- [Release notes](https://github.com/hynek/structlog/releases)
- [Changelog](https://github.com/hynek/structlog/blob/main/CHANGELOG.md)
- [Commits](hynek/structlog@25.5.0...26.1.0)

Updates `opencv-contrib-python` from 4.13.0.92 to 5.0.0.93
- [Release notes](https://github.com/opencv/opencv-python/releases)
- [Commits](https://github.com/opencv/opencv-python/commits)

Updates `pydantic-settings` from 2.12.0 to 2.14.2
- [Release notes](https://github.com/pydantic/pydantic-settings/releases)
- [Commits](pydantic/pydantic-settings@v2.12.0...v2.14.2)

Updates `textual` from 3.7.1 to 8.2.8
- [Release notes](https://github.com/Textualize/textual/releases)
- [Changelog](https://github.com/Textualize/textual/blob/main/CHANGELOG.md)
- [Commits](Textualize/textual@v3.7.1...v8.2.8)

Updates `terminaltexteffects` from 0.12.2 to 0.15.0
- [Release notes](https://github.com/ChrisBuilds/terminaltexteffects/releases)
- [Changelog](https://github.com/ChrisBuilds/terminaltexteffects/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ChrisBuilds/terminaltexteffects/commits/release-0.15.0)

Updates `typer` from 0.23.1 to 0.26.8
- [Release notes](https://github.com/fastapi/typer/releases)
- [Changelog](https://github.com/fastapi/typer/blob/master/docs/release-notes.md)
- [Commits](fastapi/typer@0.23.1...0.26.8)

Updates `numba` from 0.63.1 to 0.66.0
- [Release notes](https://github.com/numba/numba/releases)
- [Commits](numba/numba@0.63.1...0.66.0)

Updates `llvmlite` from 0.46.0 to 0.48.0
- [Release notes](https://github.com/numba/llvmlite/releases)
- [Commits](numba/llvmlite@v0.46.0...v0.48.0)

Updates `rerun-sdk` from 0.32.0 to 0.33.1
- [Release notes](https://github.com/rerun-io/rerun/releases)
- [Changelog](https://github.com/rerun-io/rerun/blob/main/CHANGELOG.md)
- [Commits](rerun-io/rerun@0.32.0...0.33.1)

Updates `protobuf` from 6.33.5 to 7.35.1
- [Release notes](https://github.com/protocolbuffers/protobuf/releases)
- [Commits](https://github.com/protocolbuffers/protobuf/commits)

Updates `cryptography` from 46.0.5 to 49.0.0
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](pyca/cryptography@46.0.5...49.0.0)

Updates `python-multipart` from 0.0.27 to 0.0.32
- [Release notes](https://github.com/Kludex/python-multipart/releases)
- [Changelog](https://github.com/Kludex/python-multipart/blob/main/CHANGELOG.md)
- [Commits](Kludex/python-multipart@0.0.27...0.0.32)

Updates `ipykernel` from 7.2.0 to 7.3.0
- [Release notes](https://github.com/ipython/ipykernel/releases)
- [Changelog](https://github.com/ipython/ipykernel/blob/main/CHANGELOG.md)
- [Commits](ipython/ipykernel@v7.2.0...v7.3.0)

Updates `timm` from 1.0.24 to 1.0.27
- [Release notes](https://github.com/huggingface/pytorch-image-models/releases)
- [Commits](huggingface/pytorch-image-models@v1.0.24...v1.0.27)

Updates `open-clip-torch` from 3.2.0 to 3.3.0
- [Release notes](https://github.com/mlfoundations/open_clip/releases)
- [Changelog](https://github.com/mlfoundations/open_clip/blob/main/HISTORY.md)
- [Commits](mlfoundations/open_clip@v3.2.0...v3.3.0)

Updates `gdown` from 6.0.0 to 6.1.0
- [Release notes](https://github.com/wkentaro/gdown/releases)
- [Commits](wkentaro/gdown@v6.0.0...v6.1.0)

Updates `tensorboard` from 2.20.0 to 2.21.0
- [Release notes](https://github.com/tensorflow/tensorboard/releases)
- [Changelog](https://github.com/tensorflow/tensorboard/blob/master/RELEASE.md)
- [Commits](tensorflow/tensorboard@2.20.0...2.21.0)

Updates `xarm-python-sdk` from 1.17.3 to 1.18.4
- [Changelog](https://github.com/xArm-Developer/xArm-Python-SDK/blob/master/ReleaseNotes.md)
- [Commits](xArm-Developer/xArm-Python-SDK@v1.17.3...v1.18.4)

Updates `portal` from 3.7.4 to 3.8.1
- [Commits](https://github.com/danijar/portal/commits)

Updates `pyarrow` from 23.0.0 to 24.0.0
- [Release notes](https://github.com/apache/arrow/releases)
- [Commits](apache/arrow@apache-arrow-23.0.0...apache-arrow-24.0.0)

Updates `langchain-core` from 1.3.3 to 1.4.8
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](langchain-ai/langchain@langchain-core==1.3.3...langchain-core==1.4.8)

Updates `langchain-openai` from 1.1.6 to 1.3.3
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](langchain-ai/langchain@langchain-openai==1.1.6...langchain-openai==1.3.3)

Updates `langchain-huggingface` from 1.2.0 to 1.2.2
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](langchain-ai/langchain@langchain-huggingface==1.2.0...langchain-huggingface==1.2.2)

Updates `langchain-ollama` from 1.0.1 to 1.1.0
- [Release notes](https://github.com/langchain-ai/langchain/releases)
- [Commits](langchain-ai/langchain@langchain-ollama==1.0.1...langchain-ollama==1.1.0)

Updates `ollama` from 0.6.1 to 0.6.2
- [Release notes](https://github.com/ollama/ollama-python/releases)
- [Commits](ollama/ollama-python@v0.6.1...v0.6.2)

Updates `openai` from 2.21.0 to 2.44.0
- [Release notes](https://github.com/openai/openai-python/releases)
- [Changelog](https://github.com/openai/openai-python/blob/main/CHANGELOG.md)
- [Commits](openai/openai-python@v2.21.0...v2.44.0)

Updates `fastapi` from 0.129.0 to 0.139.0
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](fastapi/fastapi@0.129.0...0.139.0)

Updates `sse-starlette` from 3.2.0 to 3.4.5
- [Release notes](https://github.com/sysid/sse-starlette/releases)
- [Commits](sysid/sse-starlette@v3.2.0...v3.4.5)

Updates `uvicorn` from 0.40.0 to 0.50.0
- [Release notes](https://github.com/Kludex/uvicorn/releases)
- [Changelog](https://github.com/Kludex/uvicorn/blob/main/docs/release-notes.md)
- [Commits](Kludex/uvicorn@0.40.0...0.50.0)

Updates `soundfile` from 0.13.1 to 0.14.0
- [Release notes](https://github.com/bastibe/python-soundfile/releases)
- [Commits](bastibe/python-soundfile@0.13.1...0.14.0)

Updates `ultralytics` from 8.4.14 to 8.4.87
- [Release notes](https://github.com/ultralytics/ultralytics/releases)
- [Commits](ultralytics/ultralytics@v8.4.14...v8.4.87)

Updates `pillow` from 12.2.0 to 12.3.0
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](python-pillow/Pillow@12.2.0...12.3.0)

Updates `lap` from 0.5.12 to 0.5.13
- [Commits](gatagat/lap@v0.5.12...v0.5.13)

Updates `transformers[torch]` from 4.53.3 to 5.13.0
- [Release notes](https://github.com/huggingface/transformers/releases)
- [Commits](huggingface/transformers@v4.53.3...v5.13.0)

Updates `moondream` from 0.2.0 to 1.3.0
- [Commits](https://github.com/vikhyat/moondream/commits)

Updates `omegaconf` from 2.3.0 to 2.3.1
- [Release notes](https://github.com/omry/omegaconf/releases)
- [Changelog](https://github.com/omry/omegaconf/blob/v2.3.1/NEWS.md)
- [Commits](omry/omegaconf@v2.3.0...v2.3.1)

Updates `hydra-core` from 1.3.2 to 1.3.3
- [Release notes](https://github.com/facebookresearch/hydra/releases)
- [Changelog](https://github.com/facebookresearch/hydra/blob/v1.3.3/NEWS.md)
- [Commits](facebookresearch/hydra@v1.3.2...v1.3.3)

Updates `cyclonedds` from 0.10.5 to 11.0.1
- [Release notes](https://github.com/eclipse-cyclonedds/cyclonedds-python/releases)
- [Commits](eclipse-cyclonedds/cyclonedds-python@0.10.5...11.0.1)

Updates `mcap` from 1.3.1 to 1.4.0
- [Release notes](https://github.com/foxglove/mcap/releases)
- [Commits](foxglove/mcap@go/mcap/v1.3.1...go/mcap/v1.4.0)

Updates `pyrealsense2-extended` from 2.58.1.10581.post1 to 2.58.2.10647.post1
- [Release notes](https://github.com/realsenseai/librealsense/releases)
- [Commits](https://github.com/realsenseai/librealsense/commits)

Updates `matplotlib` from 3.10.8 to 3.10.9
- [Release notes](https://github.com/matplotlib/matplotlib/releases)
- [Commits](matplotlib/matplotlib@v3.10.8...v3.10.9)

Updates `onnxruntime` from 1.24.1 to 1.24.3
- [Release notes](https://github.com/microsoft/onnxruntime/releases)
- [Changelog](https://github.com/microsoft/onnxruntime/blob/main/docs/ReleaseManagement.md)
- [Commits](microsoft/onnxruntime@v1.24.1...v1.24.3)

Updates `cupy-cuda12x` from 13.6.0 to 14.1.1
- [Release notes](https://github.com/cupy/cupy/releases)
- [Commits](cupy/cupy@v13.6.0...v14.1.1)

Updates `onnxruntime-gpu` from 1.24.1 to 1.24.3
- [Release notes](https://github.com/microsoft/onnxruntime/releases)
- [Changelog](https://github.com/microsoft/onnxruntime/blob/main/docs/ReleaseManagement.md)
- [Commits](microsoft/onnxruntime@v1.24.1...v1.24.3)

Updates `mujoco` from 3.5.0 to 3.10.0
- [Release notes](https://github.com/google-deepmind/mujoco/releases)
- [Changelog](https://github.com/google-deepmind/mujoco/blob/main/doc/changelog.rst)
- [Commits](google-deepmind/mujoco@3.5.0...3.10.0)

Updates `gtsam-extended` from 4.3a1.post1 to 4.3a1.post202607020747

Updates `reportlab` from 4.5.0 to 5.0.0

Updates `ruff` from 0.14.3 to 0.15.20
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](astral-sh/ruff@0.14.3...0.15.20)

Updates `torch` from 2.10.0 to 2.12.1
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md)
- [Commits](pytorch/pytorch@v2.10.0...v2.12.1)

Updates `pytest` from 8.3.5 to 9.1.1
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](pytest-dev/pytest@8.3.5...9.1.1)

Updates `pytest-asyncio` from 0.26.0 to 1.4.0
- [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases)
- [Commits](pytest-dev/pytest-asyncio@v0.26.0...v1.4.0)

Updates `pytest-mock` from 3.15.0 to 3.15.1
- [Release notes](https://github.com/pytest-dev/pytest-mock/releases)
- [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst)
- [Commits](pytest-dev/pytest-mock@v3.15.0...v3.15.1)

Updates `pytest-env` from 1.1.5 to 1.6.0
- [Release notes](https://github.com/pytest-dev/pytest-env/releases)
- [Commits](pytest-dev/pytest-env@1.1.5...1.6.0)

Updates `coverage` from 7.13.4 to 7.15.0
- [Release notes](https://github.com/coveragepy/coveragepy/releases)
- [Changelog](https://github.com/coveragepy/coveragepy/blob/main/CHANGES.rst)
- [Commits](coveragepy/coveragepy@7.13.4...7.15.0)

Updates `pre-commit` from 4.2.0 to 4.6.0
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](pre-commit/pre-commit@v4.2.0...v4.6.0)

Updates `py-spy` from 0.4.1 to 0.4.2
- [Release notes](https://github.com/benfred/py-spy/releases)
- [Changelog](https://github.com/benfred/py-spy/blob/master/CHANGELOG.md)
- [Commits](benfred/py-spy@v0.4.1...v0.4.2)

Updates `maturin` from 1.13.3 to 1.14.1
- [Release notes](https://github.com/pyo3/maturin/releases)
- [Changelog](https://github.com/PyO3/maturin/blob/main/Changelog.md)
- [Commits](PyO3/maturin@v1.13.3...v1.14.1)

Updates `python-lsp-ruff` from 2.3.0 to 2.3.1
- [Release notes](https://github.com/python-lsp/python-lsp-ruff/releases)
- [Commits](python-lsp/python-lsp-ruff@v2.3.0...v2.3.1)

Updates `mypy` from 1.19.0 to 2.1.0
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](python/mypy@v1.19.0...v2.1.0)

Updates `ipython` from 8.38.0 to 8.39.0
- [Release notes](https://github.com/ipython/ipython/releases)
- [Commits](ipython/ipython@8.38.0...8.39.0)

Updates `python-socketio` from 5.16.1 to 5.16.3
- [Release notes](https://github.com/miguelgrinberg/python-socketio/releases)
- [Changelog](https://github.com/miguelgrinberg/python-socketio/blob/main/CHANGES.md)
- [Commits](miguelgrinberg/python-socketio@v5.16.1...v5.16.3)

Updates `types-pyyaml` from 6.0.12.20250915 to 6.0.12.20260518
- [Commits](https://github.com/python/typeshed/commits)

Updates `types-reportlab` from 4.5.0.20260509 to 4.5.1.20260521
- [Commits](https://github.com/python/typeshed/commits)

Updates `types-requests` from 2.32.4.20260107 to 2.33.0.20260518
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: pin
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: pydantic
  dependency-version: 2.13.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: packaging
  dependency-version: '26.2'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: plum-dispatch
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: structlog
  dependency-version: 26.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: opencv-contrib-python
  dependency-version: 5.0.0.93
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: pydantic-settings
  dependency-version: 2.14.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: textual
  dependency-version: 8.2.8
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: terminaltexteffects
  dependency-version: 0.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: typer
  dependency-version: 0.26.8
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: numba
  dependency-version: 0.66.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: llvmlite
  dependency-version: 0.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: rerun-sdk
  dependency-version: 0.33.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: protobuf
  dependency-version: 7.35.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: cryptography
  dependency-version: 49.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: python-multipart
  dependency-version: 0.0.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: ipykernel
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: timm
  dependency-version: 1.0.27
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: open-clip-torch
  dependency-version: 3.3.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: gdown
  dependency-version: 6.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: tensorboard
  dependency-version: 2.21.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: xarm-python-sdk
  dependency-version: 1.18.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: portal
  dependency-version: 3.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: pyarrow
  dependency-version: 24.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: langchain-core
  dependency-version: 1.4.8
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: langchain-openai
  dependency-version: 1.3.3
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: langchain-huggingface
  dependency-version: 1.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: langchain-ollama
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: ollama
  dependency-version: 0.6.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: openai
  dependency-version: 2.44.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: fastapi
  dependency-version: 0.139.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: sse-starlette
  dependency-version: 3.4.5
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: uvicorn
  dependency-version: 0.50.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: soundfile
  dependency-version: 0.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: ultralytics
  dependency-version: 8.4.87
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: lap
  dependency-version: 0.5.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: transformers[torch]
  dependency-version: 5.13.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: moondream
  dependency-version: 1.3.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: omegaconf
  dependency-version: 2.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: hydra-core
  dependency-version: 1.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: cyclonedds
  dependency-version: 11.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: mcap
  dependency-version: 1.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: pyrealsense2-extended
  dependency-version: 2.58.2.10647.post1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: matplotlib
  dependency-version: 3.10.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: onnxruntime
  dependency-version: 1.24.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: cupy-cuda12x
  dependency-version: 14.1.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: onnxruntime-gpu
  dependency-version: 1.24.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: mujoco
  dependency-version: 3.10.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: gtsam-extended
  dependency-version: 4.3a1.post202607020747
  dependency-type: direct:production
  dependency-group: python
- dependency-name: reportlab
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: ruff
  dependency-version: 0.15.20
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: torch
  dependency-version: 2.12.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: pytest
  dependency-version: 9.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: pytest-asyncio
  dependency-version: 1.4.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: pytest-mock
  dependency-version: 3.15.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: pytest-env
  dependency-version: 1.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: coverage
  dependency-version: 7.15.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: pre-commit
  dependency-version: 4.6.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: py-spy
  dependency-version: 0.4.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: maturin
  dependency-version: 1.14.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: python-lsp-ruff
  dependency-version: 2.3.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: mypy
  dependency-version: 2.1.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: python
- dependency-name: ipython
  dependency-version: 8.39.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
- dependency-name: python-socketio
  dependency-version: 5.16.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: types-pyyaml
  dependency-version: 6.0.12.20260518
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: types-reportlab
  dependency-version: 4.5.1.20260521
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: python
- dependency-name: types-requests
  dependency-version: 2.33.0.20260518
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file python:uv Pull requests that update python:uv code labels Jul 11, 2026
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file python:uv Pull requests that update python:uv code labels Jul 11, 2026
@github-actions github-actions Bot enabled auto-merge (squash) July 11, 2026 07:14
@greptile-apps

greptile-apps Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refreshes the Python dependency set and regenerates the lockfile. The main changes are:

  • Moves OpenCV to the 5.x line.
  • Moves Transformers to the 5.x line for perception and test dependencies.
  • Updates Textual and development tooling pins.
  • Refreshes the resolved uv.lock dependency graph.

Confidence Score: 4/5

The OpenCV tracking and ResNet embedding paths can fail after these dependency upgrades.

  • OpenCV 5 no longer provides the legacy CSRT tracker API used by active perception and drone paths.
  • Transformers 5 removes the ResNet extractor API imported by the configured embedding backend.
  • The Textual upgrade also reaches private RichLog state used by the human CLI.

pyproject.toml; dimos/perception/image_embedding.py; dimos/utils/cli/human/humancli.py

Important Files Changed

Filename Overview
pyproject.toml Updates runtime, optional-feature, and development dependency constraints, including several major-version upgrades.
uv.lock Regenerates the resolved dependency graph for the updated manifest constraints.

Reviews (1): Last reviewed commit: "build(deps): bump the python group acros..." | Re-trigger Greptile

Comment thread pyproject.toml
# trackers (perception/drone) are contrib-only. <5 defers the OpenCV 5
# major bump. See also the opencv-python entry in override-dependencies.
"opencv-contrib-python>=4.8,<5",
"opencv-contrib-python>=4.8,<6",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Legacy CSRT Trackers Removed

This now locks OpenCV 5, while three reachable tracking paths call cv2.legacy.TrackerCSRT_create() in the perception and drone modules. Those legacy trackers are removed from the OpenCV 5 tracking API, so starting object tracking or drone visual tracking will raise an AttributeError instead of creating a tracker.

Suggested change
"opencv-contrib-python>=4.8,<6",
"opencv-contrib-python>=4.8,<5",

Comment thread pyproject.toml
"Pillow",
"lap>=0.5.12",
"transformers[torch]>=4.53.0,<4.54",
"transformers[torch]>=4.53.0,<5.14",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Removed ResNet Extractor API

The perception extra now resolves Transformers 5.13.0, but ImageEmbeddingProvider(model_name="resnet") imports AutoFeatureExtractor in dimos/perception/image_embedding.py. Transformers 5 removes that API, so this reachable ResNet initialization path logs and re-raises an ImportError, leaving the configured embedding provider unavailable.

Comment thread pyproject.toml
# CLI
"pydantic-settings>=2.11.0,<3",
"textual==3.7.1",
"textual==8.2.8",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Private RichLog State Dependency

The human CLI directly mutates RichLog._line_cache, RichLog.lines, and RichLog.virtual_size in dimos/utils/cli/human/humancli.py. Moving from Textual 3.7 to 8.2 crosses several major releases, so a changed internal RichLog representation will make agent-message insertion or removal fail with an attribute or cache-type error and crash the TUI.

Suggested change
"textual==8.2.8",
"textual==3.7.1",

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

❌ 12 Tests Failed:

Tests completed Failed Passed Skipped
2619 12 2607 29
View the top 3 failed test(s) by shortest run time
::dimos.control.tasks.eef_twist_task.test_eef_twist_task
Stack Traces | 0s run time
ImportError while importing test module '.../tasks/eef_twist_task/test_eef_twist_task.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
.../tasks/eef_twist_task/test_eef_twist_task.py:24: in <module>
    from dimos.control.tasks.eef_twist_task.eef_twist_task import EEFTwistTask, EEFTwistTaskConfig
.../tasks/eef_twist_task/eef_twist_task.py:24: in <module>
    import pinocchio
.venv/lib/python3.12/site-packages/cmeel.prefix/lib/python3.12.../site-packages/pinocchio/__init__.py:19: in <module>
    from .pinocchio_pywrap_default import *
E   ImportError: libtinyxml2.so.11: cannot open shared object file: No such file or directory
dimos.utils.cli.cameracalibrate.test_cameracalibrate::test_calibrate_from_frames_fisheye_recovers_K_near_truth_and_emits_four_coeffs
Stack Traces | 0.008s run time
def test_calibrate_from_frames_fisheye_recovers_K_near_truth_and_emits_four_coeffs() -> None:
        """Synthetic fisheye projections recover ``K`` close to truth and yield 4 dist coeffs."""
        cols, rows = 9, 6
        width, height = 1280, 720
        square_size_m = 0.025
        frames, image_points, K_true, _D_true = _synthetic_fisheye_image_points(
            cols=cols,
            rows=rows,
            width=width,
            height=height,
            square_size_m=square_size_m,
            count=15,
        )
    
>       out = calibrate_from_frames(
            frames,
            cols,
            rows,
            square_size_m,
            pattern_hint=(cols, rows, "requested inner corners"),
            image_points_hint=image_points,
            distortion_model=DistortionModel.fisheye,
        )

K_true     = array([[        400,           0,         640],
       [          0,         400,         360],
       [          0,           0,           1]])
_D_true    = array([      -0.05,        0.01,           0,           0])
cols       = 9
frames     = [array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0..., ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8), ...]
height     = 720
image_points = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
rows       = 6
square_size_m = 0.025
width      = 1280

.../cli/cameracalibrate/test_cameracalibrate.py:742: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../cli/cameracalibrate/cameracalibrate.py:785: in calibrate_from_frames
    rms, K, D = _calibrate_fisheye(objpoints, imgpoints, (w0, h0))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        actual_cols = 9
        actual_rows = 6
        cols       = 9
        corners_found = array([[[     657.38,      344.51]],

       [[     674.04,      346.19]],

       [[     690.73,      347.89]],

    ...     747.28,       437.8]],

       [[     763.18,      439.14]],

       [[     778.77,      440.36]]], dtype=float32)
        distortion_model = <DistortionModel.fisheye: 'fisheye'>
        f          = array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8)
        first      = array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8)
        frame      = array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8)
        frames     = [array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0..., ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8), ...]
        h0         = 720
        i          = 14
        image_points_hint = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
        imgpoints  = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
        model      = <DistortionModel.fisheye: 'fisheye'>
        objp_flat  = array([[          0,           0,           0],
       [      0.025,           0,           0],
       [       0.05,  ...    0],
       [      0.175,       0.125,           0],
       [        0.2,       0.125,           0]], dtype=float32)
        objp_view  = array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[       ...,

       [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32)
        objpoints  = [array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[      ...    [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32), ...]
        pattern_hint = (9, 6, 'requested inner corners')
        pattern_label = 'requested inner corners'
        rows       = 6
        square_size_m = 0.025
        w0         = 1280
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

objpoints = [array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[      ...    [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32), ...]
imgpoints = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
image_size = (1280, 720)

    def _calibrate_fisheye(
        objpoints: list[np.ndarray],
        imgpoints: list[np.ndarray],
        image_size: tuple[int, int],
    ) -> tuple[float, np.ndarray, np.ndarray]:
        """Run ``cv2.fisheye.calibrate`` (4-coeff Kannala-Brandt).
    
        ``objpoints`` must be a list of ``(N, 1, 3)`` arrays and ``imgpoints`` a list of
        ``(N, 1, 2)`` arrays (the fisheye solver is strict about the extra middle axis).
        """
        K = np.zeros((3, 3), dtype=np.float64)
        D = np.zeros((4, 1), dtype=np.float64)
        n_views = len(objpoints)
        rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(n_views)]
        tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(n_views)]
>       flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC | cv2.fisheye.CALIB_FIX_SKEW
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E       AttributeError: module 'cv2.fisheye' has no attribute 'CALIB_RECOMPUTE_EXTRINSIC'

D          = array([[          0],
       [          0],
       [          0],
       [          0]])
K          = array([[          0,           0,           0],
       [          0,           0,           0],
       [          0,           0,           0]])
image_size = (1280, 720)
imgpoints  = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
n_views    = 15
objpoints  = [array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[      ...    [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32), ...]
rvecs      = [array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), array([[[    ...    0]]]), array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), ...]
tvecs      = [array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), array([[[    ...    0]]]), array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), ...]

.../cli/cameracalibrate/cameracalibrate.py:686: AttributeError
dimos.perception.fiducial.test_marker_transformer::test_detect_markers_rebuilds_intrinsics_without_resetting_smoothing_track
Stack Traces | 0.011s run time
def test_detect_markers_rebuilds_intrinsics_without_resetting_smoothing_track() -> None:
        marker_id = 7
        marker_length_m = 0.18
        image_a = synthetic_marker_image(marker_id=marker_id, ts=15.0)
        image_b = synthetic_marker_image(marker_id=marker_id, ts=15.2)
        info_a = camera_info(image_a.ts)
        info_b = camera_info(image_b.ts)
        info_b.K = info_b.K.copy()
        info_b.P = info_b.P.copy()
        info_b.K[0] = info_b.K[4] = 900.0
        info_b.P[0] = info_b.P[5] = 900.0
        latest_info: CameraInfo | None = info_a
    
        obs_a = Observation[Image](
            id=45,
            ts=image_a.ts,
            data_type=Image,
            pose=(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
            _data=image_a,
        )
        obs_b = Observation[Image](
            id=46,
            ts=image_b.ts,
            data_type=Image,
            pose=(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
            _data=image_b,
        )
        transformer = DetectMarkers(
            camera_info=lambda: latest_info,
            marker_length_m=marker_length_m,
            aruco_dictionary="DICT_APRILTAG_36h11",
            smoothing_window=1.0,
        )
    
>       first = next(transformer(iter([obs_a])))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

image_a    = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=15.0)
image_b    = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=15.2)
info_a     = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=15.0)
info_b     = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=15.2)
latest_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=15.0)
marker_id  = 7
marker_length_m = 0.18
obs_a      = Observation(id=45, ts=15.0, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(0.0, 0.0, 0.0, 0.0, 0....=uint8, frame_id='camera_optical', ts=15.0), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7f7481103b40>)
obs_b      = Observation(id=46, ts=15.2, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(0.0, 0.0, 0.0, 0.0, 0....=uint8, frame_id='camera_optical', ts=15.2), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7f7481103cc0>)
transformer = #x1B[36mDetectMarkers#x1B[0m(camera_info=<lambda>, marker_length_m=0.18, aruco_dictionary='DICT_APRILTAG_36h11', world_frame='world', smoothing_window=1.0, emit_empty_frames=False)

.../perception/fiducial/test_marker_transformer.py:209: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../perception/fiducial/marker_transformer.py:224: in __call__
    detections = _detect_markers_in_image(
        image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=15.0)
        image_size_mismatch = False
        info       = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=15.0)
        obs        = Observation(id=45, ts=15.0, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(0.0, 0.0, 0.0, 0.0, 0....=uint8, frame_id='camera_optical', ts=15.0), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7f7481103b40>)
        optical_frame = 'camera_optical'
        pose_tuple = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ...)
        self       = #x1B[36mDetectMarkers#x1B[0m(camera_info=<lambda>, marker_length_m=0.18, aruco_dictionary='DICT_APRILTAG_36h11', world_frame='world', smoothing_window=1.0, emit_empty_frames=False)
        t_world_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
        upstream   = <list_iterator object at 0x7f748135b5b0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

image = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=15.0)
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=15.0)
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
marker_length_m = 0.18, aruco_dictionary = 'DICT_APRILTAG_36h11'
world_frame = 'world', detector = < cv2.aruco.ArucoDetector 0x7f7481308eb0>
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])

    def detect_markers_in_image(
        image: Image,
        *,
        camera_info: CameraInfo,
        world_T_optical: Transform,
        marker_length_m: float,
        aruco_dictionary: str,
        world_frame: str = "world",
        detector: Any | None = None,
        camera_matrix: np.ndarray | None = None,
        dist_coeffs: np.ndarray | None = None,
    ) -> list[Detection3DMarker]:
        """Detect markers in one image and return rich world-frame 3D detections."""
        if marker_length_m <= 0:
            raise ValueError(f"marker_length_m must be > 0, got {marker_length_m}")
        if (
            camera_info.width
            and camera_info.height
            and (image.width != camera_info.width or image.height != camera_info.height)
        ):
            return []
    
        if detector is None:
            detector = create_aruco_detector(aruco_dictionary)
        if (camera_matrix is None) != (dist_coeffs is None):
            raise ValueError("camera_matrix and dist_coeffs must be provided together")
        if camera_matrix is None or dist_coeffs is None:
            camera_matrix, dist_coeffs = camera_info_to_cv_matrices(camera_info)
    
        gray = image.to_grayscale().as_numpy()
        corners, ids, _ = detector.detectMarkers(gray)
        if ids is None or len(ids) == 0:
            return []
    
        optical_frame = camera_optical_frame_id(image, camera_info)
        t_world_optical = Transform(
            translation=world_T_optical.translation,
            rotation=world_T_optical.rotation,
            frame_id=world_frame,
            child_frame_id=optical_frame,
            ts=image.ts,
        )
        marker_size = Vector3(marker_length_m, marker_length_m, 0.0)
        detections: list[Detection3DMarker] = []
    
        for corner_set, mid_arr in zip(corners, ids, strict=True):
>           mid = int(mid_arr[0])
                      ^^^^^^^^^^
E           IndexError: invalid index to scalar variable.

_          = (array([[[        341,         149],
        [        383,         151],
        [        381,         193],
        [...  [        402,         212],
        [        403,         239],
        [        375,         240]]], dtype=float32))
aruco_dictionary = 'DICT_APRILTAG_36h11'
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=15.0)
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
corner_set = array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32)
corners    = (array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32),)
detections = []
detector   = < cv2.aruco.ArucoDetector 0x7f7481308eb0>
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(480, 640), dtype=uint8)
ids        = array([7], dtype=int32)
image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=15.0)
marker_length_m = 0.18
marker_size = Vector([       0.18        0.18           0])
mid_arr    = np.int32(7)
optical_frame = 'camera_optical'
t_world_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_frame = 'world'

.../perception/fiducial/marker_detect.py:85: IndexError
dimos.perception.fiducial.test_marker_transformer::test_detect_markers_transformer_uses_callablecamera_info_source
Stack Traces | 0.011s run time
def test_detect_markers_transformer_uses_callablecamera_info_source() -> None:
        image = synthetic_marker_image(marker_id=7, ts=14.0)
        obs = Observation[Image](
            id=44,
            ts=image.ts,
            data_type=Image,
            pose=(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
            _data=image,
        )
        latest_info: CameraInfo | None = None
        transformer = DetectMarkers(
            camera_info=lambda: latest_info,
            marker_length_m=0.18,
            aruco_dictionary="DICT_APRILTAG_36h11",
            emit_empty_frames=True,
        )
    
        assert list(transformer(iter([obs]))) == []
    
        latest_info = camera_info(image.ts)
>       results = list(transformer(iter([obs])))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=14.0)
latest_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=14.0)
obs        = Observation(id=44, ts=14.0, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(0.0, 0.0, 0.0, 0.0, 0....=uint8, frame_id='camera_optical', ts=14.0), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7f74811316c0>)
transformer = #x1B[36mDetectMarkers#x1B[0m(camera_info=<lambda>, marker_length_m=0.18, aruco_dictionary='DICT_APRILTAG_36h11', world_frame='world', smoothing_window=0.0, emit_empty_frames=True)

.../perception/fiducial/test_marker_transformer.py:168: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../perception/fiducial/marker_transformer.py:224: in __call__
    detections = _detect_markers_in_image(
        image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=14.0)
        image_size_mismatch = False
        info       = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=14.0)
        obs        = Observation(id=44, ts=14.0, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(0.0, 0.0, 0.0, 0.0, 0....=uint8, frame_id='camera_optical', ts=14.0), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7f74811316c0>)
        optical_frame = 'camera_optical'
        pose_tuple = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ...)
        self       = #x1B[36mDetectMarkers#x1B[0m(camera_info=<lambda>, marker_length_m=0.18, aruco_dictionary='DICT_APRILTAG_36h11', world_frame='world', smoothing_window=0.0, emit_empty_frames=True)
        t_world_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
        upstream   = <list_iterator object at 0x7f7481265b10>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

image = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=14.0)
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=14.0)
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
marker_length_m = 0.18, aruco_dictionary = 'DICT_APRILTAG_36h11'
world_frame = 'world', detector = < cv2.aruco.ArucoDetector 0x7f7481383b10>
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])

    def detect_markers_in_image(
        image: Image,
        *,
        camera_info: CameraInfo,
        world_T_optical: Transform,
        marker_length_m: float,
        aruco_dictionary: str,
        world_frame: str = "world",
        detector: Any | None = None,
        camera_matrix: np.ndarray | None = None,
        dist_coeffs: np.ndarray | None = None,
    ) -> list[Detection3DMarker]:
        """Detect markers in one image and return rich world-frame 3D detections."""
        if marker_length_m <= 0:
            raise ValueError(f"marker_length_m must be > 0, got {marker_length_m}")
        if (
            camera_info.width
            and camera_info.height
            and (image.width != camera_info.width or image.height != camera_info.height)
        ):
            return []
    
        if detector is None:
            detector = create_aruco_detector(aruco_dictionary)
        if (camera_matrix is None) != (dist_coeffs is None):
            raise ValueError("camera_matrix and dist_coeffs must be provided together")
        if camera_matrix is None or dist_coeffs is None:
            camera_matrix, dist_coeffs = camera_info_to_cv_matrices(camera_info)
    
        gray = image.to_grayscale().as_numpy()
        corners, ids, _ = detector.detectMarkers(gray)
        if ids is None or len(ids) == 0:
            return []
    
        optical_frame = camera_optical_frame_id(image, camera_info)
        t_world_optical = Transform(
            translation=world_T_optical.translation,
            rotation=world_T_optical.rotation,
            frame_id=world_frame,
            child_frame_id=optical_frame,
            ts=image.ts,
        )
        marker_size = Vector3(marker_length_m, marker_length_m, 0.0)
        detections: list[Detection3DMarker] = []
    
        for corner_set, mid_arr in zip(corners, ids, strict=True):
>           mid = int(mid_arr[0])
                      ^^^^^^^^^^
E           IndexError: invalid index to scalar variable.

_          = (array([[[        341,         149],
        [        383,         151],
        [        381,         193],
        [...  [        402,         212],
        [        403,         239],
        [        375,         240]]], dtype=float32))
aruco_dictionary = 'DICT_APRILTAG_36h11'
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=14.0)
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
corner_set = array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32)
corners    = (array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32),)
detections = []
detector   = < cv2.aruco.ArucoDetector 0x7f7481383b10>
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(480, 640), dtype=uint8)
ids        = array([7], dtype=int32)
image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=14.0)
marker_length_m = 0.18
marker_size = Vector([       0.18        0.18           0])
mid_arr    = np.int32(7)
optical_frame = 'camera_optical'
t_world_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_frame = 'world'

.../perception/fiducial/marker_detect.py:85: IndexError
dimos.perception.fiducial.test_marker_transformer::test_detect_markers_in_image_builds_rich_marker_detection
Stack Traces | 0.019s run time
def test_detect_markers_in_image_builds_rich_marker_detection() -> None:
        marker_id = 7
        marker_length_m = 0.18
        image = synthetic_marker_image(marker_id)
        info = camera_info(image.ts)
    
>       detections = detect_markers_in_image(
            image,
            camera_info=info,
            world_T_optical=world_T_optical(image.ts),
            marker_length_m=marker_length_m,
            aruco_dictionary="DICT_APRILTAG_36h11",
        )

image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10.0)
info       = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=10.0)
marker_id  = 7
marker_length_m = 0.18

.../perception/fiducial/test_marker_transformer.py:36: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

image = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10.0)
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=10.0)
world_T_optical = Transform(translation=Vector([          1           2           3]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
marker_length_m = 0.18, aruco_dictionary = 'DICT_APRILTAG_36h11'
world_frame = 'world', detector = < cv2.aruco.ArucoDetector 0x7f7481209a10>
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])

    def detect_markers_in_image(
        image: Image,
        *,
        camera_info: CameraInfo,
        world_T_optical: Transform,
        marker_length_m: float,
        aruco_dictionary: str,
        world_frame: str = "world",
        detector: Any | None = None,
        camera_matrix: np.ndarray | None = None,
        dist_coeffs: np.ndarray | None = None,
    ) -> list[Detection3DMarker]:
        """Detect markers in one image and return rich world-frame 3D detections."""
        if marker_length_m <= 0:
            raise ValueError(f"marker_length_m must be > 0, got {marker_length_m}")
        if (
            camera_info.width
            and camera_info.height
            and (image.width != camera_info.width or image.height != camera_info.height)
        ):
            return []
    
        if detector is None:
            detector = create_aruco_detector(aruco_dictionary)
        if (camera_matrix is None) != (dist_coeffs is None):
            raise ValueError("camera_matrix and dist_coeffs must be provided together")
        if camera_matrix is None or dist_coeffs is None:
            camera_matrix, dist_coeffs = camera_info_to_cv_matrices(camera_info)
    
        gray = image.to_grayscale().as_numpy()
        corners, ids, _ = detector.detectMarkers(gray)
        if ids is None or len(ids) == 0:
            return []
    
        optical_frame = camera_optical_frame_id(image, camera_info)
        t_world_optical = Transform(
            translation=world_T_optical.translation,
            rotation=world_T_optical.rotation,
            frame_id=world_frame,
            child_frame_id=optical_frame,
            ts=image.ts,
        )
        marker_size = Vector3(marker_length_m, marker_length_m, 0.0)
        detections: list[Detection3DMarker] = []
    
        for corner_set, mid_arr in zip(corners, ids, strict=True):
>           mid = int(mid_arr[0])
                      ^^^^^^^^^^
E           IndexError: invalid index to scalar variable.

_          = (array([[[        341,         149],
        [        383,         151],
        [        381,         193],
        [...  [        402,         212],
        [        403,         239],
        [        375,         240]]], dtype=float32))
aruco_dictionary = 'DICT_APRILTAG_36h11'
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=10.0)
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
corner_set = array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32)
corners    = (array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32),)
detections = []
detector   = < cv2.aruco.ArucoDetector 0x7f7481209a10>
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(480, 640), dtype=uint8)
ids        = array([7], dtype=int32)
image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10.0)
marker_length_m = 0.18
marker_size = Vector([       0.18        0.18           0])
mid_arr    = np.int32(7)
optical_frame = 'camera_optical'
t_world_optical = Transform(translation=Vector([          1           2           3]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_T_optical = Transform(translation=Vector([          1           2           3]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_frame = 'world'

.../perception/fiducial/marker_detect.py:85: IndexError
dimos.perception.fiducial.test_marker_transformer::test_detect_markers_transformer_preserves_observation_context_and_tags
Stack Traces | 0.02s run time
def test_detect_markers_transformer_preserves_observation_context_and_tags() -> None:
        marker_id = 7
        image = synthetic_marker_image(marker_id, ts=12.0)
        obs = Observation[Image](
            id=42,
            ts=image.ts,
            data_type=Image,
            pose=(1.0, 2.0, 3.0, 0.0, 0.0, 0.0, 1.0),
            _data=image,
        )
        transformer = DetectMarkers(
            camera_info=camera_info(image.ts),
            marker_length_m=0.18,
            aruco_dictionary="DICT_APRILTAG_36h11",
        )
    
>       results = list(transformer(iter([obs])))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=12.0)
marker_id  = 7
obs        = Observation(id=42, ts=12.0, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(1.0, 2.0, 3.0, 0.0, 0....=uint8, frame_id='camera_optical', ts=12.0), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7f748129eb80>)
transformer = #x1B[36mDetectMarkers#x1B[0m(camera_info=CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_op...gth_m=0.18, aruco_dictionary='DICT_APRILTAG_36h11', world_frame='world', smoothing_window=0.0, emit_empty_frames=False)

.../perception/fiducial/test_marker_transformer.py:102: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../perception/fiducial/marker_transformer.py:224: in __call__
    detections = _detect_markers_in_image(
        image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=12.0)
        image_size_mismatch = False
        info       = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=12.0)
        obs        = Observation(id=42, ts=12.0, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(1.0, 2.0, 3.0, 0.0, 0....=uint8, frame_id='camera_optical', ts=12.0), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7f748129eb80>)
        optical_frame = 'camera_optical'
        pose_tuple = (1.0, 2.0, 3.0, 0.0, 0.0, 0.0, ...)
        self       = #x1B[36mDetectMarkers#x1B[0m(camera_info=CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_op...gth_m=0.18, aruco_dictionary='DICT_APRILTAG_36h11', world_frame='world', smoothing_window=0.0, emit_empty_frames=False)
        t_world_optical = Transform(translation=Vector([          1           2           3]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
        upstream   = <list_iterator object at 0x7f74813ebfa0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

image = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=12.0)
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=12.0)
world_T_optical = Transform(translation=Vector([          1           2           3]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
marker_length_m = 0.18, aruco_dictionary = 'DICT_APRILTAG_36h11'
world_frame = 'world', detector = < cv2.aruco.ArucoDetector 0x7f748120e190>
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])

    def detect_markers_in_image(
        image: Image,
        *,
        camera_info: CameraInfo,
        world_T_optical: Transform,
        marker_length_m: float,
        aruco_dictionary: str,
        world_frame: str = "world",
        detector: Any | None = None,
        camera_matrix: np.ndarray | None = None,
        dist_coeffs: np.ndarray | None = None,
    ) -> list[Detection3DMarker]:
        """Detect markers in one image and return rich world-frame 3D detections."""
        if marker_length_m <= 0:
            raise ValueError(f"marker_length_m must be > 0, got {marker_length_m}")
        if (
            camera_info.width
            and camera_info.height
            and (image.width != camera_info.width or image.height != camera_info.height)
        ):
            return []
    
        if detector is None:
            detector = create_aruco_detector(aruco_dictionary)
        if (camera_matrix is None) != (dist_coeffs is None):
            raise ValueError("camera_matrix and dist_coeffs must be provided together")
        if camera_matrix is None or dist_coeffs is None:
            camera_matrix, dist_coeffs = camera_info_to_cv_matrices(camera_info)
    
        gray = image.to_grayscale().as_numpy()
        corners, ids, _ = detector.detectMarkers(gray)
        if ids is None or len(ids) == 0:
            return []
    
        optical_frame = camera_optical_frame_id(image, camera_info)
        t_world_optical = Transform(
            translation=world_T_optical.translation,
            rotation=world_T_optical.rotation,
            frame_id=world_frame,
            child_frame_id=optical_frame,
            ts=image.ts,
        )
        marker_size = Vector3(marker_length_m, marker_length_m, 0.0)
        detections: list[Detection3DMarker] = []
    
        for corner_set, mid_arr in zip(corners, ids, strict=True):
>           mid = int(mid_arr[0])
                      ^^^^^^^^^^
E           IndexError: invalid index to scalar variable.

_          = (array([[[        341,         149],
        [        383,         151],
        [        381,         193],
        [...  [        402,         212],
        [        403,         239],
        [        375,         240]]], dtype=float32))
aruco_dictionary = 'DICT_APRILTAG_36h11'
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=12.0)
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
corner_set = array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32)
corners    = (array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32),)
detections = []
detector   = < cv2.aruco.ArucoDetector 0x7f748120e190>
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(480, 640), dtype=uint8)
ids        = array([7], dtype=int32)
image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=12.0)
marker_length_m = 0.18
marker_size = Vector([       0.18        0.18           0])
mid_arr    = np.int32(7)
optical_frame = 'camera_optical'
t_world_optical = Transform(translation=Vector([          1           2           3]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_T_optical = Transform(translation=Vector([          1           2           3]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_frame = 'world'

.../perception/fiducial/marker_detect.py:85: IndexError
dimos.utils.cli.cameracalibrate.test_cameracalibrate::test_cli_distortion_model_fisheye_writes_equidistant_yaml_and_four_coeffs
Stack Traces | 0.032s run time
tmp_path = PosixPath('.../pytest-0/popen-gw0/test_cli_distortion_model_fish0')

    def test_cli_distortion_model_fisheye_writes_equidistant_yaml_and_four_coeffs(
        tmp_path: Path,
    ) -> None:
        """``--distortion-model fisheye`` produces a YAML with the ROS-canonical name."""
        cols, rows = 9, 6
        frames, image_points, _K_true, _D_true = _synthetic_fisheye_image_points(
            cols=cols, rows=rows, count=15
        )
        images_dir = tmp_path / "fisheye_frames"
        images_dir.mkdir()
        for i, frame in enumerate(frames):
            assert cv2.imwrite(str(images_dir / f"{i:02d}.png"), frame)
    
        # The folder source has no chessboard corners in the synthetic dummies, so route
        # through calibrate_from_frames directly to exercise the YAML emit path.
        out_path = tmp_path / "fisheye.yaml"
>       cal = calibrate_from_frames(
            frames,
            cols,
            rows,
            0.025,
            pattern_hint=(cols, rows, "requested inner corners"),
            image_points_hint=image_points,
            distortion_model=DistortionModel.fisheye,
        )

_D_true    = array([      -0.05,        0.01,           0,           0])
_K_true    = array([[        400,           0,         640],
       [          0,         400,         360],
       [          0,           0,           1]])
cols       = 9
frame      = array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8)
frames     = [array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0..., ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8), ...]
i          = 14
image_points = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
images_dir = PosixPath('.../pytest-0/popen-gw0/test_cli_distortion_model_fish0/fisheye_frames')
out_path   = PosixPath('.../pytest-0/popen-gw0/test_cli_distortion_model_fish0/fisheye.yaml')
rows       = 6
tmp_path   = PosixPath('.../pytest-0/popen-gw0/test_cli_distortion_model_fish0')

.../cli/cameracalibrate/test_cameracalibrate.py:786: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../cli/cameracalibrate/cameracalibrate.py:785: in calibrate_from_frames
    rms, K, D = _calibrate_fisheye(objpoints, imgpoints, (w0, h0))
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        actual_cols = 9
        actual_rows = 6
        cols       = 9
        corners_found = array([[[     657.38,      344.51]],

       [[     674.04,      346.19]],

       [[     690.73,      347.89]],

    ...     747.28,       437.8]],

       [[     763.18,      439.14]],

       [[     778.77,      440.36]]], dtype=float32)
        distortion_model = <DistortionModel.fisheye: 'fisheye'>
        f          = array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8)
        first      = array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8)
        frame      = array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8)
        frames     = [array([[0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       ...,
       [0..., ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0],
       [0, 0, 0, ..., 0, 0, 0]], shape=(720, 1280), dtype=uint8), ...]
        h0         = 720
        i          = 14
        image_points_hint = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
        imgpoints  = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
        model      = <DistortionModel.fisheye: 'fisheye'>
        objp_flat  = array([[          0,           0,           0],
       [      0.025,           0,           0],
       [       0.05,  ...    0],
       [      0.175,       0.125,           0],
       [        0.2,       0.125,           0]], dtype=float32)
        objp_view  = array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[       ...,

       [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32)
        objpoints  = [array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[      ...    [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32), ...]
        pattern_hint = (9, 6, 'requested inner corners')
        pattern_label = 'requested inner corners'
        rows       = 6
        square_size_m = 0.025
        w0         = 1280
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

objpoints = [array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[      ...    [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32), ...]
imgpoints = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
image_size = (1280, 720)

    def _calibrate_fisheye(
        objpoints: list[np.ndarray],
        imgpoints: list[np.ndarray],
        image_size: tuple[int, int],
    ) -> tuple[float, np.ndarray, np.ndarray]:
        """Run ``cv2.fisheye.calibrate`` (4-coeff Kannala-Brandt).
    
        ``objpoints`` must be a list of ``(N, 1, 3)`` arrays and ``imgpoints`` a list of
        ``(N, 1, 2)`` arrays (the fisheye solver is strict about the extra middle axis).
        """
        K = np.zeros((3, 3), dtype=np.float64)
        D = np.zeros((4, 1), dtype=np.float64)
        n_views = len(objpoints)
        rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(n_views)]
        tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(n_views)]
>       flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC | cv2.fisheye.CALIB_FIX_SKEW
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E       AttributeError: module 'cv2.fisheye' has no attribute 'CALIB_RECOMPUTE_EXTRINSIC'

D          = array([[          0],
       [          0],
       [          0],
       [          0]])
K          = array([[          0,           0,           0],
       [          0,           0,           0],
       [          0,           0,           0]])
image_size = (1280, 720)
imgpoints  = [array([[[     621.68,      371.87]],

       [[     636.96,       368.2]],

       [[     652.13,      364.55]],

   ...70.42,      428.71]],

       [[     786.14,      424.64]],

       [[      801.3,       420.6]]], dtype=float32), ...]
n_views    = 15
objpoints  = [array([[[          0,           0,           0]],

       [[      0.025,           0,           0]],

       [[      ...    [[      0.175,       0.125,           0]],

       [[        0.2,       0.125,           0]]], dtype=float32), ...]
rvecs      = [array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), array([[[    ...    0]]]), array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), ...]
tvecs      = [array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), array([[[    ...    0]]]), array([[[          0,           0,           0]]]), array([[[          0,           0,           0]]]), ...]

.../cli/cameracalibrate/cameracalibrate.py:686: AttributeError
dimos.perception.fiducial.test_fixture_verification::test_marker_tf_replay_synthetic_packed_board_publishes_twelve_markers
Stack Traces | 0.087s run time
layout = BoardLayout(cols=3, rows=4, marker_length_m=0.05, tags={0: TagLayout(tag_id=0, col=0, row=0, bottom_left_m=array([    ...0912,           0],
       [       0.19,      0.0412,           0],
       [       0.14,      0.0412,           0]]))})

    def test_marker_tf_replay_synthetic_packed_board_publishes_twelve_markers(
        layout: BoardLayout,
    ) -> None:
        width, height = 1920, 1080
        bgr = _synthetic_packed_apriltag_board_bgr(layout, width=width, height=height)
        ts = 10_000.0
        cam_info = CameraInfo.from_intrinsics(
            1400.0,
            1400.0,
            width / 2.0,
            height / 2.0,
            width,
            height,
            frame_id="camera_optical",
        )
        cam_info.ts = ts
    
        image = Image.from_opencv(bgr, frame_id="camera_optical", ts=ts)
        world_T_optical = Transform(
            translation=Vector3(0.0, 0.0, 0.0),
            rotation=Quaternion(0.0, 0.0, 0.0, 1.0),
            frame_id="world",
            child_frame_id="camera_optical",
            ts=ts,
        )
>       detections = detect_markers_in_image(
            image,
            camera_info=cam_info,
            world_T_optical=world_T_optical,
            marker_length_m=0.05,
            aruco_dictionary="DICT_APRILTAG_36h11",
            world_frame="world",
        )

bgr        = array([[[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
     ...  ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]]], shape=(1080, 1920, 3), dtype=uint8)
cam_info   = CameraInfo(height=1080, width=1920, distortion_model='plumb_bob', frame_id='camera_optical', ts=10000.0)
height     = 1080
image      = Image(shape=(1080, 1920, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10000.0)
layout     = BoardLayout(cols=3, rows=4, marker_length_m=0.05, tags={0: TagLayout(tag_id=0, col=0, row=0, bottom_left_m=array([    ...0912,           0],
       [       0.19,      0.0412,           0],
       [       0.14,      0.0412,           0]]))})
ts         = 10000.0
width      = 1920
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))

.../perception/fiducial/test_fixture_verification.py:180: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

image = Image(shape=(1080, 1920, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10000.0)
camera_info = CameraInfo(height=1080, width=1920, distortion_model='plumb_bob', frame_id='camera_optical', ts=10000.0)
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
marker_length_m = 0.05, aruco_dictionary = 'DICT_APRILTAG_36h11'
world_frame = 'world', detector = < cv2.aruco.ArucoDetector 0x7f74814f6ad0>
camera_matrix = array([[       1400,           0,         960],
       [          0,        1400,         540],
       [          0,           0,           1]])
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])

    def detect_markers_in_image(
        image: Image,
        *,
        camera_info: CameraInfo,
        world_T_optical: Transform,
        marker_length_m: float,
        aruco_dictionary: str,
        world_frame: str = "world",
        detector: Any | None = None,
        camera_matrix: np.ndarray | None = None,
        dist_coeffs: np.ndarray | None = None,
    ) -> list[Detection3DMarker]:
        """Detect markers in one image and return rich world-frame 3D detections."""
        if marker_length_m <= 0:
            raise ValueError(f"marker_length_m must be > 0, got {marker_length_m}")
        if (
            camera_info.width
            and camera_info.height
            and (image.width != camera_info.width or image.height != camera_info.height)
        ):
            return []
    
        if detector is None:
            detector = create_aruco_detector(aruco_dictionary)
        if (camera_matrix is None) != (dist_coeffs is None):
            raise ValueError("camera_matrix and dist_coeffs must be provided together")
        if camera_matrix is None or dist_coeffs is None:
            camera_matrix, dist_coeffs = camera_info_to_cv_matrices(camera_info)
    
        gray = image.to_grayscale().as_numpy()
        corners, ids, _ = detector.detectMarkers(gray)
        if ids is None or len(ids) == 0:
            return []
    
        optical_frame = camera_optical_frame_id(image, camera_info)
        t_world_optical = Transform(
            translation=world_T_optical.translation,
            rotation=world_T_optical.rotation,
            frame_id=world_frame,
            child_frame_id=optical_frame,
            ts=image.ts,
        )
        marker_size = Vector3(marker_length_m, marker_length_m, 0.0)
        detections: list[Detection3DMarker] = []
    
        for corner_set, mid_arr in zip(corners, ids, strict=True):
>           mid = int(mid_arr[0])
                      ^^^^^^^^^^
E           IndexError: invalid index to scalar variable.

_          = (array([[[        465,         330],
        [        507,         331],
        [        506,         399],
        [...      756,         682],
        [        757,         724],
        [        717,         725]]], dtype=float32), ...)
aruco_dictionary = 'DICT_APRILTAG_36h11'
camera_info = CameraInfo(height=1080, width=1920, distortion_model='plumb_bob', frame_id='camera_optical', ts=10000.0)
camera_matrix = array([[       1400,           0,         960],
       [          0,        1400,         540],
       [          0,           0,           1]])
corner_set = array([[[        566,         806],
        [        775,         806],
        [        775,        1015],
        [        566,        1015]]], dtype=float32)
corners    = (array([[[        566,         806],
        [        775,         806],
        [        775,        1015],
        [...      274,         559],
        [        274,         768],
        [         65,         768]]], dtype=float32), ...)
detections = []
detector   = < cv2.aruco.ArucoDetector 0x7f74814f6ad0>
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...     [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(1080, 1920), dtype=uint8)
ids        = array([11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0], dtype=int32)
image      = Image(shape=(1080, 1920, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10000.0)
marker_length_m = 0.05
marker_size = Vector([       0.05        0.05           0])
mid_arr    = np.int32(11)
optical_frame = 'camera_optical'
t_world_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_frame = 'world'

.../perception/fiducial/marker_detect.py:85: IndexError
dimos.perception.fiducial.test_fixture_verification::test_synthetic_packed_board_detects_all_twelve_ids_and_layout_homography
Stack Traces | 0.097s run time
layout = BoardLayout(cols=3, rows=4, marker_length_m=0.05, tags={0: TagLayout(tag_id=0, col=0, row=0, bottom_left_m=array([    ...0912,           0],
       [       0.19,      0.0412,           0],
       [       0.14,      0.0412,           0]]))})

    def test_synthetic_packed_board_detects_all_twelve_ids_and_layout_homography(
        layout: BoardLayout,
    ) -> None:
        width, height = 1920, 1080
        bgr = _synthetic_packed_apriltag_board_bgr(layout, width=width, height=height)
        gray = cv2.cvtColor(bgr, cv2.COLOR_BGR2GRAY)
        det = cv2.aruco.ArucoDetector(
            cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_APRILTAG_36h11),
            cv2.aruco.DetectorParameters(),
        )
        corners, ids, _ = det.detectMarkers(gray)
        assert ids is not None and len(ids) == 12
        detected = sorted(int(np.asarray(i).reshape(-1)[0]) for i in ids)
        assert detected == list(range(12))
    
        corners_by_id: dict[int, np.ndarray] = {}
        for corner_set, id_arr in zip(corners, ids, strict=True):
>           corners_by_id[int(id_arr[0])] = np.asarray(corner_set, dtype=np.float32).reshape(4, 2)
                              ^^^^^^^^^
E           IndexError: invalid index to scalar variable.

_          = (array([[[        465,         330],
        [        507,         331],
        [        506,         399],
        [...      756,         682],
        [        757,         724],
        [        717,         725]]], dtype=float32), ...)
bgr        = array([[[255, 255, 255],
        [255, 255, 255],
        [255, 255, 255],
        ...,
        [255, 255, 255],
     ...  ...,
        [255, 255, 255],
        [255, 255, 255],
        [255, 255, 255]]], shape=(1080, 1920, 3), dtype=uint8)
corner_set = array([[[        566,         806],
        [        775,         806],
        [        775,        1015],
        [        566,        1015]]], dtype=float32)
corners    = (array([[[        566,         806],
        [        775,         806],
        [        775,        1015],
        [...      274,         559],
        [        274,         768],
        [         65,         768]]], dtype=float32), ...)
corners_by_id = {}
det        = < cv2.aruco.ArucoDetector 0x7f74814f5c10>
detected   = [0, 1, 2, 3, 4, 5, ...]
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...     [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(1080, 1920), dtype=uint8)
height     = 1080
id_arr     = np.int32(11)
ids        = array([11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0], dtype=int32)
layout     = BoardLayout(cols=3, rows=4, marker_length_m=0.05, tags={0: TagLayout(tag_id=0, col=0, row=0, bottom_left_m=array([    ...0912,           0],
       [       0.19,      0.0412,           0],
       [       0.14,      0.0412,           0]]))})
width      = 1920

.../perception/fiducial/test_fixture_verification.py:148: IndexError
dimos.perception.fiducial.test_marker_detection_stream_module::test_marker_detection_stream_pipeline_outputs_arrays_for_marker_and_empty_frame
Stack Traces | 0.115s run time
def test_marker_detection_stream_pipeline_outputs_arrays_for_marker_and_empty_frame() -> None:
        marker_id = 7
        marker_length_m = 0.18
        marker_image = synthetic_marker_image(marker_id, ts=10.0)
        empty_image = blank_image(ts=11.0)
    
        module = MarkerDetectionStreamModule(
            marker_length_m=marker_length_m,
            camera_info=camera_info(marker_image.ts),
            quality_window_s=0.01,
        )
        try:
            with MemoryStore() as store:
                stream = store.stream("color_image", Image)
                stream.append(
                    marker_image,
                    ts=marker_image.ts,
                    pose=(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
                )
                stream.append(
                    empty_image,
                    ts=empty_image.ts,
                    pose=(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0),
                )
    
>               outputs = [obs.data for obs in module.pipeline(stream).to_list()]
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

empty_image = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=11.0)
marker_id  = 7
marker_image = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10.0)
marker_length_m = 0.18
module     = <dimos.perception.fiducial.marker_detection_stream_module.MarkerDetectionStreamModule object at 0x7fb53eac5010>
store      = <dimos.memory2.store.memory.MemoryStore object at 0x7fb53eac5eb0>
stream     = <dimos.memory2.stream.Stream object at 0x7fb53eadfe00>

.../perception/fiducial/test_marker_detection_stream_module.py:160: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
dimos/memory2/stream.py:476: in to_list
    return list(self)
           ^^^^^^^^^^
        self       = <dimos.memory2.stream.Stream object at 0x7fb53eac33e0>
.../perception/fiducial/marker_transformer.py:337: in __call__
    for obs in upstream:
        flush      = <function MarkersPerFrame.__call__.<locals>.flush at 0x7fb52a9b2020>
        pending    = []
        pending_obs = None
        pending_ts = None
        self       = #x1B[36mMarkersPerFrame#x1B[0m(frame_id='world')
        upstream   = <generator object DetectMarkers.__call__ at 0x7fb52a915cf0>
.../perception/fiducial/marker_transformer.py:224: in __call__
    detections = _detect_markers_in_image(
        image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10.0)
        image_size_mismatch = False
        info       = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=10.0)
        obs        = Observation(id=0, ts=10.0, data_type=<class 'dimos.msgs.sensor_msgs.Image.Image'>, pose_tuple=(0.0, 0.0, 0.0, 0.0, 0.0...=uint8, frame_id='camera_optical', ts=10.0), _loader=None, _data_lock=<unlocked _thread.lock object at 0x7fb52a9a6540>)
        optical_frame = 'camera_optical'
        pose_tuple = (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ...)
        self       = #x1B[36mDetectMarkers#x1B[0m(camera_info=CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_op...ngth_m=0.18, aruco_dictionary='DICT_APRILTAG_36h11', world_frame='world', smoothing_window=0.0, emit_empty_frames=True)
        t_world_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
        upstream   = <generator object QualityWindow.__call__ at 0x7fb53eb8d8b0>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

image = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10.0)
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=10.0)
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
marker_length_m = 0.18, aruco_dictionary = 'DICT_APRILTAG_36h11'
world_frame = 'world', detector = < cv2.aruco.ArucoDetector 0x7fb53eaa5790>
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])

    def detect_markers_in_image(
        image: Image,
        *,
        camera_info: CameraInfo,
        world_T_optical: Transform,
        marker_length_m: float,
        aruco_dictionary: str,
        world_frame: str = "world",
        detector: Any | None = None,
        camera_matrix: np.ndarray | None = None,
        dist_coeffs: np.ndarray | None = None,
    ) -> list[Detection3DMarker]:
        """Detect markers in one image and return rich world-frame 3D detections."""
        if marker_length_m <= 0:
            raise ValueError(f"marker_length_m must be > 0, got {marker_length_m}")
        if (
            camera_info.width
            and camera_info.height
            and (image.width != camera_info.width or image.height != camera_info.height)
        ):
            return []
    
        if detector is None:
            detector = create_aruco_detector(aruco_dictionary)
        if (camera_matrix is None) != (dist_coeffs is None):
            raise ValueError("camera_matrix and dist_coeffs must be provided together")
        if camera_matrix is None or dist_coeffs is None:
            camera_matrix, dist_coeffs = camera_info_to_cv_matrices(camera_info)
    
        gray = image.to_grayscale().as_numpy()
        corners, ids, _ = detector.detectMarkers(gray)
        if ids is None or len(ids) == 0:
            return []
    
        optical_frame = camera_optical_frame_id(image, camera_info)
        t_world_optical = Transform(
            translation=world_T_optical.translation,
            rotation=world_T_optical.rotation,
            frame_id=world_frame,
            child_frame_id=optical_frame,
            ts=image.ts,
        )
        marker_size = Vector3(marker_length_m, marker_length_m, 0.0)
        detections: list[Detection3DMarker] = []
    
        for corner_set, mid_arr in zip(corners, ids, strict=True):
>           mid = int(mid_arr[0])
                      ^^^^^^^^^^
E           IndexError: invalid index to scalar variable.

_          = (array([[[        341,         149],
        [        383,         151],
        [        381,         193],
        [...  [        402,         212],
        [        403,         239],
        [        375,         240]]], dtype=float32))
aruco_dictionary = 'DICT_APRILTAG_36h11'
camera_info = CameraInfo(height=480, width=640, distortion_model='plumb_bob', frame_id='camera_optical', ts=10.0)
camera_matrix = array([[        600,           0,         320],
       [          0,         600,         240],
       [          0,           0,           1]])
corner_set = array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32)
corners    = (array([[[        210,         130],
        [        429,         130],
        [        429,         349],
        [        210,         349]]], dtype=float32),)
detections = []
detector   = < cv2.aruco.ArucoDetector 0x7fb53eaa5790>
dist_coeffs = array([[          0],
       [          0],
       [          0],
       [          0],
       [          0]])
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(480, 640), dtype=uint8)
ids        = array([7], dtype=int32)
image      = Image(shape=(480, 640, 3), format=BGR, dtype=uint8, frame_id='camera_optical', ts=10.0)
marker_length_m = 0.18
marker_size = Vector([       0.18        0.18           0])
mid_arr    = np.int32(7)
optical_frame = 'camera_optical'
t_world_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_T_optical = Transform(translation=Vector([          0           0           0]), rotation=Quaternion(0.000000, 0.000000, 0.000000, 1.000000))
world_frame = 'world'

.../perception/fiducial/marker_detect.py:85: IndexError
dimos.control.tasks.test_registry::test_declared_task_factory_paths_resolve
Stack Traces | 0.136s run time
def test_declared_task_factory_paths_resolve() -> None:
        for name, factory_path in sorted(control_task_registry._factory_paths.items()):
            module_name, attr = factory_path.split(":", maxsplit=1)
            try:
>               module = importlib.import_module(module_name)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

attr       = 'create_task'
factory_path = 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task:create_task'
module_name = 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task'
name       = 'cartesian_ik'

.../control/tasks/test_registry.py:64: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
........./usr/lib/python3.12/importlib/__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        level      = 0
        name       = 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task'
        package    = None
<frozen importlib._bootstrap>:1387: in _gcd_import
    ???
        level      = 0
        name       = 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task'
        package    = None
<frozen importlib._bootstrap>:1360: in _find_and_load
    ???
        import_    = <function _gcd_import at 0x7fb71fba40e0>
        module     = <object object at 0x7fb71fb78060>
        name       = 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task'
<frozen importlib._bootstrap>:1331: in _find_and_load_unlocked
    ???
        child      = 'cartesian_ik_task'
        import_    = <function _gcd_import at 0x7fb71fba40e0>
        name       = 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task'
        parent     = 'dimos.control.tasks.cartesian_ik_task'
        parent_module = <module 'dimos.control.tasks.cartesian_ik_task' (namespace) from ['.../control/tasks/cartesian_ik_task']>
        parent_spec = ModuleSpec(name='dimos.control.tasks.cartesian_ik_task', loader=<_frozen_importlib_external.NamespaceLoader object at ...0>, submodule_search_locations=_NamespacePath(['.../control/tasks/cartesian_ik_task']))
        path       = _NamespacePath(['.../control/tasks/cartesian_ik_task'])
        spec       = ModuleSpec(name='dimos.control.tasks.cartesian_ik_task.cartesian_ik_task', loader=<_frozen_importlib_external.SourceFi... at 0x7fb52a9100e0>, origin='.../control/tasks/cartesian_ik_task/cartesian_ik_task.py')
<frozen importlib._bootstrap>:935: in _load_unlocked
    ???
        module     = <module 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task' from '.../control/tasks/cartesian_ik_task/cartesian_ik_task.py'>
        spec       = ModuleSpec(name='dimos.control.tasks.cartesian_ik_task.cartesian_ik_task', loader=<_frozen_importlib_external.SourceFi... at 0x7fb52a9100e0>, origin='.../control/tasks/cartesian_ik_task/cartesian_ik_task.py')
<frozen importlib._bootstrap_external>:995: in exec_module
    ???
        code       = <code object <module> at 0x7fb52a9370a0, file ".../control/tasks/cartesian_ik_task/cartesian_ik_task.py", line 1>
        module     = <module 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task' from '.../control/tasks/cartesian_ik_task/cartesian_ik_task.py'>
        self       = <_frozen_importlib_external.SourceFileLoader object at 0x7fb52a9100e0>
<frozen importlib._bootstrap>:488: in _call_with_frames_removed
    ???
        args       = (<code object <module> at 0x7fb52a9370a0, file ".../control/tasks/cartesian_ik_task/ca...l.tasks.cartesian_ik_task', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fb52a9100e0>, ...})
        f          = <built-in function exec>
        kwds       = {}
.../tasks/cartesian_ik_task/cartesian_ik_task.py:38: in <module>
    from dimos.manipulation.planning.kinematics.pinocchio_ik import (
        Any        = typing.Any
        BaseControlTask = <class 'dimos.control.task.BaseControlTask'>
        ControlMode = <enum 'ControlMode'>
        CoordinatorState = <class 'dimos.control.task.CoordinatorState'>
        JointCommandOutput = <class 'dimos.control.task.JointCommandOutput'>
        Path       = <class 'pathlib.Path'>
        ResourceClaim = <class 'dimos.control.task.ResourceClaim'>
        TYPE_CHECKING = False
        __builtins__ = <builtins>
        __cached__ = '.../control/tasks/cartesian_ik_task/__pycache__/cartesian_ik_task.cpython-312.pyc'
        __doc__    = 'Cartesian control task with internal Pinocchio IK solver.\n\nAccepts streaming cartesian poses (e.g., from teleoperat...ing)\nand computes inverse kinematics internally to output joint commands.\nParticipates in joint-level arbitration.\n'
        __file__   = '.../control/tasks/cartesian_ik_task/cartesian_ik_task.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fb52a9100e0>
        __name__   = 'dimos.control.tasks.cartesian_ik_task.cartesian_ik_task'
        __package__ = 'dimos.control.tasks.cartesian_ik_task'
        __spec__   = ModuleSpec(name='dimos.control.tasks.cartesian_ik_task.cartesian_ik_task', loader=<_frozen_importlib_external.SourceFi... at 0x7fb52a9100e0>, origin='.../control/tasks/cartesian_ik_task/cartesian_ik_task.py')
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        dataclass  = <function dataclass at 0x7fb71f14c040>
        np         = <module 'numpy' from '.../dimos/dimos/.venv/lib/python3.12........./site-packages/numpy/__init__.py'>
        threading  = <module 'threading' from '........./usr/lib/python3.12/threading.py'>
.../planning/kinematics/pinocchio_ik.py:40: in <module>
    import pinocchio
        Any        = typing.Any
        Path       = <class 'pathlib.Path'>
        TYPE_CHECKING = False
        __builtins__ = <builtins>
        __cached__ = '.../kinematics/__pycache__/pinocchio_ik.cpython-312.pyc'
        __doc__    = 'Pinocchio-based inverse kinematics solver.\n\nStandalone IK solver using Pinocchio for forward kinematics and Jacobia...>>> q_solution, converged, error = ik.solve(target_se3, q_init)\n    >>> ee_pose = ik.forward_kinematics(q_solution)\n'
        __file__   = '/home/runner/work/dimos/dimos/.../planning/kinematics/pinocchio_ik.py'
        __loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fb52a913fe0>
        __name__   = 'dimos.manipulation.planning.kinematics.pinocchio_ik'
        __package__ = 'dimos.manipulation.planning.kinematics'
        __spec__   = ModuleSpec(name='dimos.manipulation.planning.kinematics.pinocchio_ik', loader=<_frozen_importlib_external.SourceFileLo...ject at 0x7fb52a913fe0>, origin='/home/runner/work/dimos/dimos/.../planning/kinematics/pinocchio_ik.py')
        annotations = _Feature((3, 7, 0, 'beta', 1), None, 16777216)
        dataclass  = <function dataclass at 0x7fb71f14c040>
        norm       = <function norm at 0x7fb713b7ad30>
        np         = <module 'numpy' from '.../dimos/dimos/.venv/lib/python3.12........./site-packages/numpy/__init__.py'>
        solve      = <function solve at 0x7fb713b78e30>
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    #
    # Copyright (c) 2015-2021 CNRS INRIA
    #
    # ruff: noqa: E402, F401, F403, F405
    
    import numpy
    
    # On Windows, if pinocchio.dll is not in the same directory than
    # the .pyd, it will not be loaded.
    # We first try to load pinocchio, then, if it fail and we are on Windows:
    #  1. We add all paths inside PINOCCHIO_WINDOWS_DLL_PATH to DllDirectory
    #  2. If PINOCCHIO_WINDOWS_DLL_PATH we add the relative path from the
    #     package directory to the bin directory to DllDirectory
    # This solution is inspired from:
    #  - https://github..../pull/1511/files
    #  - https://stackoverflow..../questions/65334494/python-c-extension-packaging-dll-along-with-pyd
    # More resources on https://github..../pyobjcryst/issues/33
    try:
>       from .pinocchio_pywrap_default import *
E       ImportError: libtinyxml2.so.11: cannot open shared object file: No such file or directory

__builtins__ = <builtins>
__cached__ = '.../dimos/dimos/.venv/lib/python3.12/site-packages/cmeel.prefix/lib/python3.12.../pinocchio/__pycache__/__init__.cpython-312.pyc'
__doc__    = None
__file__   = '.../dimos/dimos/.venv/lib/python3.12/site-packages/cmeel.prefix/lib/python3.12....../site-packages/pinocchio/__init__.py'
__loader__ = <_frozen_importlib_external.SourceFileLoader object at 0x7fb53eade930>
__name__   = 'pinocchio'
__package__ = 'pinocchio'
__path__   = ['.../dimos/dimos/.venv/lib/python3.12/site-packages/cmeel.prefix/lib/python3.12/site-packages/pinocchio']
__spec__   = ModuleSpec(name='pinocchio', loader=<_frozen_importlib_external.SourceFileLoader object at 0x7fb53eade930>, origin='/h....../dimos/dimos/.venv/lib/python3.12/site-packages/cmeel.prefix/lib/python3.12/site-packages/pinocchio'])
numpy      = <module 'numpy' from '.../dimos/dimos/.venv/lib/python3.12........./site-packages/numpy/__init__.py'>
platform   = <module 'platform' from '........./usr/lib/python3.12/platform.py'>

.venv/lib/python3.12/site-packages/cmeel.prefix/lib/python3.12....../site-packages/pinocchio/__init__.py:19: ImportError
dimos.utils.cli.cameracalibrate.test_cameracalibrate::test_find_chessboard_corners_synthetic_board_returns_expected_count
Stack Traces | 0.183s run time
def test_find_chessboard_corners_synthetic_board_returns_expected_count() -> None:
        cols, rows = 9, 6
        gray = _synthetic_chessboard_gray(640, 480, cols, rows, square_px=40)
        corners = find_chessboard_corners(gray, cols, rows)
        assert corners is not None
>       assert corners.shape == (cols * rows, 1, 2)
E       assert (54, 2) == (54, 1, 2)
E         
E         At index 1 diff: #x1B[0m#x1B[94m2#x1B[39;49;00m#x1B[90m#x1B[39;49;00m != #x1B[0m#x1B[94m1#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         Right contains one more item: #x1B[0m#x1B[94m2#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         
E         Full diff:
E         #x1B[0m#x1B[90m #x1B[39;49;00m (#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m     54,#x1B[90m#x1B[39;49;00m
E         #x1B[91m-     1,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m     2,#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m )#x1B[90m#x1B[39;49;00m

cols       = 9
corners    = array([[      159.5,       139.5],
       [      199.5,       139.5],
       [      239.5,       139.5],
       [     ...      [      399.5,       339.5],
       [      439.5,       339.5],
       [      479.5,       339.5]], dtype=float32)
gray       = array([[255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 25...       [255, 255, 255, ..., 255, 255, 255],
       [255, 255, 255, ..., 255, 255, 255]], shape=(480, 640), dtype=uint8)
rows       = 6

.../cli/cameracalibrate/test_cameracalibrate.py:630: AssertionError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

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

Labels

dependencies Pull requests that update a dependency file python:uv Pull requests that update python:uv code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants