diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..07fe41c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# GitHub syntax highlighting +pixi.lock linguist-language=YAML linguist-generated=true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 424aeac..07ef7af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,15 +2,33 @@ name: Upload Python Package on: push: - tags: "*" permissions: contents: read jobs: - deploy: + ruff-check: runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: "3.11" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pre-commit + - name: Run pre-commit to check + run: pre-commit run --all-files --color always --verbose + # TODO: Add a step to run tests + + deploy: + runs-on: ubuntu-latest + needs: ruff-check + # run on tag only + if: startsWith(github.ref, 'refs/tags/') steps: - uses: actions/checkout@v3 - name: Set up Python @@ -23,8 +41,16 @@ jobs: pip install build - name: Build package run: python -m build --wheel + + - name: Publish package to the test PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.TEST_PYPI_TOKEN }} + repository-url: https://test.pypi.org/legacy/ + - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} diff --git a/.gitignore b/.gitignore index eb88869..1d5d4a7 100644 --- a/.gitignore +++ b/.gitignore @@ -161,4 +161,6 @@ cython_debug/ #.idea/ *TODO .vscode* -*old \ No newline at end of file +*old# pixi environments +.pixi +*.egg-info diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e5b9194..fd13093 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,13 @@ repos: - - repo: https://github.com/psf/black - rev: "22.3.0" + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.6.3 hooks: - - id: black-jupyter + # Run the formatter. + - id: ruff-format + types_or: [python, pyi, jupyter] + + - repo: https://github.com/kynan/nbstripout + rev: 0.7.1 + hooks: + - id: nbstripout diff --git a/darli/__init__.py b/darli/__init__.py index ac80a2c..e69de29 100644 --- a/darli/__init__.py +++ b/darli/__init__.py @@ -1,3 +0,0 @@ -import casadi_kin_dyn.casadi_kin_dyn as _ # noqa: F401 - -import darli.backend # noqa: F401 diff --git a/darli/backend/__init__.py b/darli/backend/__init__.py index 8572384..58ef022 100644 --- a/darli/backend/__init__.py +++ b/darli/backend/__init__.py @@ -1,11 +1,12 @@ from ._base import ( BackendBase, - Frame, - BodyInfo, + # Frame, + # BodyInfo, ConeBase, PinocchioBased, - JointType, - CentroidalDynamics, + # JointType, + # CentroidalDynamics, ) # noqa: F401 from ._casadi import CasadiBackend, CasadiCone # noqa: F401 from ._pinocchio import PinocchioBackend, PinocchioCone # noqa: F401 +from ._structs import Frame, BodyInfo, CentroidalDynamics, JointType diff --git a/darli/backend/_base.py b/darli/backend/_base.py index 1a6eea1..e036142 100644 --- a/darli/backend/_base.py +++ b/darli/backend/_base.py @@ -1,87 +1,34 @@ from abc import ABC, abstractmethod -from enum import Enum -from dataclasses import dataclass -from typing import Dict, List +from typing import Callable, Dict, List from ..utils.arrays import ArrayLike, ArrayLikeFactory +from ._structs import JointType, BodyInfo, CentroidalDynamics import pinocchio as pin import numpy as np import numpy.typing as npt +import os -class Frame(Enum): - LOCAL = 1 - WORLD = 2 - LOCAL_WORLD_ALIGNED = 3 +def parse_description_type(description_path: str) -> Callable: + """Returns the appropriate Pinocchio model builder based on file extension. - @classmethod - def from_str(cls, string: str) -> "Frame": - if string == "local": - return cls.LOCAL - elif string == "world": - return cls.WORLD - elif string == "world_aligned": - return cls.LOCAL_WORLD_ALIGNED - else: - raise ValueError(f"Unknown frame type: {string}") - - -class JointType(Enum): - OMIT = 1 # empty = none = no joint = skip - FREE_FLYER = 2 - PLANAR = 3 - - @classmethod - def from_str(cls, string: str) -> "JointType": - if string == "omit": - return cls.OMIT - elif string == "free_flyer": - return cls.FREE_FLYER - elif string == "planar": - return cls.PLANAR - else: - raise ValueError(f"Unknown joint type: {string}") - - -@dataclass -class BodyInfo: - position: ArrayLike - rotation: ArrayLike - quaternion: ArrayLike - jacobian: Dict[Frame, ArrayLike] - djacobian: Dict[Frame, ArrayLike] - lin_vel: Dict[Frame, ArrayLike] - ang_vel: Dict[Frame, ArrayLike] - lin_acc: Dict[Frame, ArrayLike] - ang_acc: Dict[Frame, ArrayLike] + Args: + description_path (str): Path to the description file. + Returns: + Callable: Pinocchio model builder function. -@dataclass -class CentroidalDynamics: - """ - linear: linear momentum - angular: angular momentum - linear_dt: linear momentum derivative - angular_dt: angular momentum derivative - matrix: centroidal momentum matrix - matrix_dt: same as linear momentum derivative w.r.t. q - dynamics_jacobian_q: momentum derivative w.r.t. q - dynamics_jacobian_v: momentum derivative w.r.t. v - dynamics_jacobian_vdot: momentum derivative w.r.t. dv - - Under the hood uses pinocchio methods: - - computeCentroidalMomentumTimeVariation - - computeCentroidalDynamicsDerivatives + Raises: + ValueError: If the file extension is not recognized. """ + _, ext = os.path.splitext(description_path) + ext = ext.lower() - linear: ArrayLike - angular: ArrayLike - linear_dt: ArrayLike - angular_dt: ArrayLike - matrix: ArrayLike - matrix_dt: ArrayLike - dynamics_jacobian_q: ArrayLike - dynamics_jacobian_v: ArrayLike - dynamics_jacobian_dv: ArrayLike + if ext == ".urdf": + return pin.buildModelFromUrdf + elif ext == ".xml": + return pin.buildModelFromMJCF + else: + raise ValueError(f"Unrecognized description extension: {ext}") class ConeBase(ABC): @@ -97,27 +44,25 @@ def linear(self, force: ArrayLike | None) -> ArrayLike: class PinocchioBased: def __init__( self, - urdf_path: str, + description_path: str, root_joint: JointType | None = None, fixed_joints: Dict[str, float | npt.ArrayLike] = None, ) -> None: if fixed_joints is None: fixed_joints = {} - self.__urdf_path = urdf_path + self.__description_path = description_path joint_types = { JointType.FREE_FLYER: pin.JointModelFreeFlyer(), JointType.PLANAR: pin.JointModelPlanar(), } - + builder = parse_description_type(description_path) # pass root_joint if specified if root_joint is None or root_joint == JointType.OMIT: - model: pin.Model = pin.buildModelFromUrdf(urdf_path) + model: pin.Model = builder(description_path) else: - model: pin.Model = pin.buildModelFromUrdf( - urdf_path, joint_types[root_joint] - ) + model: pin.Model = builder(description_path, joint_types[root_joint]) # freeze joints and update coordinate freeze_joint_indices = [] @@ -145,9 +90,9 @@ def __init__( self._pindata: pin.Data = self._pinmodel.createData() @property - def urdf_path(self) -> str: + def description_path(self) -> str: """Returns the path to the URDF file used to build the model.""" - return self.__urdf_path + return self.__description_path @property def total_mass(self) -> float: @@ -324,7 +269,7 @@ def centroidal_dynamics( pass @abstractmethod - def update_body(self, body: str, body_urdf_name: str = None) -> BodyInfo: + def update_body(self, body: str, body_description_name: str = None) -> BodyInfo: pass @abstractmethod @@ -339,5 +284,4 @@ def integrate_configuration( q: ArrayLike | None = None, v: ArrayLike | None = None, dt: float = 1, - ) -> ArrayLike: - ... + ) -> ArrayLike: ... diff --git a/darli/backend/_casadi.py b/darli/backend/_casadi.py index 986a22a..a0b6ad6 100644 --- a/darli/backend/_casadi.py +++ b/darli/backend/_casadi.py @@ -1,7 +1,8 @@ -import casadi_kin_dyn.casadi_kin_dyn as ckd - +import pinocchio.casadi as cpin +import pinocchio as pin from .liecasadi import SO3 -from ._base import BackendBase, ConeBase, Frame, BodyInfo, JointType, CentroidalDynamics +from ._base import BackendBase, ConeBase +from ._structs import Frame, BodyInfo, CentroidalDynamics, JointType from ..utils.arrays import CasadiLikeFactory, ArrayLike import casadi as cs from typing import Dict @@ -153,30 +154,17 @@ class CasadiBackend(BackendBase): def __init__( self, - urdf_path: str, + description_path: str, root_joint: JointType | None = JointType.OMIT, fixed_joints: Dict[str, float | npt.ArrayLike] = None, ) -> None: - super().__init__(urdf_path) - if not fixed_joints: - fixed_joints = {} - - self.__joint_types = { - JointType.FREE_FLYER: ckd.CasadiKinDyn.JointType.FREE_FLYER, - JointType.PLANAR: ckd.CasadiKinDyn.JointType.PLANAR, - JointType.OMIT: ckd.CasadiKinDyn.JointType.OMIT, - } + super().__init__(description_path, root_joint, fixed_joints) - self.__urdf_path: str = urdf_path - urdf = open(self.__urdf_path, "r").read() - self.__kindyn: ckd.CasadiKinDyn = ckd.CasadiKinDyn( - urdf, - root_joint=self.__joint_types[root_joint], - fixed_joints=fixed_joints, - ) + self.__model: cpin.Model = cpin.Model(self._pinmodel) + self.__data: cpin.Data = self.__model.createData() - self.__nq = self.__kindyn.nq() - self.__nv = self.__kindyn.nv() + self.__nq = self.__model.nq + self.__nv = self.__model.nv self.__nu = self.__nv self._q = cs.SX.sym("q", self.__nq) @@ -186,12 +174,13 @@ def __init__( self._tau = cs.SX.sym("tau", self.__nv) self.__frame_mapping = { - "local": ckd.CasadiKinDyn.LOCAL, - "world": ckd.CasadiKinDyn.WORLD, - "world_aligned": ckd.CasadiKinDyn.LOCAL_WORLD_ALIGNED, + "local": pin.LOCAL, + "world": pin.WORLD, + "world_aligned": pin.LOCAL_WORLD_ALIGNED, } self.__frame_types = self.__frame_mapping.keys() + self.__centroidal_derivatives = None @property def nq(self) -> int: @@ -216,17 +205,24 @@ def update( if tau is not None: self._tau = tau + if dv is not None or tau is not None: + self.__centroidal_derivatives = cpin.computeCentroidalDynamicsDerivatives( + self.__model, self.__data, self._q, self._v, self._dv + ) + def rnea( self, q: ArrayLike | None = None, v: ArrayLike | None = None, dv: ArrayLike | None = None, ) -> ArrayLike: - return self.__kindyn.rnea()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - a=dv if dv is not None else self._dv, - )["tau"] + return cpin.rnea( + self.__model, + self.__data, + q if q is not None else self._q, + v if v is not None else self._v, + dv if dv is not None else self._dv, + ) def aba( self, @@ -234,29 +230,36 @@ def aba( v: ArrayLike | None = None, tau: ArrayLike | None = None, ) -> ArrayLike: - return self.__kindyn.aba()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - tau=tau if tau is not None else self._tau, - )["a"] + return cpin.aba( + self.__model, + self.__data, + q if q is not None else self._q, + v if v is not None else self._v, + tau if tau is not None else self._tau, + ) def inertia_matrix(self, q: ArrayLike | None = None) -> ArrayLike: - return self.__kindyn.crba()(q=q if q is not None else self._q)["B"] + return cpin.crba(self.__model, self.__data, q if q is not None else self._q) def kinetic_energy( self, q: ArrayLike | None = None, v: ArrayLike | None = None ) -> ArrayLike: - return self.__kindyn.kineticEnergy()( - q=q if q is not None else self._q, v=v if v is not None else self._v - )["DT"] + return cpin.computeKineticEnergy( + self.__model, + self.__data, + q if q is not None else self._q, + v if v is not None else self._v, + ) def potential_energy(self, q: ArrayLike | None = None) -> ArrayLike: - return self.__kindyn.potentialEnergy()(q=q if q is not None else self._q)["DU"] + return cpin.computePotentialEnergy( + self.__model, self.__data, q if q is not None else self._q + ) def jacobian(self, q: ArrayLike | None = None) -> ArrayLike: - return self.__kindyn.jacobianCenterOfMass(False)( - q=q if q is not None else self._q - )["Jcom"] + return cpin.jacobianCenterOfMass( + self.__model, self.__data, q if q is not None else self._q + ) def jacobian_dt( self, q: ArrayLike | None = None, v: ArrayLike | None = None @@ -271,20 +274,21 @@ def jacobian_dt( ) def com_pos(self, q: ArrayLike | None = None) -> ArrayLike: - return self.__kindyn.centerOfMass()( - q=q if q is not None else self._q, - v=self.math.zeros(self.nv).array, - a=self.math.zeros(self.nv).array, - )["com"] + return cpin.centerOfMass( + self.__model, self.__data, q if q is not None else self._q + ) def com_vel( self, q: ArrayLike | None = None, v: ArrayLike | None = None ) -> ArrayLike: - return self.__kindyn.centerOfMass()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - a=self.math.zeros(self.nv).array, - )["vcom"] + cpin.centerOfMass( + self.__model, + self.__data, + q if q is not None else self._q, + v if v is not None else self._v, + ) + + return self.__data.vcom[0] def com_acc( self, @@ -292,11 +296,15 @@ def com_acc( v: ArrayLike | None = None, dv: ArrayLike | None = None, ) -> ArrayLike: - return self.__kindyn.centerOfMass()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - a=dv if dv is not None else self._dv, - )["acom"] + cpin.centerOfMass( + self.__model, + self.__data, + q if q is not None else self._q, + v if v is not None else self._v, + dv if dv is not None else self._dv, + ) + + return self.__data.acom[0] def torque_regressor( self, @@ -304,29 +312,35 @@ def torque_regressor( v: ArrayLike | None = None, dv: ArrayLike | None = None, ) -> ArrayLike: - return self.__kindyn.jointTorqueRegressor()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - a=dv if dv is not None else self._dv, - )["regressor"] + return cpin.computeJointTorqueRegressor( + self.__model, + self.__data, + q if q is not None else self._q, + v if v is not None else self._v, + dv if dv is not None else self._dv, + ) def kinetic_regressor( self, q: ArrayLike | None = None, v: ArrayLike | None = None, ) -> ArrayLike: - return self.__kindyn.kineticEnergyRegressor()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - )["kinetic_regressor"] + return cpin.computeKineticEnergyRegressor( + self.__model, + self.__data, + q if q is not None else self._q, + v if v is not None else self._v, + ) def potential_regressor( self, q: ArrayLike | None = None, ) -> ArrayLike: - return self.__kindyn.potentialEnergyRegressor()( - q=q if q is not None else self._q, - )["potential_regressor"] + return cpin.computePotentialEnergyRegressor( + self.__model, + self.__data, + q if q is not None else self._q, + ) def _spatial_kinetic_energy_jacobian(self): # Define CasADi symbolic variables @@ -364,6 +378,7 @@ def momentum_regressor( q_inp: ArrayLike | None = None, v_inp: ArrayLike | None = None, ): + raise NotImplementedError("This function is not implemented yet") # store functions spatial_kinetic_energy_jacobian = self._spatial_kinetic_energy_jacobian() torque_reg_fn = self.__kindyn.jointTorqueRegressor() @@ -431,52 +446,57 @@ def momentum_regressor( v_inp if v_inp is not None else self._v, ) - def update_body(self, body: str, body_urdf_name: str = None) -> BodyInfo: + def update_body(self, body: str, body_urdf_name: str | None = None) -> BodyInfo: if body_urdf_name is None: body_urdf_name = body - return BodyInfo( - position=self.__kindyn.fk(body_urdf_name)(q=self._q)["ee_pos"], - rotation=self.__kindyn.fk(body_urdf_name)(q=self._q)["ee_rot"], - quaternion=SO3.from_matrix( - self.__kindyn.fk(body_urdf_name)(q=self._q)["ee_rot"] - ).xyzw, - jacobian={ - Frame.from_str(frame): self.__kindyn.jacobian( - body_urdf_name, self.__frame_mapping[frame] - )(q=self._q)["J"] - for frame in self.__frame_types - }, - lin_vel={ - Frame.from_str(frame): self.__kindyn.frameVelocity( - body_urdf_name, self.__frame_mapping[frame] - )(q=self._q, qdot=self._v)["ee_vel_linear"] - for frame in self.__frame_types - }, - ang_vel={ - Frame.from_str(frame): self.__kindyn.frameVelocity( - body_urdf_name, self.__frame_mapping[frame] - )(q=self._q, qdot=self._v)["ee_vel_angular"] - for frame in self.__frame_types - }, - lin_acc={ - Frame.from_str(frame): self.__kindyn.frameAcceleration( - body_urdf_name, self.__frame_mapping[frame] - )(q=self._q, qdot=self._v, qddot=self._dv)["ee_acc_linear"] - for frame in self.__frame_types - }, - ang_acc={ - Frame.from_str(frame): self.__kindyn.frameAcceleration( - body_urdf_name, self.__frame_mapping[frame] - )(q=self._q, qdot=self._v, qddot=self._dv)["ee_acc_angular"] - for frame in self.__frame_types - }, - djacobian={ - Frame.from_str(frame): self.__kindyn.jacobianTimeVariation( - body_urdf_name, self.__frame_mapping[frame] - )(q=self._q, v=self._v)["dJ"] - for frame in self.__frame_types - }, + + # check that the frame is present in the model + if not self.__model.existFrame(body_urdf_name): + raise KeyError(f"Frame {body_urdf_name} does not exist in the model") + + frame_idx = self.__model.getFrameId(body_urdf_name) + + jacobian = {} + djacobian = {} + lin_vel = {} + ang_vel = {} + lin_acc = {} + ang_acc = {} + cpin.framesForwardKinematics(self.__model, self.__data, self._q) + for frame_str, fstr in self.__frame_mapping.items(): + frame = Frame.from_str(frame_str) + + jacobian[frame] = cpin.getFrameJacobian( + self.__model, self.__data, frame_idx, fstr + ) + djacobian[frame] = cpin.getFrameJacobianTimeVariation( + self.__model, self.__data, frame_idx, fstr + ) + # TODO: Redo this with standart pin functions + lin_vel[frame] = jacobian[frame][:3, :] @ self._v + ang_vel[frame] = jacobian[frame][3:, :] @ self._v + lin_acc[frame] = ( + jacobian[frame][:3, :] @ self._dv + djacobian[frame][:3, :] @ self._v + ) + ang_acc[frame] = ( + jacobian[frame][3:, :] @ self._dv + djacobian[frame][3:, :] @ self._v + ) + + result = BodyInfo( + position=self.__data.oMf[frame_idx].translation, + rotation=self.__data.oMf[frame_idx].rotation, + quaternion=cpin.SE3ToXYZQUAT(self.__data.oMf[frame_idx])[3:], + jacobian=jacobian, + djacobian=djacobian, + lin_vel=lin_vel, + ang_vel=ang_vel, + lin_acc=lin_acc, + ang_acc=ang_acc, ) + # DO WE NEED THIS IN CASADI BACKEND? + # self.__body_info_cache[body_urdf_name] = result + + return result def cone( self, force: ArrayLike | None, mu: float, type: str, X=None, Y=None @@ -489,51 +509,7 @@ def integrate_configuration( v: ArrayLike | None = None, dt: float | cs.SX = 1.0, ) -> ArrayLike: - if self.nq != self.nv: - q = q if q is not None else self._q - v = v if v is not None else self._v - - # we have to use lie geometry - # to integrate se3 and joint space separately - # TODO: - # replace with SE3 - # what if someone will fix base position? - pos = q[:3] - xyzw = q[3:7] - so3 = lie.SO3(xyzw) - joints = q[7:] - - pos_tang = v[:3] * dt - so3_tang = lie.SO3Tangent(v[3:6] * dt) - joint_tang = v[6:] * dt - - # se3 = lie.SE3(pos=pos, xyzw=xyzw) - # se3_tang = lie.SE3Tangent(v[:6] * dt) - # container[:3] = se3_next.xyzw - # container[3:7] = se3_next.xyzw - # se3_next = se3 + so3_tang - - pos_next = pos + pos_tang - so3_next = so3 + so3_tang - joints_next = joints + joint_tang - - container = cs.SX.zeros(self.nq) - configuration_next = cs.vertcat(pos_next, so3_next.xyzw, joints_next) - # container[:3] = pos_next - # container[3:7] = so3_next.xyzw - # container[7:] = joints_next - container = configuration_next - return container - else: - return (q if q is not None else self._q) + ( - v if v is not None else self._v - ) * dt - - # do not ever try to use this in optimization - # return self.__kindyn.integrate()( - # q=q if q is not None else self._q, - # v=v * dt if v is not None else self._v * dt, - # )["qnext"] + return cpin.integrate(self.__model, q, v * dt) def centroidal_dynamics( self, @@ -541,25 +517,38 @@ def centroidal_dynamics( v: ArrayLike | None = None, dv: ArrayLike | None = None, ) -> CentroidalDynamics: - dyn = self.__kindyn.computeCentroidalDynamics()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - a=dv if dv is not None else self._dv, + if q is None and v is None and dv is None: + return CentroidalDynamics( + matrix=self.__data.Ag, + linear=self.__data.hg.linear, + angular=self.__data.hg.angular, + linear_dt=self.__data.dhg.linear, + angular_dt=self.__data.dhg.angular, + matrix_dt=self.__centroidal_derivatives[0], + dynamics_jacobian_q=self.__centroidal_derivatives[1], + dynamics_jacobian_v=self.__centroidal_derivatives[2], + dynamics_jacobian_dv=self.__centroidal_derivatives[3], + ) + + self._q = q if q is not None else self._q + self._v = v if v is not None else self._v + self._dv = dv if dv is not None else self._dv + + cpin.computeCentroidalMomentumTimeVariation( + self.__model, self.__data, self._q, self._v, self._dv ) - dyn_der = self.__kindyn.computeCentroidalDynamicsDerivatives()( - q=q if q is not None else self._q, - v=v if v is not None else self._v, - a=dv if dv is not None else self._dv, + cpin.computeCentroidalDynamicsDerivatives( + self.__model, self.__data, self._q, self._v, self._dv ) return CentroidalDynamics( - matrix=dyn["Ag"], - linear=dyn["h_lin"], - angular=dyn["h_ang"], - linear_dt=dyn["dh_lin"], - angular_dt=dyn["dh_ang"], - matrix_dt=dyn_der["dh_dq"], - dynamics_jacobian_q=dyn_der["dhdot_dq"], - dynamics_jacobian_v=dyn_der["dhdot_dv"], - dynamics_jacobian_dv=dyn_der["dhdot_da"], + matrix=self.__data.Ag, + linear=self.__data.hg.linear, + angular=self.__data.hg.angular, + linear_dt=self.__data.dhg.linear, + angular_dt=self.__data.dhg.angular, + matrix_dt=self.__centroidal_derivatives[0], + dynamics_jacobian_q=self.__centroidal_derivatives[1], + dynamics_jacobian_v=self.__centroidal_derivatives[2], + dynamics_jacobian_dv=self.__centroidal_derivatives[3], ) diff --git a/darli/backend/_pinocchio.py b/darli/backend/_pinocchio.py index cb7654b..ccf5930 100644 --- a/darli/backend/_pinocchio.py +++ b/darli/backend/_pinocchio.py @@ -1,6 +1,7 @@ import pinocchio as pin -from ._base import BackendBase, BodyInfo, ConeBase, Frame, JointType, CentroidalDynamics +from ._base import BackendBase, ConeBase +from ._structs import Frame, BodyInfo, CentroidalDynamics, JointType from ..utils.arrays import ArrayLike, NumpyLikeFactory import numpy as np import numpy.typing as npt @@ -133,11 +134,11 @@ class PinocchioBackend(BackendBase): def __init__( self, - urdf_path: str, + description_path: str, root_joint: JointType | None = None, fixed_joints: Dict[str, float | npt.ArrayLike] = None, ) -> None: - super().__init__(urdf_path, root_joint, fixed_joints) + super().__init__(description_path, root_joint, fixed_joints) # backend base already contains model and data in pinocchio format # as we have created everything in super().__init__(), we can use it here @@ -488,10 +489,14 @@ def momentum_regressor( return phi_p, dphi_h - def update_body(self, body: str, body_urdf_name: str = None) -> BodyInfo: + def update_body(self, body: str, body_urdf_name: str | None = None) -> BodyInfo: if body_urdf_name is None: body_urdf_name = body + # check that body_urdf_name is in the model + if not self.__model.existFrame(body_urdf_name): + raise KeyError(f"Link {body_urdf_name} not found in the model") + # if we have cached information about body, clean it if body_urdf_name in self.__body_info_cache: return self.__body_info_cache[body_urdf_name] @@ -504,28 +509,31 @@ def update_body(self, body: str, body_urdf_name: str = None) -> BodyInfo: ang_vel = {} lin_acc = {} ang_acc = {} + + pin.framesForwardKinematics(self.__model, self.__data, self._q) + for frame_str, fstr in self.__frame_mapping.items(): frame = Frame.from_str(frame_str) - jacobian[frame] = pin.getFrameJacobian( self.__model, self.__data, frame_idx, fstr ) djacobian[frame] = pin.getFrameJacobianTimeVariation( self.__model, self.__data, frame_idx, fstr ) - lin_vel[frame] = jacobian[frame][:3] @ self._v - ang_vel[frame] = jacobian[frame][3:] @ self._v + # TODO: Redo this with standart pin functions + lin_vel[frame] = jacobian[frame][:3, :] @ self._v + ang_vel[frame] = jacobian[frame][3:, :] @ self._v lin_acc[frame] = ( - jacobian[frame][:3] @ self._dv + djacobian[frame][:3] @ self._v + jacobian[frame][:3, :] @ self._dv + djacobian[frame][:3, :] @ self._v ) ang_acc[frame] = ( - jacobian[frame][3:] @ self._dv + djacobian[frame][3:] @ self._v + jacobian[frame][3:, :] @ self._dv + djacobian[frame][3:, :] @ self._v ) result = BodyInfo( position=self.__data.oMf[frame_idx].translation, rotation=self.__data.oMf[frame_idx].rotation, - quaternion=pin.se3ToXYZQUAT(self.__data.oMf[frame_idx])[3:], + quaternion=pin.SE3ToXYZQUAT(self.__data.oMf[frame_idx])[3:], jacobian=jacobian, djacobian=djacobian, lin_vel=lin_vel, diff --git a/darli/backend/_structs.py b/darli/backend/_structs.py new file mode 100644 index 0000000..1b7175c --- /dev/null +++ b/darli/backend/_structs.py @@ -0,0 +1,80 @@ +from enum import Enum +from dataclasses import dataclass +from typing import Dict +from ..utils.arrays import ArrayLike + + +class Frame(Enum): + LOCAL = 1 + WORLD = 2 + LOCAL_WORLD_ALIGNED = 3 + + @classmethod + def from_str(cls, string: str) -> "Frame": + if string == "local": + return cls.LOCAL + elif string == "world": + return cls.WORLD + elif string == "world_aligned": + return cls.LOCAL_WORLD_ALIGNED + else: + raise ValueError(f"Unknown frame type: {string}") + + +class JointType(Enum): + OMIT = 1 # empty = none = no joint = skip + FREE_FLYER = 2 + PLANAR = 3 + + @classmethod + def from_str(cls, string: str) -> "JointType": + if string == "omit": + return cls.OMIT + elif string == "free_flyer": + return cls.FREE_FLYER + elif string == "planar": + return cls.PLANAR + else: + raise ValueError(f"Unknown joint type: {string}") + + +@dataclass +class BodyInfo: + position: ArrayLike + rotation: ArrayLike + quaternion: ArrayLike + jacobian: Dict[Frame, ArrayLike] + djacobian: Dict[Frame, ArrayLike] + lin_vel: Dict[Frame, ArrayLike] + ang_vel: Dict[Frame, ArrayLike] + lin_acc: Dict[Frame, ArrayLike] + ang_acc: Dict[Frame, ArrayLike] + + +@dataclass +class CentroidalDynamics: + """ + linear: linear momentum + angular: angular momentum + linear_dt: linear momentum derivative + angular_dt: angular momentum derivative + matrix: centroidal momentum matrix + matrix_dt: same as linear momentum derivative w.r.t. q + dynamics_jacobian_q: momentum derivative w.r.t. q + dynamics_jacobian_v: momentum derivative w.r.t. v + dynamics_jacobian_vdot: momentum derivative w.r.t. dv + + Under the hood uses pinocchio methods: + - computeCentroidalMomentumTimeVariation + - computeCentroidalDynamicsDerivatives + """ + + linear: ArrayLike + angular: ArrayLike + linear_dt: ArrayLike + angular_dt: ArrayLike + matrix: ArrayLike + matrix_dt: ArrayLike + dynamics_jacobian_q: ArrayLike + dynamics_jacobian_v: ArrayLike + dynamics_jacobian_dv: ArrayLike diff --git a/darli/backend/liecasadi/so3.py b/darli/backend/liecasadi/so3.py index 7ba8e26..c1beee0 100644 --- a/darli/backend/liecasadi/so3.py +++ b/darli/backend/liecasadi/so3.py @@ -17,6 +17,7 @@ # SO3 Manifold should be defined on Rotation matrices! # No conversion to and back from SO3/Quaternions + @dataclasses.dataclass class SO3: xyzw: Vector @@ -49,17 +50,23 @@ def from_matrix(matrix: Matrix) -> "SO3": qw = 0.5 * cs.sqrt(m[0, 0] + m[1, 1] + m[2, 2] + 1) - qx = cs.if_else(m[2, 1] - m[1, 2] >= 0, - 0.5 * cs.sqrt(m[0, 0] - m[1, 1] - m[2, 2] + 1), - -0.5 * cs.sqrt(m[0, 0] - m[1, 1] - m[2, 2] + 1)) + qx = cs.if_else( + m[2, 1] - m[1, 2] >= 0, + 0.5 * cs.sqrt(m[0, 0] - m[1, 1] - m[2, 2] + 1), + -0.5 * cs.sqrt(m[0, 0] - m[1, 1] - m[2, 2] + 1), + ) - qy = cs.if_else(m[0, 2] - m[2, 0] >= 0, - 0.5 * cs.sqrt(m[1, 1] - m[2, 2] - m[0, 0] + 1), - -0.5 * cs.sqrt(m[1, 1] - m[2, 2] - m[0, 0] + 1)) + qy = cs.if_else( + m[0, 2] - m[2, 0] >= 0, + 0.5 * cs.sqrt(m[1, 1] - m[2, 2] - m[0, 0] + 1), + -0.5 * cs.sqrt(m[1, 1] - m[2, 2] - m[0, 0] + 1), + ) - qz = cs.if_else(m[1, 0] - m[0, 1] >= 0, - 0.5 * cs.sqrt(m[2, 2] - m[0, 0] - m[1, 1] + 1), - -0.5 * cs.sqrt(m[2, 2] - m[0, 0] - m[1, 1] + 1)) + qz = cs.if_else( + m[1, 0] - m[0, 1] >= 0, + 0.5 * cs.sqrt(m[2, 2] - m[0, 0] - m[1, 1] + 1), + -0.5 * cs.sqrt(m[2, 2] - m[0, 0] - m[1, 1] + 1), + ) return SO3(xyzw=cs.vertcat(qx, qy, qz, qw)) @@ -112,12 +119,14 @@ def __rmul__(self, other) -> "SO3": return SO3(xyzw=(other.quat * self.xyzw).coeffs()) def log(self) -> "SO3Tangent": - norm = cs.norm_2(self.quat.coeffs()[:3])# + cs.np.finfo(np.float64).eps) - theta = cs.if_else(norm > 0+ cs.np.finfo(np.float64).eps, - 2 * self.quat.coeffs()[:3] * cs.atan2(norm, self.quat.coeffs()[3]) / norm, - cs.MX.zeros(3,1)) + norm = cs.norm_2(self.quat.coeffs()[:3]) # + cs.np.finfo(np.float64).eps) + theta = cs.if_else( + norm > 0 + cs.np.finfo(np.float64).eps, + 2 * self.quat.coeffs()[:3] * cs.atan2(norm, self.quat.coeffs()[3]) / norm, + cs.MX.zeros(3, 1), + ) return SO3Tangent(vec=theta) - + def distance(self, other: "SO3") -> cs.MX: R1 = self.as_matrix() R2 = other.as_matrix() @@ -125,7 +134,7 @@ def distance(self, other: "SO3") -> cs.MX: cos = (trace - 1) / 2 dist = cs.acos(cos) return dist**2 - + def __sub__(self, other) -> "SO3Tangent": if type(self) is type(other): return (other.inverse() * self).log() diff --git a/darli/model/_base.py b/darli/model/_base.py index 7d6406d..3b49ec1 100644 --- a/darli/model/_base.py +++ b/darli/model/_base.py @@ -334,12 +334,10 @@ def selector(self): pass @abstractmethod - def add_body(self, bodies_names: List[str] | Dict[str, str]): - ... + def add_body(self, bodies_names: List[str] | Dict[str, str]): ... @abstractmethod - def body(self, name: str) -> BodyBase: - ... + def body(self, name: str) -> BodyBase: ... @abstractmethod def centroidal_dynamics( @@ -347,8 +345,7 @@ def centroidal_dynamics( q: ArrayLike | None = None, v: ArrayLike | None = None, dv: ArrayLike | None = None, - ) -> CentroidalDynamics: - ... + ) -> CentroidalDynamics: ... @abstractmethod def update( @@ -357,5 +354,4 @@ def update( v: ArrayLike, dv: ArrayLike | None = None, u: ArrayLike | None = None, - ) -> ArrayLike: - ... + ) -> ArrayLike: ... diff --git a/darli/model/_body.py b/darli/model/_body.py index 9ac818c..2af9ebf 100644 --- a/darli/model/_body.py +++ b/darli/model/_body.py @@ -9,10 +9,10 @@ class Body(BodyBase): def __init__(self, name, backend: BackendBase, contact_type=None): if isinstance(name, dict): self.name = list(name.keys())[0] - self.urdf_name = name[self.name] + self.description_name = name[self.name] else: self.name = name - self.urdf_name = name + self.description_name = name self.__backend: BackendBase = backend @@ -151,7 +151,7 @@ def get_angular_acceleration(self, frame: Frame) -> ArrayLike: return self.__info.ang_acc[frame] def update(self): - self.__info = self.__backend.update_body(self.name, self.urdf_name) + self.__info = self.__backend.update_body(self.name, self.description_name) # update contact if self.__contact is not None: @@ -167,7 +167,7 @@ def add_contact( ): self.__contact_type = contact_type self.__contact = constructor( - self.urdf_name, + self.description_name, self.__backend, frame=frame, type=contact_type, diff --git a/darli/model/_model.py b/darli/model/_model.py index 2f69c4c..5bfc770 100644 --- a/darli/model/_model.py +++ b/darli/model/_model.py @@ -7,8 +7,6 @@ from ._base import Energy, CoM, ModelBase, BodyBase from ._body import Body -# from .state_space import CasadiStateSpace, PinocchioStateSpace - class Model(ModelBase): def __init__(self, backend: BackendBase): diff --git a/darli/parametric/_parameters/_parameters.py b/darli/parametric/_parameters/_parameters.py index ca4b4c6..ff657ee 100644 --- a/darli/parametric/_parameters/_parameters.py +++ b/darli/parametric/_parameters/_parameters.py @@ -11,9 +11,9 @@ # """Matrix exponential for a 4x4 matrix using CasADi.""" # # Compute the matrix exponential using CasADi's expm() function # expmA = cs.expm(A) - # +# # return expmA -# +# # def logm_pd(A): # """Matrix logarithm for a real positive definite matrix using CasADi.""" # # Compute the Cholesky decomposition of the matrix @@ -21,14 +21,13 @@ # # Compute the logarithm of the Cholesky factor # L_log = cs.solve(L, cs.eye(4)) * cs.log(cs.diag(L)) # # Reconstruct the matrix logarithm using the Cholesky factor logarithm -# logmA = L_log @ L_log.T +# logmA = L_log @ L_log.T # return logmA # Maybe we should move this to the <>? class InertialParameters: def __init__(self): - self.dim = 4 self.ndx = 10 self.vector = np.zeros(self.ndx) @@ -48,37 +47,39 @@ def __sub__(self, other): result.matrix = self.matrix - other.matrix return result - def exp(self, tangent_vector, point = None): + def exp(self, tangent_vector, point=None): # Exponential map if point is None: point = self.matrix - + p_inv_tv = np.linalg.solve(point, tangent_vector) w, v = np.linalg.eigh(p_inv_tv) # Exponentiate the eigenvalues w_exp = np.exp(w) # Reconstruct the matrix exponential using the eigen decomposition expm_inv = v @ np.diag(w_exp) @ v.T - + return point @ expm_inv def log(self, point_a, point_b): c = np.linalg.cholesky(point_a) c_inv = np.linalg.inv(c) - + w, v = np.linalg.eigh(c_inv @ point_b @ c_inv.T) # Compute the logarithm of the eigenvalues w_log = np.log(w) # Reconstruct the matrix logarithm using the eigen decomposition logm = v @ np.diag(w_log) @ v.T - + return c @ logm @ c.T def retraction(self, tangent_vector): # Retraction operation point = self.matrix p_inv_tv = np.linalg.solve(point, tangent_vector) - return (point + tangent_vector + tangent_vector @ p_inv_tv / 2) / np.trace(point + tangent_vector) + return (point + tangent_vector + tangent_vector @ p_inv_tv / 2) / np.trace( + point + tangent_vector + ) def tangent(self, vector): # Tangent space computation @@ -98,6 +99,7 @@ def euclidian_jacobian(self, tangent_vector): # Euclidean operations return tangent_vector + # The following class is used for the collection of InertialParameters # i.e Lumped parameters class LumpedParameters(InertialParameters): @@ -111,4 +113,4 @@ def __init__(self, nb): class ReducedParameters(InertialParameters): def __init__(self, nb, basis): super().__init__() - # Add any additional attributes specific to ReducedParameters \ No newline at end of file + # Add any additional attributes specific to ReducedParameters diff --git a/darli/robots/_robots.py b/darli/robots/_robots.py index 89a000a..27540a3 100644 --- a/darli/robots/_robots.py +++ b/darli/robots/_robots.py @@ -97,9 +97,10 @@ def quadruped( foots: Dict = None, arm: Dict = None, floating_selector=True, - friction = 1.0, + friction=1.0, reference: Frame = Frame.LOCAL_WORLD_ALIGNED, - root_joint: JointType = None) -> Model | Parametric | Functional: + root_joint: JointType = None, +) -> Model | Parametric | Functional: bodies_names = {} if torso is not None: diff --git a/darli/state_space/_common.py b/darli/state_space/_common.py index ce11bd8..128702f 100644 --- a/darli/state_space/_common.py +++ b/darli/state_space/_common.py @@ -131,8 +131,8 @@ def rollout( if control_sampling is None: control_sampling = dt - assert controls.shape[1] == int( - n_steps * dt / control_sampling + assert ( + controls.shape[1] == int(n_steps * dt / control_sampling) ), f"We expect controls to have shape[1] = {int(n_steps * dt / control_sampling)}, but got {controls.shape[1]}" time = 0 diff --git a/darli/state_space/_state/_state.py b/darli/state_space/_state/_state.py index a75be16..c31250c 100644 --- a/darli/state_space/_state/_state.py +++ b/darli/state_space/_state/_state.py @@ -3,11 +3,11 @@ # StateSpace.state -# state() = -# groups = [Vector(3), SO(3), Vector(nj)] -# -# -# nx = +# state() = +# groups = [Vector(3), SO(3), Vector(nj)] +# +# +# nx = class State: @@ -44,7 +44,6 @@ def configuration_space(self): # Return the configuration space of the state pass - def state_mapping(self, other_state): # Map another state to the same configuration space as the current state pass @@ -103,4 +102,4 @@ def __truediv__(self, scalar): new_state.data = self.data / scalar return new_state else: - raise TypeError("Unsupported operand type for /") \ No newline at end of file + raise TypeError("Unsupported operand type for /") diff --git a/darli/state_space/_state/_tangent.py b/darli/state_space/_state/_tangent.py index 47ed426..ad3996b 100644 --- a/darli/state_space/_state/_tangent.py +++ b/darli/state_space/_state/_tangent.py @@ -1,5 +1,6 @@ import numpy as np + class Tangent: def __init__(self, ndx): self.ndx = ndx @@ -59,4 +60,4 @@ def __repr__(self): return f"Tangent(ndx={self.ndx}, data={self.data})" def __str__(self): - return f"Tangent vector of dimension {self.ndx}: {self.data}" \ No newline at end of file + return f"Tangent vector of dimension {self.ndx}: {self.data}" diff --git a/darli/state_space/integrators/_mid_point.py b/darli/state_space/integrators/_mid_point.py index ea6e236..e7ac35b 100644 --- a/darli/state_space/integrators/_mid_point.py +++ b/darli/state_space/integrators/_mid_point.py @@ -1,4 +1,5 @@ """Module for forward euler integrator""" + from ._base import Integrator, ModelBase, ArrayLike, cs diff --git a/darli/state_space/integrators/_rk4.py b/darli/state_space/integrators/_rk4.py index 4491f11..a103948 100644 --- a/darli/state_space/integrators/_rk4.py +++ b/darli/state_space/integrators/_rk4.py @@ -1,4 +1,5 @@ """Module for RK4 integrator""" + from ._base import Integrator, ModelBase, ArrayLike, cs diff --git a/darli/utils/manifolds/__manifold.py b/darli/utils/manifolds/__manifold.py index af0ec5c..bb6878f 100644 --- a/darli/utils/manifolds/__manifold.py +++ b/darli/utils/manifolds/__manifold.py @@ -3,7 +3,7 @@ # https://github.com/pymanopt/pymanopt/blob/master/src/pymanopt/manifolds/manifold.py -# Manifold Class +# Manifold Class # ATTRIBUTES: # nx # ndx @@ -16,25 +16,25 @@ # __neg__ # __rsub__ # __truediv__ -# +# # Methods: # log # exp # logmap -# expmap +# expmap # action # dist # gradient # hessian -# tangent -# neutral -# random +# tangent +# neutral +# random # inverse -# Tangent Class +# Tangent Class -# Product Class +# Product Class diff --git a/darli/utils/manifolds/__se3.py b/darli/utils/manifolds/__se3.py index 0ac26ff..d7055b6 100644 --- a/darli/utils/manifolds/__se3.py +++ b/darli/utils/manifolds/__se3.py @@ -1,3 +1,2 @@ - # Here we will define casadi/numpy manifold of quaternions -# https://github.com/pymanopt/pymanopt/blob/master/src/pymanopt/manifolds/euclidean.py \ No newline at end of file +# https://github.com/pymanopt/pymanopt/blob/master/src/pymanopt/manifolds/euclidean.py diff --git a/darli/utils/manifolds/__spd.py b/darli/utils/manifolds/__spd.py index ad9e91b..2141e21 100644 --- a/darli/utils/manifolds/__spd.py +++ b/darli/utils/manifolds/__spd.py @@ -1,3 +1,2 @@ - # here we will define casadi/numpy manifold of symmetric positive definite matrices -# https://github.com/pymanopt/pymanopt/blob/master/src/pymanopt/manifolds/positive_definite.py \ No newline at end of file +# https://github.com/pymanopt/pymanopt/blob/master/src/pymanopt/manifolds/positive_definite.py diff --git a/darli/utils/manifolds/__vector.py b/darli/utils/manifolds/__vector.py index 228962e..9a74e1d 100644 --- a/darli/utils/manifolds/__vector.py +++ b/darli/utils/manifolds/__vector.py @@ -1 +1 @@ -# A simple vector space manifold \ No newline at end of file +# A simple vector space manifold diff --git a/environment.yml b/environment.yml index afd1022..b08c84f 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: base +name: darli_dev channels: - conda-forge dependencies: @@ -6,6 +6,7 @@ dependencies: - pip - ipykernel - libgfortran5 + - pinocchio>=3.0.0 - pip: - darli - robot_descriptions diff --git a/pixi.lock b/pixi.lock new file mode 100644 index 0000000..2a164c5 --- /dev/null +++ b/pixi.lock @@ -0,0 +1,1988 @@ +version: 5 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/ampl-mp-3.1.0-h2cc385e_1006.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/assimp-5.4.1-h8343317_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.7.4-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/casadi-3.6.5-py312h1a19fd5_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/console_bridge-1.0.2-h924138e_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-3.4.0-h00ab1b0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigenpy-3.7.0-py312hcdefc7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hpp-fcl-2.4.4-py312h65ace4e_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ipopt-3.14.16-h3696c94_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-23_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.84.0-h0ccab89_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.84.0-h00ab1b0_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.84.0-ha770c72_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-1.84.0-py312hf74af30_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-devel-1.84.0-py312h9cebb41_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-23_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h77fa898_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-14.1.0-h69a702a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-14.1.0-hc5f4f2c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.11.0-default_h5622ce7_1000.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-23_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_hac2b453_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libosqp-0.6.3-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libqdldl-0.1.5-h27087fc_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libscotch-7.0.4-h2fe6a88_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libspral-2024.05.08-hdf4021c_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-14.1.0-hc0a3c3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.7-he7c6b58_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/metis-5.1.0-h59595ed_1007.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mumps-include-5.7.2-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mumps-seq-5.7.2-h6e8dedb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/octomap-1.9.8-h924138e_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4bc722e_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pinocchio-3.1.0-py312he572396_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/proxsuite-0.6.6-py312h2492b07_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.4-h194c7f8_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-static-2020.2-h434a139_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.14.0-py312hc2bc53b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h297d8ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tinyxml2-10.0.0-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/unixodbc-2.3.12-h661eb56_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/urdfdom-4.0.0-hee28ff1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/urdfdom_headers-1.1.1-h00ab1b0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-h4ab18f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + - pypi: https://files.pythonhosted.org/packages/a2/ad/e0d3c824784ff121c03cc031f944bc7e139a8f1870ffd2845cc2dd76f6c4/absl_py-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1f/0f/c890339dd605f3ebc269543247bdd43b703cce6825b5ed42ff5f2d6122c7/coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/2e/35/7f8fcc9c23a504cf09e2795164eeb39a39ade1b2c7c8724ee207b2019ae6/etils-1.9.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/5b/8f0c4a5bb9fd491c277c21eff7ccae71b47d43c4446c9d0c6cff2fe8c2c4/gitdb-4.0.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/e8/462afb18f3627d11d4dab74228b52094e1a121d57fe57957c821c50bbfba/glfw-2.7.0-py2.py27.py3.py30.py31.py32.py33.py34.py35.py36.py37.py38-none-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/db/2a/728c8ae66011600fac5731a7db030d23c42f1321fd9547654f0c3b2b32d7/importlib_resources-6.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5d/72/4194951a281c21cdf2ebfff44f57dcaff95e4c15b1a6019d5738c698fb73/mujoco-3.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/48/00e31747821d3fc56faddd00a4725454d1e694a8b67d715cf20f531506a5/PyOpenGL-3.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/f9/cf155cf32ca7d6fa3601bc4c5dd19086af4b320b706919d48a4c79081cf9/pytest-8.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/4f/0b/49d4d4cd84ffa2d7aded910d0c27f144bdd98e5fbca452b40882c2c0c16e/robot_descriptions-1.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/a5/10f97f73544edcdef54409f1d839f6049a0d79df68adbc1ceb24d1aaca42/smmap-5.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/48/5d/acf5905c36149bbaec41ccf7f2b68814647347b72075ac0b1fe3022fdc73/tqdm-4.66.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/9e/c96f7a4cd0bf5625bb409b7e61e99b1130dc63a98cb8b24aeabae62d43e8/zipp-3.20.1-py3-none-any.whl + - pypi: . + dev: + channels: + - url: https://conda.anaconda.org/conda-forge/ + indexes: + - https://pypi.org/simple + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/ampl-mp-3.1.0-h2cc385e_1006.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/assimp-5.4.1-h8343317_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.7.4-hbcca054_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/casadi-3.6.5-py312h1a19fd5_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/console_bridge-1.0.2-h924138e_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigen-3.4.0-h00ab1b0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/eigenpy-3.7.0-py312hcdefc7e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/hpp-fcl-2.4.4-py312h65ace4e_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ipopt-3.14.16-h3696c94_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_7.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-23_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.84.0-h0ccab89_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.84.0-h00ab1b0_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.84.0-ha770c72_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-1.84.0-py312hf74af30_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-devel-1.84.0-py312h9cebb41_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-23_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h77fa898_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-14.1.0-h69a702a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-14.1.0-hc5f4f2c_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.11.0-default_h5622ce7_1000.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-23_linux64_openblas.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_hac2b453_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libosqp-0.6.3-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libqdldl-0.1.5-h27087fc_1.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libscotch-7.0.4-h2fe6a88_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libspral-2024.05.08-hdf4021c_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-14.1.0-hc0a3c3a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.7-he7c6b58_4.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/metis-5.1.0-h59595ed_1007.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mumps-include-5.7.2-ha770c72_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/mumps-seq-5.7.2-h6e8dedb_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/octomap-1.9.8-h924138e_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4bc722e_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/pinocchio-3.1.0-py312he572396_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/proxsuite-0.6.6-py312h2492b07_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.4-h194c7f8_0_cpython.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/qhull-static-2020.2-h434a139_5.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.14.0-py312hc2bc53b_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h297d8ca_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tinyxml2-10.0.0-h59595ed_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/unixodbc-2.3.12-h661eb56_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/urdfdom-4.0.0-hee28ff1_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/urdfdom_headers-1.1.1-h00ab1b0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-h4ab18f5_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + - pypi: https://files.pythonhosted.org/packages/a2/ad/e0d3c824784ff121c03cc031f944bc7e139a8f1870ffd2845cc2dd76f6c4/absl_py-2.1.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1f/0f/c890339dd605f3ebc269543247bdd43b703cce6825b5ed42ff5f2d6122c7/coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/2e/35/7f8fcc9c23a504cf09e2795164eeb39a39ade1b2c7c8724ee207b2019ae6/etils-1.9.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ae/f0/48285f0262fe47103a4a45972ed2f9b93e4c80b8fd609fa98da78b2a5706/filelock-3.15.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/5b/8f0c4a5bb9fd491c277c21eff7ccae71b47d43c4446c9d0c6cff2fe8c2c4/gitdb-4.0.11-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/e8/462afb18f3627d11d4dab74228b52094e1a121d57fe57957c821c50bbfba/glfw-2.7.0-py2.py27.py3.py30.py31.py32.py33.py34.py35.py36.py37.py38-none-manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/24/6c/a4f39abe7f19600b74528d0c717b52fff0b300bb0161081510d39c53cb00/identify-2.6.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/db/2a/728c8ae66011600fac5731a7db030d23c42f1321fd9547654f0c3b2b32d7/importlib_resources-6.4.4-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/5d/72/4194951a281c21cdf2ebfff44f57dcaff95e4c15b1a6019d5738c698fb73/mujoco-3.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/68/13/2aa1f0e1364feb2c9ef45302f387ac0bd81484e9c9a4c5688a322fbdfd08/platformdirs-4.2.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/92/caae8c86e94681b42c246f0bca35c059a2f0529e5b92619f6aba4cf7e7b6/pre_commit-3.8.0-py2.py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/99/48/00e31747821d3fc56faddd00a4725454d1e694a8b67d715cf20f531506a5/PyOpenGL-3.1.7-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/0f/f9/cf155cf32ca7d6fa3601bc4c5dd19086af4b320b706919d48a4c79081cf9/pytest-8.3.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/b4/33/720548182ffa8344418126017aa1d4ab4aeec9a2275f04ce3f3573d8ace8/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/4f/0b/49d4d4cd84ffa2d7aded910d0c27f144bdd98e5fbca452b40882c2c0c16e/robot_descriptions-1.12.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/a7/a5/10f97f73544edcdef54409f1d839f6049a0d79df68adbc1ceb24d1aaca42/smmap-5.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/48/5d/acf5905c36149bbaec41ccf7f2b68814647347b72075ac0b1fe3022fdc73/tqdm-4.66.5-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/4d/410156100224c5e2f0011d435e477b57aed9576fc7fe137abcf14ec16e11/virtualenv-20.26.3-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/07/9e/c96f7a4cd0bf5625bb409b7e61e99b1130dc63a98cb8b24aeabae62d43e8/zipp-3.20.1-py3-none-any.whl + - pypi: . +packages: +- kind: conda + name: _libgcc_mutex + version: '0.1' + build: conda_forge + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 + md5: d7c89558ba9fa0495403155b64376d81 + license: None + purls: [] + size: 2562 + timestamp: 1578324546067 +- kind: conda + name: _openmp_mutex + version: '4.5' + build: 2_gnu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 + md5: 73aaf86a425cc6e73fcf236a5a46396d + depends: + - _libgcc_mutex 0.1 conda_forge + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 23621 + timestamp: 1650670423406 +- kind: pypi + name: absl-py + version: 2.1.0 + url: https://files.pythonhosted.org/packages/a2/ad/e0d3c824784ff121c03cc031f944bc7e139a8f1870ffd2845cc2dd76f6c4/absl_py-2.1.0-py3-none-any.whl + sha256: 526a04eadab8b4ee719ce68f204172ead1027549089702d99b9059f129ff1308 + requires_python: '>=3.7' +- kind: conda + name: ampl-mp + version: 3.1.0 + build: h2cc385e_1006 + build_number: 1006 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ampl-mp-3.1.0-h2cc385e_1006.tar.bz2 + sha256: ff6e942d6490496d98d670f783275078d2a30c694202304ecd49fb759b93c07f + md5: 6c2f16f5650a7c66ffdfee57b890ea06 + depends: + - libgcc-ng >=9.4.0 + - libgfortran-ng + - libgfortran5 >=9.4.0 + - libstdcxx-ng >=9.4.0 + - unixodbc >=2.3.9,<2.4.0a0 + license: HPND + purls: [] + size: 1137486 + timestamp: 1645057516176 +- kind: conda + name: assimp + version: 5.4.1 + build: h8343317_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/assimp-5.4.1-h8343317_0.conda + sha256: 0661a0d38ad37ef0f50fdd4f4d80f4532d27ea5a887735113582fd8a5cc73fef + md5: f02332fc881c714278a88d1eaf18bd66 + depends: + - libboost >=1.84.0,<1.85.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + - zlib + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 3468429 + timestamp: 1715776025810 +- kind: conda + name: bzip2 + version: 1.0.8 + build: h4bc722e_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/bzip2-1.0.8-h4bc722e_7.conda + sha256: 5ced96500d945fb286c9c838e54fa759aa04a7129c59800f0846b4335cee770d + md5: 62ee74e96c5ebb0af99386de58cf9553 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + license: bzip2-1.0.6 + license_family: BSD + purls: [] + size: 252783 + timestamp: 1720974456583 +- kind: conda + name: ca-certificates + version: 2024.7.4 + build: hbcca054_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2024.7.4-hbcca054_0.conda + sha256: c1548a3235376f464f9931850b64b02492f379b2f2bb98bc786055329b080446 + md5: 23ab7665c5f63cfb9f1f6195256daac6 + license: ISC + purls: [] + size: 154853 + timestamp: 1720077432978 +- kind: conda + name: casadi + version: 3.6.5 + build: py312h1a19fd5_4 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/casadi-3.6.5-py312h1a19fd5_4.conda + sha256: 7907df9842a6ff421d8a2021bb445fc3163a4b6deba9a72fcd323963e65aa7b0 + md5: ccdb7d718b867aa931fe22ef1b86e877 + depends: + - ipopt >=3.14.16,<3.14.17.0a0 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + - libosqp >=0.6.3,<0.6.4.0a0 + - libstdcxx-ng >=12 + - numpy >=1.19,<3 + - proxsuite >=0.6.4,<0.7.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - tinyxml2 >=10.0.0,<11.0a0 + license: LGPL-3.0-or-later + license_family: LGPL + purls: + - pkg:pypi/casadi?source=conda-forge-mapping + size: 5681319 + timestamp: 1718574519517 +- kind: pypi + name: cfgv + version: 3.4.0 + url: https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl + sha256: b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9 + requires_python: '>=3.8' +- kind: conda + name: console_bridge + version: 1.0.2 + build: h924138e_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/console_bridge-1.0.2-h924138e_1.tar.bz2 + sha256: 29caeda123ea705e68de46dc3b86065ec78f5b44d7ae69b320cc57e136d2d9d7 + md5: e891b2b856a57d2b2ddb9ed366e3f2ce + depends: + - libgcc-ng >=10.3.0 + - libstdcxx-ng >=10.3.0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 18460 + timestamp: 1648912649612 +- kind: pypi + name: coverage + version: 7.6.1 + url: https://files.pythonhosted.org/packages/1f/0f/c890339dd605f3ebc269543247bdd43b703cce6825b5ed42ff5f2d6122c7/coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca + requires_dist: + - tomli ; python_full_version <= '3.11.0a6' and extra == 'toml' + requires_python: '>=3.8' +- kind: pypi + name: darli + version: 0.5.0 + path: . + sha256: 6300e8bc2f9e3e2eac4cc9b99342073ea4f9c51cbf5e6eece807d2dc5b01a5e8 + requires_dist: + - pytest>=8.3.2,<9 + - robot-descriptions>=1.12.0,<2 + - mujoco>=3.2.2,<4 + - pytest-cov>=5.0.0,<6 + - pre-commit ; extra == 'dev' + requires_python: '>=3.9' + editable: true +- kind: pypi + name: distlib + version: 0.3.8 + url: https://files.pythonhosted.org/packages/8e/41/9307e4f5f9976bc8b7fea0b66367734e8faf3ec84bc0d412d8cfabbb66cd/distlib-0.3.8-py2.py3-none-any.whl + sha256: 034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784 +- kind: conda + name: eigen + version: 3.4.0 + build: h00ab1b0_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/eigen-3.4.0-h00ab1b0_0.conda + sha256: 53b15a98aadbe0704479bacaf7a5618fcb32d1577be320630674574241639b34 + md5: b1b879d6d093f55dd40d58b5eb2f0699 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: MPL-2.0 + license_family: MOZILLA + purls: [] + size: 1088433 + timestamp: 1690272126173 +- kind: conda + name: eigenpy + version: 3.7.0 + build: py312hcdefc7e_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/eigenpy-3.7.0-py312hcdefc7e_0.conda + sha256: 81a6021e85bf0656d18830f1fdc61e93c3260e274dcf1703c3863ed8da5927c3 + md5: adcc6467fcf1e7bf6913d631ef0c920e + depends: + - eigen + - libboost-python >=1.84.0,<1.85.0a0 + - libboost-python-devel + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - numpy >=1.26.4,<2.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - scipy + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 2828887 + timestamp: 1718200596400 +- kind: pypi + name: etils + version: 1.9.4 + url: https://files.pythonhosted.org/packages/2e/35/7f8fcc9c23a504cf09e2795164eeb39a39ade1b2c7c8724ee207b2019ae6/etils-1.9.4-py3-none-any.whl + sha256: 4387e7a4911a3b5cc4b92b99a9211386d176b43bae1dac8e2fe345fc2cb95e4b + requires_dist: + - etils[array-types] ; extra == 'all' + - etils[eapp] ; extra == 'all' + - etils[ecolab] ; extra == 'all' + - etils[edc] ; extra == 'all' + - etils[enp] ; extra == 'all' + - etils[epath] ; extra == 'all' + - etils[epath-gcs] ; extra == 'all' + - etils[epath-s3] ; extra == 'all' + - etils[epy] ; extra == 'all' + - etils[etqdm] ; extra == 'all' + - etils[etree] ; extra == 'all' + - etils[etree-dm] ; extra == 'all' + - etils[etree-jax] ; extra == 'all' + - etils[etree-tf] ; extra == 'all' + - etils[enp] ; extra == 'array-types' + - pytest ; extra == 'dev' + - pytest-subtests ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - pyink ; extra == 'dev' + - pylint>=2.6.0 ; extra == 'dev' + - chex ; extra == 'dev' + - torch ; extra == 'dev' + - optree ; extra == 'dev' + - tensorflow-datasets ; extra == 'dev' + - pydantic ; extra == 'dev' + - sphinx-apitree[ext] ; extra == 'docs' + - etils[dev,all] ; extra == 'docs' + - absl-py ; extra == 'eapp' + - simple-parsing ; extra == 'eapp' + - etils[epy] ; extra == 'eapp' + - jupyter ; extra == 'ecolab' + - numpy ; extra == 'ecolab' + - mediapy ; extra == 'ecolab' + - packaging ; extra == 'ecolab' + - protobuf ; extra == 'ecolab' + - etils[enp] ; extra == 'ecolab' + - etils[epy] ; extra == 'ecolab' + - etils[etree] ; extra == 'ecolab' + - etils[epy] ; extra == 'edc' + - numpy ; extra == 'enp' + - etils[epy] ; extra == 'enp' + - fsspec ; extra == 'epath' + - importlib-resources ; extra == 'epath' + - typing-extensions ; extra == 'epath' + - zipp ; extra == 'epath' + - etils[epy] ; extra == 'epath' + - gcsfs ; extra == 'epath-gcs' + - etils[epath] ; extra == 'epath-gcs' + - s3fs ; extra == 'epath-s3' + - etils[epath] ; extra == 'epath-s3' + - typing-extensions ; extra == 'epy' + - absl-py ; extra == 'etqdm' + - tqdm ; extra == 'etqdm' + - etils[epy] ; extra == 'etqdm' + - etils[array-types] ; extra == 'etree' + - etils[epy] ; extra == 'etree' + - etils[enp] ; extra == 'etree' + - etils[etqdm] ; extra == 'etree' + - dm-tree ; extra == 'etree-dm' + - etils[etree] ; extra == 'etree-dm' + - jax[cpu] ; extra == 'etree-jax' + - etils[etree] ; extra == 'etree-jax' + - tensorflow ; extra == 'etree-tf' + - etils[etree] ; extra == 'etree-tf' + - etils[ecolab] ; extra == 'lazy-imports' + requires_python: '>=3.10' +- kind: pypi + name: filelock + version: 3.15.4 + url: https://files.pythonhosted.org/packages/ae/f0/48285f0262fe47103a4a45972ed2f9b93e4c80b8fd609fa98da78b2a5706/filelock-3.15.4-py3-none-any.whl + sha256: 6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7 + requires_dist: + - furo>=2023.9.10 ; extra == 'docs' + - sphinx-autodoc-typehints!=1.23.4,>=1.25.2 ; extra == 'docs' + - sphinx>=7.2.6 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'testing' + - coverage>=7.3.2 ; extra == 'testing' + - diff-cover>=8.0.1 ; extra == 'testing' + - pytest-asyncio>=0.21 ; extra == 'testing' + - pytest-cov>=4.1 ; extra == 'testing' + - pytest-mock>=3.12 ; extra == 'testing' + - pytest-timeout>=2.2 ; extra == 'testing' + - pytest>=7.4.3 ; extra == 'testing' + - virtualenv>=20.26.2 ; extra == 'testing' + - typing-extensions>=4.8 ; python_version < '3.11' and extra == 'typing' + requires_python: '>=3.8' +- kind: pypi + name: fsspec + version: 2024.9.0 + url: https://files.pythonhosted.org/packages/1d/a0/6aaea0c2fbea2f89bfd5db25fb1e3481896a423002ebe4e55288907a97a3/fsspec-2024.9.0-py3-none-any.whl + sha256: a0947d552d8a6efa72cc2c730b12c41d043509156966cca4fb157b0f2a0c574b + requires_dist: + - adlfs ; extra == 'abfs' + - adlfs ; extra == 'adl' + - pyarrow>=1 ; extra == 'arrow' + - dask ; extra == 'dask' + - distributed ; extra == 'dask' + - pre-commit ; extra == 'dev' + - ruff ; extra == 'dev' + - numpydoc ; extra == 'doc' + - sphinx ; extra == 'doc' + - sphinx-design ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - yarl ; extra == 'doc' + - dropbox ; extra == 'dropbox' + - dropboxdrivefs ; extra == 'dropbox' + - requests ; extra == 'dropbox' + - adlfs ; extra == 'full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'full' + - dask ; extra == 'full' + - distributed ; extra == 'full' + - dropbox ; extra == 'full' + - dropboxdrivefs ; extra == 'full' + - fusepy ; extra == 'full' + - gcsfs ; extra == 'full' + - libarchive-c ; extra == 'full' + - ocifs ; extra == 'full' + - panel ; extra == 'full' + - paramiko ; extra == 'full' + - pyarrow>=1 ; extra == 'full' + - pygit2 ; extra == 'full' + - requests ; extra == 'full' + - s3fs ; extra == 'full' + - smbprotocol ; extra == 'full' + - tqdm ; extra == 'full' + - fusepy ; extra == 'fuse' + - gcsfs ; extra == 'gcs' + - pygit2 ; extra == 'git' + - requests ; extra == 'github' + - gcsfs ; extra == 'gs' + - panel ; extra == 'gui' + - pyarrow>=1 ; extra == 'hdfs' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'http' + - libarchive-c ; extra == 'libarchive' + - ocifs ; extra == 'oci' + - s3fs ; extra == 's3' + - paramiko ; extra == 'sftp' + - smbprotocol ; extra == 'smb' + - paramiko ; extra == 'ssh' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test' + - numpy ; extra == 'test' + - pytest ; extra == 'test' + - pytest-asyncio!=0.22.0 ; extra == 'test' + - pytest-benchmark ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-recording ; extra == 'test' + - pytest-rerunfailures ; extra == 'test' + - requests ; extra == 'test' + - aiobotocore<3.0.0,>=2.5.4 ; extra == 'test-downstream' + - dask-expr ; extra == 'test-downstream' + - dask[dataframe,test] ; extra == 'test-downstream' + - moto[server]<5,>4 ; extra == 'test-downstream' + - pytest-timeout ; extra == 'test-downstream' + - xarray ; extra == 'test-downstream' + - adlfs ; extra == 'test-full' + - aiohttp!=4.0.0a0,!=4.0.0a1 ; extra == 'test-full' + - cloudpickle ; extra == 'test-full' + - dask ; extra == 'test-full' + - distributed ; extra == 'test-full' + - dropbox ; extra == 'test-full' + - dropboxdrivefs ; extra == 'test-full' + - fastparquet ; extra == 'test-full' + - fusepy ; extra == 'test-full' + - gcsfs ; extra == 'test-full' + - jinja2 ; extra == 'test-full' + - kerchunk ; extra == 'test-full' + - libarchive-c ; extra == 'test-full' + - lz4 ; extra == 'test-full' + - notebook ; extra == 'test-full' + - numpy ; extra == 'test-full' + - ocifs ; extra == 'test-full' + - pandas ; extra == 'test-full' + - panel ; extra == 'test-full' + - paramiko ; extra == 'test-full' + - pyarrow ; extra == 'test-full' + - pyarrow>=1 ; extra == 'test-full' + - pyftpdlib ; extra == 'test-full' + - pygit2 ; extra == 'test-full' + - pytest ; extra == 'test-full' + - pytest-asyncio!=0.22.0 ; extra == 'test-full' + - pytest-benchmark ; extra == 'test-full' + - pytest-cov ; extra == 'test-full' + - pytest-mock ; extra == 'test-full' + - pytest-recording ; extra == 'test-full' + - pytest-rerunfailures ; extra == 'test-full' + - python-snappy ; extra == 'test-full' + - requests ; extra == 'test-full' + - smbprotocol ; extra == 'test-full' + - tqdm ; extra == 'test-full' + - urllib3 ; extra == 'test-full' + - zarr ; extra == 'test-full' + - zstandard ; extra == 'test-full' + - tqdm ; extra == 'tqdm' + requires_python: '>=3.8' +- kind: pypi + name: gitdb + version: 4.0.11 + url: https://files.pythonhosted.org/packages/fd/5b/8f0c4a5bb9fd491c277c21eff7ccae71b47d43c4446c9d0c6cff2fe8c2c4/gitdb-4.0.11-py3-none-any.whl + sha256: 81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4 + requires_dist: + - smmap<6,>=3.0.1 + requires_python: '>=3.7' +- kind: pypi + name: gitpython + version: 3.1.43 + url: https://files.pythonhosted.org/packages/e9/bd/cc3a402a6439c15c3d4294333e13042b915bbeab54edc457c723931fed3f/GitPython-3.1.43-py3-none-any.whl + sha256: eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff + requires_dist: + - gitdb<5,>=4.0.1 + - typing-extensions>=3.7.4.3 ; python_version < '3.8' + - sphinx==4.3.2 ; extra == 'doc' + - sphinx-rtd-theme ; extra == 'doc' + - sphinxcontrib-applehelp<=1.0.4,>=1.0.2 ; extra == 'doc' + - sphinxcontrib-devhelp==1.0.2 ; extra == 'doc' + - sphinxcontrib-htmlhelp<=2.0.1,>=2.0.0 ; extra == 'doc' + - sphinxcontrib-qthelp==1.0.3 ; extra == 'doc' + - sphinxcontrib-serializinghtml==1.1.5 ; extra == 'doc' + - sphinx-autodoc-typehints ; extra == 'doc' + - coverage[toml] ; extra == 'test' + - ddt!=1.4.3,>=1.1.1 ; extra == 'test' + - mypy ; extra == 'test' + - pre-commit ; extra == 'test' + - pytest>=7.3.1 ; extra == 'test' + - pytest-cov ; extra == 'test' + - pytest-instafail ; extra == 'test' + - pytest-mock ; extra == 'test' + - pytest-sugar ; extra == 'test' + - typing-extensions ; python_version < '3.11' and extra == 'test' + - mock ; python_version < '3.8' and extra == 'test' + requires_python: '>=3.7' +- kind: pypi + name: glfw + version: 2.7.0 + url: https://files.pythonhosted.org/packages/ec/e8/462afb18f3627d11d4dab74228b52094e1a121d57fe57957c821c50bbfba/glfw-2.7.0-py2.py27.py3.py30.py31.py32.py33.py34.py35.py36.py37.py38-none-manylinux2014_x86_64.whl + sha256: d8630dd9673860c427abde5b79bbc348e02eccde8a3f2a802c5a2a4fb5d79fb8 + requires_dist: + - glfw-preview ; extra == 'preview' +- kind: conda + name: hpp-fcl + version: 2.4.4 + build: py312h65ace4e_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/hpp-fcl-2.4.4-py312h65ace4e_5.conda + sha256: 8dccc570a9c2e3bf64ec1c96184bb251b1c5abfb4171f71ced0cafe2692c512f + md5: dabf1239b64068e94f0c99b7877a3bf8 + depends: + - __glibc >=2.17,<3.0.a0 + - assimp >=5.4.1,<5.4.2.0a0 + - eigen + - eigenpy >=3.7.0,<3.7.1.0a0 + - libboost-python >=1.84.0,<1.85.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - numpy >=1.26.4,<2.0a0 + - octomap >=1.9.8,<1.10.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - qhull >=2020.2,<2020.3.0a0 + - qhull-static + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 1507487 + timestamp: 1720991349654 +- kind: conda + name: icu + version: '75.1' + build: he02047a_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/icu-75.1-he02047a_0.conda + sha256: 71e750d509f5fa3421087ba88ef9a7b9be11c53174af3aa4d06aff4c18b38e8e + md5: 8b189310083baabfb622af68fd9d3ae3 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: MIT + license_family: MIT + purls: [] + size: 12129203 + timestamp: 1720853576813 +- kind: pypi + name: identify + version: 2.6.0 + url: https://files.pythonhosted.org/packages/24/6c/a4f39abe7f19600b74528d0c717b52fff0b300bb0161081510d39c53cb00/identify-2.6.0-py2.py3-none-any.whl + sha256: e79ae4406387a9d300332b5fd366d8994f1525e8414984e1a59e058b2eda2dd0 + requires_dist: + - ukkonen ; extra == 'license' + requires_python: '>=3.8' +- kind: pypi + name: importlib-resources + version: 6.4.4 + url: https://files.pythonhosted.org/packages/db/2a/728c8ae66011600fac5731a7db030d23c42f1321fd9547654f0c3b2b32d7/importlib_resources-6.4.4-py3-none-any.whl + sha256: dda242603d1c9cd836c3368b1174ed74cb4049ecd209e7a1a0104620c18c5c11 + requires_dist: + - zipp>=3.1.0 ; python_version < '3.10' + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-enabler>=2.2 ; extra == 'enabler' + - pytest!=8.1.*,>=6 ; extra == 'test' + - zipp>=3.17 ; extra == 'test' + - jaraco-test>=5.4 ; extra == 'test' + - pytest-mypy ; extra == 'type' + requires_python: '>=3.8' +- kind: pypi + name: iniconfig + version: 2.0.0 + url: https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl + sha256: b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374 + requires_python: '>=3.7' +- kind: conda + name: ipopt + version: 3.14.16 + build: h3696c94_4 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ipopt-3.14.16-h3696c94_4.conda + sha256: 77167ac924980c367951eaa0afb27dd4ec003ed81ef5ee57c527a36edb4bb90f + md5: 55d12faab09c8596cafdb77bb6656a54 + depends: + - ampl-mp >=3.1.0,<3.2.0a0 + - libblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + - liblapack >=3.9.0,<4.0a0 + - libspral >=2024.5.8,<2024.5.9.0a0 + - libstdcxx-ng >=12 + - metis >=5.1.0,<5.1.1.0a0 + - mumps-seq >=5.7.2,<5.7.3.0a0 + license: EPL-1.0 + purls: [] + size: 1021947 + timestamp: 1718800264678 +- kind: conda + name: ld_impl_linux-64 + version: '2.40' + build: hf3520f5_7 + build_number: 7 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.40-hf3520f5_7.conda + sha256: 764b6950aceaaad0c67ef925417594dd14cd2e22fff864aeef455ac259263d15 + md5: b80f2f396ca2c28b8c14c437a4ed1e74 + constrains: + - binutils_impl_linux-64 2.40 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 707602 + timestamp: 1718625640445 +- kind: conda + name: libblas + version: 3.9.0 + build: 23_linux64_openblas + build_number: 23 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.9.0-23_linux64_openblas.conda + sha256: edb1cee5da3ac4936940052dcab6969673ba3874564f90f5110f8c11eed789c2 + md5: 96c8450a40aa2b9733073a9460de972c + depends: + - libopenblas >=0.3.27,<0.3.28.0a0 + - libopenblas >=0.3.27,<1.0a0 + constrains: + - liblapacke 3.9.0 23_linux64_openblas + - libcblas 3.9.0 23_linux64_openblas + - liblapack 3.9.0 23_linux64_openblas + - blas * openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14880 + timestamp: 1721688759937 +- kind: conda + name: libboost + version: 1.84.0 + build: h0ccab89_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.84.0-h0ccab89_5.conda + sha256: f66f16ce2402eedb58f4cf1a09b4edfab644e540bb287fe65a7d52f529fe00d1 + md5: b26bd978e55fad1d173ea96c1c50c6c2 + depends: + - __glibc >=2.17,<3.0.a0 + - bzip2 >=1.0.8,<2.0a0 + - icu >=75.1,<76.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.3.1,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zstd >=1.5.6,<1.6.0a0 + constrains: + - boost-cpp =1.84.0 + license: BSL-1.0 + purls: [] + size: 2857449 + timestamp: 1722289875483 +- kind: conda + name: libboost-devel + version: 1.84.0 + build: h00ab1b0_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.84.0-h00ab1b0_5.conda + sha256: f126001a1f8ef95ea56dbd93767f3a54f26dc1b555e5bf1484d69edd228b9c43 + md5: 8781c46806d1a66c50676614f0dcc2df + depends: + - libboost 1.84.0 h0ccab89_5 + - libboost-headers 1.84.0 ha770c72_5 + constrains: + - boost-cpp =1.84.0 + license: BSL-1.0 + purls: [] + size: 39471 + timestamp: 1722289996647 +- kind: conda + name: libboost-headers + version: 1.84.0 + build: ha770c72_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.84.0-ha770c72_5.conda + sha256: 85257c026772e47054683aa466c358fbd229d54055f42126974a77d577b0192f + md5: 39d4e07ebb688d3d4b331e9b20389d05 + constrains: + - boost-cpp =1.84.0 + license: BSL-1.0 + purls: [] + size: 13664568 + timestamp: 1722289895857 +- kind: conda + name: libboost-python + version: 1.84.0 + build: py312hf74af30_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-1.84.0-py312hf74af30_5.conda + sha256: a4edc94962eda2f0185c3e61bada39bbf063dc562dfbfd46980bd3d8b24169f4 + md5: 56712a4ad5e24124ce37d4a6bc2c0e94 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - numpy >=1.19,<3 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - boost =1.84.0 + - py-boost <0.0a0 + license: BSL-1.0 + purls: [] + size: 124878 + timestamp: 1722290442257 +- kind: conda + name: libboost-python-devel + version: 1.84.0 + build: py312h9cebb41_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libboost-python-devel-1.84.0-py312h9cebb41_5.conda + sha256: e90fd7e07dc3ddb6b49d1e000a2445daf9c3d162c610e2c78f0cf808ee249b71 + md5: 1e91f41ba0da28b255ceb4812d853157 + depends: + - libboost-devel 1.84.0 h00ab1b0_5 + - libboost-python 1.84.0 py312hf74af30_5 + - numpy >=1.19,<3 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - boost =1.84.0 + - py-boost <0.0a0 + license: BSL-1.0 + purls: [] + size: 20221 + timestamp: 1722290538514 +- kind: conda + name: libcblas + version: 3.9.0 + build: 23_linux64_openblas + build_number: 23 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.9.0-23_linux64_openblas.conda + sha256: 3e7a3236e7e03e308e1667d91d0aa70edd0cba96b4b5563ef4adde088e0881a5 + md5: eede29b40efa878cbe5bdcb767e97310 + depends: + - libblas 3.9.0 23_linux64_openblas + constrains: + - liblapacke 3.9.0 23_linux64_openblas + - liblapack 3.9.0 23_linux64_openblas + - blas * openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14798 + timestamp: 1721688767584 +- kind: conda + name: libedit + version: 3.1.20191231 + build: he28a2e2_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2 + sha256: a57d37c236d8f7c886e01656f4949d9dcca131d2a0728609c6f7fa338b65f1cf + md5: 4d331e44109e3f0e19b4cb8f9b82f3e1 + depends: + - libgcc-ng >=7.5.0 + - ncurses >=6.2,<7.0.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 123878 + timestamp: 1597616541093 +- kind: conda + name: libexpat + version: 2.6.2 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.6.2-h59595ed_0.conda + sha256: 331bb7c7c05025343ebd79f86ae612b9e1e74d2687b8f3179faec234f986ce19 + md5: e7ba12deb7020dd080c6c70e7b6f6a3d + depends: + - libgcc-ng >=12 + constrains: + - expat 2.6.2.* + license: MIT + license_family: MIT + purls: [] + size: 73730 + timestamp: 1710362120304 +- kind: conda + name: libffi + version: 3.4.2 + build: h7f98852_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.4.2-h7f98852_5.tar.bz2 + sha256: ab6e9856c21709b7b517e940ae7028ae0737546122f83c2aa5d692860c3b149e + md5: d645c6d2ac96843a2bfaccd2d62b3ac3 + depends: + - libgcc-ng >=9.4.0 + license: MIT + license_family: MIT + purls: [] + size: 58292 + timestamp: 1636488182923 +- kind: conda + name: libgcc-ng + version: 14.1.0 + build: h77fa898_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h77fa898_0.conda + sha256: b8e869ac96591cda2704bf7e77a301025e405227791a0bddf14a3dac65125538 + md5: ca0fad6a41ddaef54a153b78eccb5037 + depends: + - _libgcc_mutex 0.1 conda_forge + - _openmp_mutex >=4.5 + constrains: + - libgomp 14.1.0 h77fa898_0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 842109 + timestamp: 1719538896937 +- kind: conda + name: libgfortran-ng + version: 14.1.0 + build: h69a702a_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran-ng-14.1.0-h69a702a_0.conda + sha256: ef624dacacf97b2b0af39110b36e2fd3e39e358a1a6b7b21b85c9ac22d8ffed9 + md5: f4ca84fbd6d06b0a052fb2d5b96dde41 + depends: + - libgfortran5 14.1.0 hc5f4f2c_0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 49893 + timestamp: 1719538933879 +- kind: conda + name: libgfortran5 + version: 14.1.0 + build: hc5f4f2c_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgfortran5-14.1.0-hc5f4f2c_0.conda + sha256: a67d66b1e60a8a9a9e4440cee627c959acb4810cb182e089a4b0729bfdfbdf90 + md5: 6456c2620c990cd8dde2428a27ba0bc5 + depends: + - libgcc-ng >=14.1.0 + constrains: + - libgfortran-ng 14.1.0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 1457561 + timestamp: 1719538909168 +- kind: conda + name: libgomp + version: 14.1.0 + build: h77fa898_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_0.conda + sha256: 7699df61a1f6c644b3576a40f54791561f2845983120477a16116b951c9cdb05 + md5: ae061a5ed5f05818acdf9adab72c146d + depends: + - _libgcc_mutex 0.1 conda_forge + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 456925 + timestamp: 1719538796073 +- kind: conda + name: libhwloc + version: 2.11.0 + build: default_h5622ce7_1000 + build_number: 1000 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libhwloc-2.11.0-default_h5622ce7_1000.conda + sha256: 4cc0292ee8fff450da8b02ceadfab6e44646e0d6a586012b76c5454f770f546e + md5: 695ee1e435b873780efccc64362cda89 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libxml2 >=2.12.7,<3.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 2415753 + timestamp: 1719333896030 +- kind: conda + name: libiconv + version: '1.17' + build: hd590300_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-hd590300_2.conda + sha256: 8ac2f6a9f186e76539439e50505d98581472fedb347a20e7d1f36429849f05c9 + md5: d66573916ffcf376178462f1b61c941e + depends: + - libgcc-ng >=12 + license: LGPL-2.1-only + purls: [] + size: 705775 + timestamp: 1702682170569 +- kind: conda + name: liblapack + version: 3.9.0 + build: 23_linux64_openblas + build_number: 23 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.9.0-23_linux64_openblas.conda + sha256: 25c7aef86c8a1d9db0e8ee61aa7462ba3b46b482027a65d66eb83e3e6f949043 + md5: 2af0879961951987e464722fd00ec1e0 + depends: + - libblas 3.9.0 23_linux64_openblas + constrains: + - liblapacke 3.9.0 23_linux64_openblas + - libcblas 3.9.0 23_linux64_openblas + - blas * openblas + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 14823 + timestamp: 1721688775172 +- kind: conda + name: libnsl + version: 2.0.1 + build: hd590300_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hd590300_0.conda + sha256: 26d77a3bb4dceeedc2a41bd688564fe71bf2d149fdcf117049970bc02ff1add6 + md5: 30fd6e37fe21f86f4bd26d6ee73eeec7 + depends: + - libgcc-ng >=12 + license: LGPL-2.1-only + license_family: GPL + purls: [] + size: 33408 + timestamp: 1697359010159 +- kind: conda + name: libopenblas + version: 0.3.27 + build: pthreads_hac2b453_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.27-pthreads_hac2b453_1.conda + sha256: 714cb82d7c4620ea2635a92d3df263ab841676c9b183d0c01992767bb2451c39 + md5: ae05ece66d3924ac3d48b4aa3fa96cec + depends: + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + constrains: + - openblas >=0.3.27,<0.3.28.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 5563053 + timestamp: 1720426334043 +- kind: conda + name: libosqp + version: 0.6.3 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libosqp-0.6.3-h59595ed_0.conda + sha256: 9ae82670f53a43b119ecb137de53f17822b772360a1083817d4fcc178f60b6fe + md5: af90a98ba90a4063f252848e2f3aa5e6 + depends: + - libgcc-ng >=12 + - libqdldl >=0.1.5,<0.1.6.0a0 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 72079 + timestamp: 1685065354843 +- kind: conda + name: libqdldl + version: 0.1.5 + build: h27087fc_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libqdldl-0.1.5-h27087fc_1.tar.bz2 + sha256: 367c6a2d87dedfa03db0024956c4343fdf88b004dfb0831163d67e17680b547f + md5: 931d743c4d1219d5efc3a97bdb578053 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 16905 + timestamp: 1667006397176 +- kind: conda + name: libscotch + version: 7.0.4 + build: h2fe6a88_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libscotch-7.0.4-h2fe6a88_5.conda + sha256: 218ddc7a3d5f55f78edf0b78262c0988e70ee9a630c35f45098dae37591c558b + md5: dd1e1c54432494476d66c679014c675c + depends: + - bzip2 >=1.0.8,<2.0a0 + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + - libzlib >=1.2.13,<2.0a0 + - xz >=5.2.6,<6.0a0 + - zlib + license: CECILL-C + purls: [] + size: 341039 + timestamp: 1717069891622 +- kind: conda + name: libspral + version: 2024.05.08 + build: hdf4021c_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libspral-2024.05.08-hdf4021c_2.conda + sha256: b4efcd64e92dfb2a38c5ddc2ac42d066fe5103246396750c83a10d1eaffa02d4 + md5: 10aff913b33607cf87797a9b58fec9db + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + - libhwloc >=2.11.0,<2.11.1.0a0 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + - libzlib >=1.3.1,<2.0a0 + - metis >=5.1.0,<5.1.1.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 355325 + timestamp: 1720086058802 +- kind: conda + name: libsqlite + version: 3.46.0 + build: hde9e2c9_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libsqlite-3.46.0-hde9e2c9_0.conda + sha256: daee3f68786231dad457d0dfde3f7f1f9a7f2018adabdbb864226775101341a8 + md5: 18aa975d2094c34aef978060ae7da7d8 + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0a0 + license: Unlicense + purls: [] + size: 865346 + timestamp: 1718050628718 +- kind: conda + name: libstdcxx-ng + version: 14.1.0 + build: hc0a3c3a_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-14.1.0-hc0a3c3a_0.conda + sha256: 88c42b388202ffe16adaa337e36cf5022c63cf09b0405cf06fc6aeacccbe6146 + md5: 1cb187a157136398ddbaae90713e2498 + depends: + - libgcc-ng 14.1.0 h77fa898_0 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + purls: [] + size: 3881307 + timestamp: 1719538923443 +- kind: conda + name: libuuid + version: 2.38.1 + build: h0b41bf4_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libuuid-2.38.1-h0b41bf4_0.conda + sha256: 787eb542f055a2b3de553614b25f09eefb0a0931b0c87dbcce6efdfd92f04f18 + md5: 40b61aab5c7ba9ff276c41cfffe6b80b + depends: + - libgcc-ng >=12 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 33601 + timestamp: 1680112270483 +- kind: conda + name: libxcrypt + version: 4.4.36 + build: hd590300_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libxcrypt-4.4.36-hd590300_1.conda + sha256: 6ae68e0b86423ef188196fff6207ed0c8195dd84273cb5623b85aa08033a410c + md5: 5aa797f8787fe7a17d1b0821485b5adc + depends: + - libgcc-ng >=12 + license: LGPL-2.1-or-later + purls: [] + size: 100393 + timestamp: 1702724383534 +- kind: conda + name: libxml2 + version: 2.12.7 + build: he7c6b58_4 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libxml2-2.12.7-he7c6b58_4.conda + sha256: 10e9e0ac52b9a516a17edbc07f8d559e23778e54f1a7721b2e0e8219284fed3b + md5: 08a9265c637230c37cb1be4a6cad4536 + depends: + - __glibc >=2.17,<3.0.a0 + - icu >=75.1,<76.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libzlib >=1.3.1,<2.0a0 + - xz >=5.2.6,<6.0a0 + license: MIT + license_family: MIT + purls: [] + size: 707169 + timestamp: 1721031016143 +- kind: conda + name: libzlib + version: 1.3.1 + build: h4ab18f5_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-h4ab18f5_1.conda + sha256: adf6096f98b537a11ae3729eaa642b0811478f0ea0402ca67b5108fe2cb0010d + md5: 57d7dc60e9325e3de37ff8dffd18e814 + depends: + - libgcc-ng >=12 + constrains: + - zlib 1.3.1 *_1 + license: Zlib + license_family: Other + purls: [] + size: 61574 + timestamp: 1716874187109 +- kind: conda + name: metis + version: 5.1.0 + build: h59595ed_1007 + build_number: 1007 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/metis-5.1.0-h59595ed_1007.conda + sha256: 446bf794497284e2ffa28ab9191d70c38d372c51e3fd073f0d8b35efb51e7e02 + md5: 40ccb8318df2500f83bd868dd8fcd201 + depends: + - libgcc-ng >=12 + license: Apache-2.0 + license_family: APACHE + purls: [] + size: 3890263 + timestamp: 1693402645559 +- kind: pypi + name: mujoco + version: 3.2.2 + url: https://files.pythonhosted.org/packages/5d/72/4194951a281c21cdf2ebfff44f57dcaff95e4c15b1a6019d5738c698fb73/mujoco-3.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: a744f11c3a3e2b823cf4200d5334a743566daa29ea5a4a47354ded6e2ddc2aaf + requires_dist: + - absl-py + - etils[epath] + - glfw + - numpy + - pyopengl + requires_python: '>=3.8' +- kind: conda + name: mumps-include + version: 5.7.2 + build: ha770c72_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/mumps-include-5.7.2-ha770c72_0.conda + sha256: c69f8038d70242bb9443a67157967f7e4a927e66a5d938338a6c01c0f957bdce + md5: 5cd4042ea914dd6234a98da967747ed8 + license: CECILL-C + purls: [] + size: 21748 + timestamp: 1718731802510 +- kind: conda + name: mumps-seq + version: 5.7.2 + build: h6e8dedb_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/mumps-seq-5.7.2-h6e8dedb_0.conda + sha256: 7438d262cd488a76ce0f85654b0f9d645224ede99d9cc67344698fa6585520ac + md5: 759b4c48af5afea2af246aa4dfe27304 + depends: + - libblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + - liblapack >=3.9.0,<4.0a0 + - libscotch >=7.0.4,<7.0.5.0a0 + - metis >=5.1.0,<5.1.1.0a0 + - mumps-include >=5.7.2,<5.7.3.0a0 + license: CECILL-C + purls: [] + size: 2035746 + timestamp: 1718731935071 +- kind: conda + name: ncurses + version: '6.5' + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h59595ed_0.conda + sha256: 4fc3b384f4072b68853a0013ea83bdfd3d66b0126e2238e1d6e1560747aa7586 + md5: fcea371545eda051b6deafb24889fc69 + depends: + - libgcc-ng >=12 + license: X11 AND BSD-3-Clause + purls: [] + size: 887465 + timestamp: 1715194722503 +- kind: pypi + name: nodeenv + version: 1.9.1 + url: https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl + sha256: ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9 + requires_python: '>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*' +- kind: conda + name: numpy + version: 1.26.4 + build: py312heda63a1_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + sha256: fe3459c75cf84dcef6ef14efcc4adb0ade66038ddd27cadb894f34f4797687d8 + md5: d8285bea2a350f63fab23bf460221f3f + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + constrains: + - numpy-base <0a0 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/numpy?source=conda-forge-mapping + size: 7484186 + timestamp: 1707225809722 +- kind: conda + name: octomap + version: 1.9.8 + build: h924138e_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/octomap-1.9.8-h924138e_0.tar.bz2 + sha256: a4258176de30ccfbf3b13b97391a9c0b9f5a4d513d964d139d7f70dd45676543 + md5: 06e95e004ea7181cd1bab08276b09471 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 264375 + timestamp: 1668155567283 +- kind: conda + name: openssl + version: 3.3.1 + build: h4bc722e_2 + build_number: 2 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.3.1-h4bc722e_2.conda + sha256: b294b3cc706ad1048cdb514f0db3da9f37ae3fcc0c53a7104083dd0918adb200 + md5: e1b454497f9f7c1147fdde4b53f1b512 + depends: + - __glibc >=2.17,<3.0.a0 + - ca-certificates + - libgcc-ng >=12 + constrains: + - pyopenssl >=22.1 + license: Apache-2.0 + license_family: Apache + purls: [] + size: 2895213 + timestamp: 1721194688955 +- kind: pypi + name: packaging + version: '24.1' + url: https://files.pythonhosted.org/packages/08/aa/cc0199a5f0ad350994d660967a8efb233fe0416e4639146c089643407ce6/packaging-24.1-py3-none-any.whl + sha256: 5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124 + requires_python: '>=3.8' +- kind: conda + name: pinocchio + version: 3.1.0 + build: py312he572396_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pinocchio-3.1.0-py312he572396_1.conda + sha256: 08cde280f118d8929934079df6fd4b2b97205809c1c12ce3e50c4fa747db473a + md5: 50408735732839ee51f0f537be579b20 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex >=4.5 + - casadi >=3.6.5,<3.7.0a0 + - console_bridge >=1.0.2,<1.1.0a0 + - eigen + - eigenpy >=3.7.0,<3.7.1.0a0 + - hpp-fcl >=2.4.4,<2.4.5.0a0 + - libboost >=1.84.0,<1.85.0a0 + - libboost-python >=1.84.0,<1.85.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - numpy >=1.26.4,<2.0a0 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - qhull >=2020.2,<2020.3.0a0 + - qhull-static + - urdfdom >=4.0.0,<4.1.0a0 + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 15098684 + timestamp: 1721065986639 +- kind: pypi + name: platformdirs + version: 4.2.2 + url: https://files.pythonhosted.org/packages/68/13/2aa1f0e1364feb2c9ef45302f387ac0bd81484e9c9a4c5688a322fbdfd08/platformdirs-4.2.2-py3-none-any.whl + sha256: 2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee + requires_dist: + - furo>=2023.9.10 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx-autodoc-typehints>=1.25.2 ; extra == 'docs' + - sphinx>=7.2.6 ; extra == 'docs' + - appdirs==1.4.4 ; extra == 'test' + - covdefaults>=2.3 ; extra == 'test' + - pytest-cov>=4.1 ; extra == 'test' + - pytest-mock>=3.12 ; extra == 'test' + - pytest>=7.4.3 ; extra == 'test' + - mypy>=1.8 ; extra == 'type' + requires_python: '>=3.8' +- kind: pypi + name: pluggy + version: 1.5.0 + url: https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl + sha256: 44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669 + requires_dist: + - pre-commit ; extra == 'dev' + - tox ; extra == 'dev' + - pytest ; extra == 'testing' + - pytest-benchmark ; extra == 'testing' + requires_python: '>=3.8' +- kind: pypi + name: pre-commit + version: 3.8.0 + url: https://files.pythonhosted.org/packages/07/92/caae8c86e94681b42c246f0bca35c059a2f0529e5b92619f6aba4cf7e7b6/pre_commit-3.8.0-py2.py3-none-any.whl + sha256: 9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f + requires_dist: + - cfgv>=2.0.0 + - identify>=1.0.0 + - nodeenv>=0.11.1 + - pyyaml>=5.1 + - virtualenv>=20.10.0 + requires_python: '>=3.9' +- kind: conda + name: proxsuite + version: 0.6.6 + build: py312h2492b07_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/proxsuite-0.6.6-py312h2492b07_0.conda + sha256: 7cab86b44ed33623399efe1ce40863e5f895289d76586e5c77852de634042219 + md5: 4fda2a68d9ef0db54360178548a13285 + depends: + - eigen + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - numpy + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + - scipy + - simde + license: BSD-2-Clause + license_family: BSD + purls: [] + size: 1638721 + timestamp: 1718618654729 +- kind: pypi + name: pyopengl + version: 3.1.7 + url: https://files.pythonhosted.org/packages/99/48/00e31747821d3fc56faddd00a4725454d1e694a8b67d715cf20f531506a5/PyOpenGL-3.1.7-py3-none-any.whl + sha256: a6ab19cf290df6101aaf7470843a9c46207789855746399d0af92521a0a92b7a +- kind: pypi + name: pytest + version: 8.3.2 + url: https://files.pythonhosted.org/packages/0f/f9/cf155cf32ca7d6fa3601bc4c5dd19086af4b320b706919d48a4c79081cf9/pytest-8.3.2-py3-none-any.whl + sha256: 4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5 + requires_dist: + - iniconfig + - packaging + - pluggy<2,>=1.5 + - exceptiongroup>=1.0.0rc8 ; python_version < '3.11' + - tomli>=1 ; python_version < '3.11' + - colorama ; sys_platform == 'win32' + - argcomplete ; extra == 'dev' + - attrs>=19.2 ; extra == 'dev' + - hypothesis>=3.56 ; extra == 'dev' + - mock ; extra == 'dev' + - pygments>=2.7.2 ; extra == 'dev' + - requests ; extra == 'dev' + - setuptools ; extra == 'dev' + - xmlschema ; extra == 'dev' + requires_python: '>=3.8' +- kind: pypi + name: pytest-cov + version: 5.0.0 + url: https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl + sha256: 4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652 + requires_dist: + - pytest>=4.6 + - coverage[toml]>=5.2.1 + - fields ; extra == 'testing' + - hunter ; extra == 'testing' + - process-tests ; extra == 'testing' + - pytest-xdist ; extra == 'testing' + - virtualenv ; extra == 'testing' + requires_python: '>=3.8' +- kind: conda + name: python + version: 3.12.4 + build: h194c7f8_0_cpython + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.12.4-h194c7f8_0_cpython.conda + sha256: 97a78631e6c928bf7ad78d52f7f070fcf3bd37619fa48dc4394c21cf3058cdee + md5: d73490214f536cccb5819e9873048c92 + depends: + - bzip2 >=1.0.8,<2.0a0 + - ld_impl_linux-64 >=2.36.1 + - libexpat >=2.6.2,<3.0a0 + - libffi >=3.4,<4.0a0 + - libgcc-ng >=12 + - libnsl >=2.0.1,<2.1.0a0 + - libsqlite >=3.46.0,<4.0a0 + - libuuid >=2.38.1,<3.0a0 + - libxcrypt >=4.4.36 + - libzlib >=1.3.1,<2.0a0 + - ncurses >=6.5,<7.0a0 + - openssl >=3.3.1,<4.0a0 + - readline >=8.2,<9.0a0 + - tk >=8.6.13,<8.7.0a0 + - tzdata + - xz >=5.2.6,<6.0a0 + constrains: + - python_abi 3.12.* *_cp312 + license: Python-2.0 + purls: [] + size: 32073625 + timestamp: 1718621771849 +- kind: conda + name: python_abi + version: '3.12' + build: 4_cp312 + build_number: 4 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.12-4_cp312.conda + sha256: 182a329de10a4165f6e8a3804caf751f918f6ea6176dd4e5abcdae1ed3095bf6 + md5: dccc2d142812964fcc6abdc97b672dff + constrains: + - python 3.12.* *_cpython + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6385 + timestamp: 1695147396604 +- kind: pypi + name: pyyaml + version: 6.0.1 + url: https://files.pythonhosted.org/packages/b4/33/720548182ffa8344418126017aa1d4ab4aeec9a2275f04ce3f3573d8ace8/PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + sha256: 6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 + requires_python: '>=3.6' +- kind: conda + name: qhull + version: '2020.2' + build: h434a139_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/qhull-2020.2-h434a139_5.conda + sha256: 776363493bad83308ba30bcb88c2552632581b143e8ee25b1982c8c743e73abc + md5: 353823361b1d27eb3960efb076dfcaf6 + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: LicenseRef-Qhull + purls: [] + size: 552937 + timestamp: 1720813982144 +- kind: conda + name: qhull-static + version: '2020.2' + build: h434a139_5 + build_number: 5 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/qhull-static-2020.2-h434a139_5.conda + sha256: b02a0e50dd4b5cb619b862c83cde685988c2a6dceb687198ae9ac3cfa8c4c926 + md5: 0556a8e4d1b88edbf12969718634f3da + depends: + - __glibc >=2.17,<3.0.a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - qhull 2020.2 h434a139_5 + license: LicenseRef-Qhull + purls: [] + size: 444184 + timestamp: 1720814041633 +- kind: conda + name: readline + version: '8.2' + build: h8228510_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/readline-8.2-h8228510_1.conda + sha256: 5435cf39d039387fbdc977b0a762357ea909a7694d9528ab40f005e9208744d7 + md5: 47d31b792659ce70f470b5c82fdfb7a4 + depends: + - libgcc-ng >=12 + - ncurses >=6.3,<7.0a0 + license: GPL-3.0-only + license_family: GPL + purls: [] + size: 281456 + timestamp: 1679532220005 +- kind: pypi + name: robot-descriptions + version: 1.12.0 + url: https://files.pythonhosted.org/packages/4f/0b/49d4d4cd84ffa2d7aded910d0c27f144bdd98e5fbca452b40882c2c0c16e/robot_descriptions-1.12.0-py3-none-any.whl + sha256: d1330a1eae7b0937a60a72f2ea73b030547cc3255292eb404d82a87e8f20ffd5 + requires_dist: + - gitpython>=3.1.18 + - tqdm>=4.64.0 + - idyntree>=8.0.0 ; extra == 'opts' + - mujoco>=3.2.0 ; extra == 'opts' + - pin>=2.6.10 ; extra == 'opts' + - pybullet>=3.2.6 ; extra == 'opts' + - robomeshcat>=1.0.4 ; extra == 'opts' + - yourdfpy>=0.0.56 ; extra == 'opts' + requires_python: '>=3.7' +- kind: conda + name: scipy + version: 1.14.0 + build: py312hc2bc53b_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.14.0-py312hc2bc53b_1.conda + sha256: 6bd24bc823863bb568ffe0ebdfb506d4413d94d15b478b12a0b223d9373f531e + md5: eae80145f63aa04a02dda456d4883b46 + depends: + - libblas >=3.9.0,<4.0a0 + - libcblas >=3.9.0,<4.0a0 + - libgcc-ng >=12 + - libgfortran-ng + - libgfortran5 >=12.3.0 + - liblapack >=3.9.0,<4.0a0 + - libstdcxx-ng >=12 + - numpy <2.3 + - numpy >=1.19,<3 + - python >=3.12,<3.13.0a0 + - python_abi 3.12.* *_cp312 + license: BSD-3-Clause + license_family: BSD + purls: + - pkg:pypi/scipy?source=conda-forge-mapping + size: 17653680 + timestamp: 1720324049729 +- kind: conda + name: simde + version: 0.8.2 + build: h297d8ca_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/simde-0.8.2-h297d8ca_0.conda + sha256: d152e4d14dd6b328c8020da542af08f68a6ee9db05c534926c9f576755ce654d + md5: 9dedc1a9db2e61dea861988bf0a47849 + license: MIT + license_family: MIT + purls: [] + size: 483976 + timestamp: 1714665319038 +- kind: pypi + name: smmap + version: 5.0.1 + url: https://files.pythonhosted.org/packages/a7/a5/10f97f73544edcdef54409f1d839f6049a0d79df68adbc1ceb24d1aaca42/smmap-5.0.1-py3-none-any.whl + sha256: e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da + requires_python: '>=3.7' +- kind: conda + name: tinyxml2 + version: 10.0.0 + build: h59595ed_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/tinyxml2-10.0.0-h59595ed_0.conda + sha256: e89306d01999f629a329ddb2e2ca9b8fbfe7c483d13f9805f0c6891a24a6e9c8 + md5: 5e27e4a780264caed4be372ded70a9e9 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: Zlib + purls: [] + size: 120640 + timestamp: 1704495493222 +- kind: conda + name: tk + version: 8.6.13 + build: noxft_h4845f30_101 + build_number: 101 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.13-noxft_h4845f30_101.conda + sha256: e0569c9caa68bf476bead1bed3d79650bb080b532c64a4af7d8ca286c08dea4e + md5: d453b98d9c83e71da0741bb0ff4d76bc + depends: + - libgcc-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: TCL + license_family: BSD + purls: [] + size: 3318875 + timestamp: 1699202167581 +- kind: pypi + name: tqdm + version: 4.66.5 + url: https://files.pythonhosted.org/packages/48/5d/acf5905c36149bbaec41ccf7f2b68814647347b72075ac0b1fe3022fdc73/tqdm-4.66.5-py3-none-any.whl + sha256: 90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd + requires_dist: + - colorama ; platform_system == 'Windows' + - pytest>=6 ; extra == 'dev' + - pytest-cov ; extra == 'dev' + - pytest-timeout ; extra == 'dev' + - pytest-xdist ; extra == 'dev' + - ipywidgets>=6 ; extra == 'notebook' + - slack-sdk ; extra == 'slack' + - requests ; extra == 'telegram' + requires_python: '>=3.7' +- kind: pypi + name: typing-extensions + version: 4.12.2 + url: https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl + sha256: 04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d + requires_python: '>=3.8' +- kind: conda + name: tzdata + version: 2024a + build: h0c530f3_0 + subdir: noarch + noarch: generic + url: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024a-h0c530f3_0.conda + sha256: 7b2b69c54ec62a243eb6fba2391b5e443421608c3ae5dbff938ad33ca8db5122 + md5: 161081fc7cec0bfda0d86d7cb595f8d8 + license: LicenseRef-Public-Domain + purls: [] + size: 119815 + timestamp: 1706886945727 +- kind: conda + name: unixodbc + version: 2.3.12 + build: h661eb56_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/unixodbc-2.3.12-h661eb56_0.conda + sha256: 718eb807a5e6e6993ee06745cb2a25a6b353427485a6e50df01db99c6016a53f + md5: a737e5c549c13fbb5590c581848b0446 + depends: + - libedit >=3.1.20191231,<3.2.0a0 + - libgcc-ng >=12 + - libiconv >=1.17,<2.0a0 + - libstdcxx-ng >=12 + license: LGPL-2.1 + purls: [] + size: 281830 + timestamp: 1691504075258 +- kind: conda + name: urdfdom + version: 4.0.0 + build: hee28ff1_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/urdfdom-4.0.0-hee28ff1_1.conda + sha256: 9d3e05fcc27ab26da05cbbf2e4b2a9758179769b02dd05251da5bea9eab4aa84 + md5: 35552fa73a1abca7183b3d5c18065c49 + depends: + - console_bridge >=1.0.2,<1.1.0a0 + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - tinyxml2 >=10.0.0,<11.0a0 + - urdfdom_headers + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 106196 + timestamp: 1704626684063 +- kind: conda + name: urdfdom_headers + version: 1.1.1 + build: h00ab1b0_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/urdfdom_headers-1.1.1-h00ab1b0_0.conda + sha256: 8a4834d2ef3bbbb1317aeb7050d55af7bbf03f403367cf208cebe10aed08d8ea + md5: 0c93705030e070a6c8cc15d4292004db + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 19445 + timestamp: 1703634091466 +- kind: pypi + name: virtualenv + version: 20.26.3 + url: https://files.pythonhosted.org/packages/07/4d/410156100224c5e2f0011d435e477b57aed9576fc7fe137abcf14ec16e11/virtualenv-20.26.3-py3-none-any.whl + sha256: 8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589 + requires_dist: + - distlib<1,>=0.3.7 + - filelock<4,>=3.12.2 + - importlib-metadata>=6.6 ; python_version < '3.8' + - platformdirs<5,>=3.9.1 + - furo>=2023.7.26 ; extra == 'docs' + - proselint>=0.13 ; extra == 'docs' + - sphinx!=7.3,>=7.1.2 ; extra == 'docs' + - sphinx-argparse>=0.4 ; extra == 'docs' + - sphinxcontrib-towncrier>=0.2.1a0 ; extra == 'docs' + - towncrier>=23.6 ; extra == 'docs' + - covdefaults>=2.3 ; extra == 'test' + - coverage-enable-subprocess>=1 ; extra == 'test' + - coverage>=7.2.7 ; extra == 'test' + - flaky>=3.7 ; extra == 'test' + - packaging>=23.1 ; extra == 'test' + - pytest-env>=0.8.2 ; extra == 'test' + - pytest-freezer>=0.4.8 ; (platform_python_implementation == 'PyPy' or (platform_python_implementation == 'CPython' and sys_platform == 'win32' and python_version >= '3.13')) and extra == 'test' + - pytest-mock>=3.11.1 ; extra == 'test' + - pytest-randomly>=3.12 ; extra == 'test' + - pytest-timeout>=2.1 ; extra == 'test' + - pytest>=7.4 ; extra == 'test' + - setuptools>=68 ; extra == 'test' + - time-machine>=2.10 ; platform_python_implementation == 'CPython' and extra == 'test' + requires_python: '>=3.7' +- kind: conda + name: xz + version: 5.2.6 + build: h166bdaf_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 + sha256: 03a6d28ded42af8a347345f82f3eebdd6807a08526d47899a42d62d319609162 + md5: 2161070d867d1b1204ea749c8eec4ef0 + depends: + - libgcc-ng >=12 + license: LGPL-2.1 and GPL-2.0 + purls: [] + size: 418368 + timestamp: 1660346797927 +- kind: pypi + name: zipp + version: 3.20.1 + url: https://files.pythonhosted.org/packages/07/9e/c96f7a4cd0bf5625bb409b7e61e99b1130dc63a98cb8b24aeabae62d43e8/zipp-3.20.1-py3-none-any.whl + sha256: 9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064 + requires_dist: + - pytest-checkdocs>=2.4 ; extra == 'check' + - pytest-ruff>=0.2.1 ; sys_platform != 'cygwin' and extra == 'check' + - pytest-cov ; extra == 'cover' + - sphinx>=3.5 ; extra == 'doc' + - jaraco-packaging>=9.3 ; extra == 'doc' + - rst-linker>=1.9 ; extra == 'doc' + - furo ; extra == 'doc' + - sphinx-lint ; extra == 'doc' + - jaraco-tidelift>=1.4 ; extra == 'doc' + - pytest-enabler>=2.2 ; extra == 'enabler' + - pytest!=8.1.*,>=6 ; extra == 'test' + - jaraco-itertools ; extra == 'test' + - jaraco-functools ; extra == 'test' + - more-itertools ; extra == 'test' + - big-o ; extra == 'test' + - pytest-ignore-flaky ; extra == 'test' + - jaraco-test ; extra == 'test' + - importlib-resources ; python_version < '3.9' and extra == 'test' + - pytest-mypy ; extra == 'type' + requires_python: '>=3.8' +- kind: conda + name: zlib + version: 1.3.1 + build: h4ab18f5_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-h4ab18f5_1.conda + sha256: cee16ab07a11303de721915f0a269e8c7a54a5c834aa52f74b1cc3a59000ade8 + md5: 9653f1bf3766164d0e65fa723cabbc54 + depends: + - libgcc-ng >=12 + - libzlib 1.3.1 h4ab18f5_1 + license: Zlib + license_family: Other + purls: [] + size: 93004 + timestamp: 1716874213487 +- kind: conda + name: zstd + version: 1.5.6 + build: ha6fb4c9_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda + sha256: c558b9cc01d9c1444031bd1ce4b9cff86f9085765f17627a6cd85fc623c8a02b + md5: 4d056880988120e29d75bfff282e0f45 + depends: + - libgcc-ng >=12 + - libstdcxx-ng >=12 + - libzlib >=1.2.13,<2.0.0a0 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 554846 + timestamp: 1714722996770 diff --git a/pyproject.toml b/pyproject.toml index f7f4670..5e9ae65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,9 @@ [project] name = "darli" -description = "The DARLi is a Python 3 library that supports both numerical and symbolical computations of open loop articulated robots provided urdf file." -version = "0.4.3" +description = "The DARLi is a Python 3 library that supports numerical and symbolical computations of open loop articulated robots provided urdf file." +version = "0.5.0" authors = [{ name = "Lev Kozlov" }, { name = "Simeon Nedelchev" }] -dependencies = ["cmeel_casadi_kin_dyn>=1.6.14"] +dependencies = ["pytest>=8.3.2,<9", "robot-descriptions>=1.12.0,<2", "mujoco>=3.2.2,<4", "pytest-cov>=5.0.0,<6"] readme = "README.md" requires-python = ">=3.9" @@ -34,3 +34,19 @@ packages = [ "darli.utils.arrays", "darli.utils.quaternions", ] + +[tool.pixi.project] +channels = ["conda-forge"] +platforms = ["linux-64"] + +[tool.pixi.pypi-dependencies] +darli = { path = ".", editable = true } + +[tool.pixi.environments] +default = { solve-group = "default" } +dev = { features = ["dev"], solve-group = "default" } + +[tool.pixi.tasks] + +[tool.pixi.dependencies] +pinocchio = ">=3.1.0,<4" diff --git a/tests/test_backend.py b/tests/test_backend.py new file mode 100644 index 0000000..0a224f3 --- /dev/null +++ b/tests/test_backend.py @@ -0,0 +1,211 @@ +import pytest +import numpy as np +import casadi as cs +from darli.backend import PinocchioBackend, BackendBase, JointType, CasadiBackend + +# Import model paths +from robot_descriptions.panda_description import URDF_PATH as PANDA_URDF_PATH +from robot_descriptions.panda_mj_description import MJCF_PATH as PANDA_MJCF_PATH +from robot_descriptions.h1_description import URDF_PATH as H1_URDF_PATH + + +# Fixture for test data for the Panda URDF model +@pytest.fixture +def panda_urdf_data(): + return { + "q": np.array([0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0, 0]), + "v": np.array([0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0, 0]), + "dv": np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0]), + "tau": np.array([0.1, 0.0, -0.1, 0.0, 0.1, 0.0, -0.1, 0, 0]), + "body_name": "panda_link7", + "force": np.array([-9.81, 0.0, 0.0]), + "mu": 0.4, + "type": "point", + } + + +# Fixture for test data for the Panda MJCF model +@pytest.fixture +def panda_mjcf_data(): + return { + "q": np.array([0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0, 0]), + "v": np.array([0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0, 0]), + "dv": np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0]), + "tau": np.array([0.1, 0.0, -0.1, 0.0, 0.1, 0.0, -0.1, 0, 0]), + "body_name": "link7", + "force": np.array([-9.81, 0.0, 0.0]), + "mu": 0.4, + "type": "point", + } + + +# Fixture for test data for the H1 URDF model +@pytest.fixture +def h1_urdf_data(): + return { + "q": np.concatenate([np.array([0, 0, 0, 0, 0, 0, 1]), np.zeros(19)]), + "v": np.zeros(25), + "dv": np.zeros(25), + "tau": np.zeros(25), + "body_name": "right_elbow_link", + "force": np.array([-9.81, 0.0, 0.0]), + "mu": 0.4, + "type": "sliding", + "dt": 0.02, + } + + +# Fixture for test data for the Panda URDF model with Casadi backend +@pytest.fixture +def panda_urdf_data_casadi(): + return { + "q": cs.SX.sym("q", 9), + "v": cs.SX.sym("v", 9), + "dv": cs.SX.sym("dv", 9), + "tau": cs.SX.sym("tau", 9), + "body_name": "panda_link7", + "force": np.array([-9.81, 0.0, 0.0]), + "mu": 0.4, + "type": "point", + } + + +# Fixture for test data for the Panda MJCF model with Casadi backend +@pytest.fixture +def panda_mjcf_data_casadi(): + return { + "q": cs.SX.sym("q", 9), + "v": cs.SX.sym("v", 9), + "dv": cs.SX.sym("dv", 9), + "tau": cs.SX.sym("tau", 9), + "body_name": "link7", + "force": np.array([-9.81, 0.0, 0.0]), + "mu": 0.4, + "type": "point", + } + + +# Fixture for test data for the H1 URDF model with Casadi backend +@pytest.fixture +def h1_urdf_data_casadi(): + return { + "q": cs.SX.sym("q", 26), + "v": cs.SX.sym("v", 25), + "dv": cs.SX.sym("dv", 25), + "tau": cs.SX.sym("tau", 25), + "body_name": "right_elbow_link", + "force": np.array([-9.81, 0.0, 0.0]), + "mu": 0.4, + "type": "sliding", + } + + +# Helper function to run common tests on any backend +def run_backend_tests(backend: BackendBase, data): + backend.update(data["q"], data["v"], data["dv"], data["tau"]) + + assert backend.rnea(data["q"], data["v"], data["dv"]) is not None + assert backend.aba(data["q"], data["v"], data["tau"]) is not None + assert backend.inertia_matrix(data["q"]) is not None + assert backend.kinetic_energy(data["q"], data["v"]) is not None + assert backend.potential_energy(data["q"]) is not None + assert backend.jacobian(data["q"]) is not None + assert backend.jacobian_dt(data["q"], data["v"]) is not None + assert backend.com_pos(data["q"]) is not None + assert backend.com_vel(data["q"], data["v"]) is not None + assert backend.com_acc(data["q"], data["v"], data["dv"]) is not None + assert backend.torque_regressor(data["q"], data["v"], data["dv"]) is not None + assert backend.kinetic_regressor(data["q"], data["v"]) is not None + assert backend.potential_regressor(data["q"]) is not None + + # test momentum regressor only for PinocchioBackend + # TODO: change when CasadiBackend implements momentum_regressor + if isinstance(backend, PinocchioBackend): + assert backend.momentum_regressor(data["q"], data["v"]) is not None + assert backend.centroidal_dynamics(data["q"], data["v"], data["dv"]) is not None + + # try update_body with existing and non-existing body names + assert backend.update_body(data["body_name"]) is not None + # should return a KeyError + pytest.raises(KeyError, backend.update_body, "non_existent_body") + + assert backend.cone(data["force"], data["mu"], data["type"]) is not None + assert backend.integrate_configuration(data["q"], data["v"]) is not None + + +# Fixture to create backend for the Panda URDF model +@pytest.fixture +def panda_urdf_backend(panda_urdf_data): + backend_instance = PinocchioBackend(PANDA_URDF_PATH) + return backend_instance, panda_urdf_data + + +# Fixture to create backend for the Panda MJCF model +@pytest.fixture +def panda_mjcf_backend(panda_mjcf_data): + backend_instance = PinocchioBackend(PANDA_MJCF_PATH) + return backend_instance, panda_mjcf_data + + +# Fixture to create backend for the H1 URDF model +@pytest.fixture +def h1_urdf_backend(h1_urdf_data): + backend_instance = PinocchioBackend(H1_URDF_PATH, root_joint=JointType.FREE_FLYER) + return backend_instance, h1_urdf_data + + +# Tests for Panda URDF backend +def test_panda_urdf_backend(panda_urdf_backend): + backend, data = panda_urdf_backend + run_backend_tests(backend, data) + + +# Tests for Panda MJCF backend +def test_panda_mjcf_backend(panda_mjcf_backend): + backend, data = panda_mjcf_backend + run_backend_tests(backend, data) + + +# Tests for H1 URDF backend +def test_h1_urdf_backend(h1_urdf_backend): + backend, data = h1_urdf_backend + run_backend_tests(backend, data) + + +# Fixture to create Casadi backend for the Panda URDF model +@pytest.fixture +def panda_urdf_backend_casadi(panda_urdf_data_casadi): + backend_instance = CasadiBackend(PANDA_URDF_PATH) + return backend_instance, panda_urdf_data_casadi + + +# Fixture to create Casadi backend for the Panda MJCF model +@pytest.fixture +def panda_mjcf_backend_casadi(panda_mjcf_data_casadi): + backend_instance = CasadiBackend(PANDA_MJCF_PATH) + return backend_instance, panda_mjcf_data_casadi + + +# Fixture to create Casadi backend for the H1 URDF model +@pytest.fixture +def h1_urdf_backend_casadi(h1_urdf_data_casadi): + backend_instance = CasadiBackend(H1_URDF_PATH, root_joint=JointType.FREE_FLYER) + return backend_instance, h1_urdf_data_casadi + + +# Tests for Casadi backend with Panda URDF model +def test_panda_urdf_backend_casadi(panda_urdf_backend_casadi): + backend, data = panda_urdf_backend_casadi + run_backend_tests(backend, data) + + +# Tests for Casadi backend with Panda MJCF model +def test_panda_mjcf_backend_casadi(panda_mjcf_backend_casadi): + backend, data = panda_mjcf_backend_casadi + run_backend_tests(backend, data) + + +# Tests for Casadi backend with H1 URDF model +def test_h1_urdf_backend_casadi(h1_urdf_backend_casadi): + backend, data = h1_urdf_backend_casadi + run_backend_tests(backend, data) diff --git a/tests/test_model.py b/tests/test_model.py new file mode 100644 index 0000000..998c4e8 --- /dev/null +++ b/tests/test_model.py @@ -0,0 +1,148 @@ +import pytest +import numpy as np +from darli.model import Model +from darli.model.functional import Functional +from darli.backend import PinocchioBackend, CasadiBackend, JointType + +# Import model paths +from robot_descriptions.panda_description import URDF_PATH as PANDA_URDF_PATH +from robot_descriptions.panda_mj_description import MJCF_PATH as PANDA_MJCF_PATH +from robot_descriptions.h1_description import URDF_PATH as H1_URDF_PATH + + +# Fixture for test data (numeric) +@pytest.fixture +def test_data(): + return { + "q": np.array([0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0, 0]), + "v": np.array([0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0, 0]), + "dv": np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0]), + "tau": np.array([0.1, 0.0, -0.1, 0.0, 0.1, 0.0, -0.1, 0, 0]), + } + + +@pytest.fixture +def test_data_h1(): + return { + "q": np.concatenate([np.array([0, 0, 0, 0, 0, 0, 1]), np.zeros(19)]), + "v": np.zeros(25), + "dv": np.zeros(25), + "tau": np.zeros(25), + } + + +# Fixture to create Model instance with PinocchioBackend (Panda URDF) +@pytest.fixture +def model_instance_panda_urdf(test_data): + backend = PinocchioBackend(PANDA_URDF_PATH) + model = Model(backend) + return model, test_data + + +# Fixture to create FunctionalModel instance with CasadiBackend (Panda URDF) +@pytest.fixture +def functional_model_instance_panda_urdf(test_data): + backend = CasadiBackend(PANDA_URDF_PATH) + functional_model = Functional(backend) + return functional_model, test_data + + +# Fixture to create Model instance with PinocchioBackend (Panda MJCF) +@pytest.fixture +def model_instance_panda_mjcf(test_data): + backend = PinocchioBackend(PANDA_MJCF_PATH) + model = Model(backend) + return model, test_data + + +# Fixture to create FunctionalModel instance with CasadiBackend (Panda MJCF) +@pytest.fixture +def functional_model_instance_panda_mjcf(test_data): + backend = CasadiBackend(PANDA_MJCF_PATH) + functional_model = Functional(backend) + return functional_model, test_data + + +# Fixture to create Model instance with PinocchioBackend (H1 URDF) +@pytest.fixture +def model_instance_h1(test_data_h1): + backend = PinocchioBackend( + H1_URDF_PATH, root_joint=JointType.FREE_FLYER + ) # Assuming the H1 URDF requires a free flyer joint + model = Model(backend) + return model, test_data_h1 + + +# Fixture to create FunctionalModel instance with CasadiBackend (H1 URDF) +@pytest.fixture +def functional_model_instance_h1(test_data_h1): + backend = CasadiBackend(H1_URDF_PATH, root_joint=JointType.FREE_FLYER) + functional_model = Functional(backend) + return functional_model, test_data_h1 + + +# Helper function to run comparison tests between Model and FunctionalModel +def compare_model_outputs(model, functional_model, data): + q, v, dv, tau = data["q"], data["v"], data["dv"], data["tau"] + + # compare com + assert np.allclose( + model.com(q).position, np.array(functional_model.com.position(q)).flatten() + ) + assert np.allclose( + model.com(q, v).velocity, + np.array(functional_model.com.velocity(q, v)).flatten(), + ) + assert np.allclose( + model.com(q, v, dv).acceleration, + np.array(functional_model.com.acceleration(q, v, dv)).flatten(), + ) + assert np.allclose( + model.com(q).jacobian, np.array(functional_model.com.jacobian(q)) + ) + + # compare energy + assert np.isclose(model.energy(q, v).kinetic, functional_model.energy.kinetic(q, v)) + assert np.isclose(model.energy(q).potential, functional_model.energy.potential(q)) + + # compare inertia + assert np.allclose(model.inertia(q), np.array(functional_model.inertia(q))) + + # compare coriolis + assert np.allclose( + model.coriolis(q, v), np.array(functional_model.coriolis(q, v)).flatten() + ) + + # compare bias force + assert np.allclose( + model.bias_force(q, v), np.array(functional_model.bias_force(q, v)).flatten() + ) + + # compare forward dynamics + assert np.allclose( + model.forward_dynamics(q, v, tau), + np.array(functional_model.forward_dynamics(q, v, tau)).flatten(), + ) + + # compare inverse dynamics + assert np.allclose( + model.inverse_dynamics(q, v, dv), + np.array(functional_model.inverse_dynamics(q, v, dv)).flatten(), + ) + + +# Test to compare Model and FunctionalModel outputs using the same numeric data +@pytest.mark.parametrize( + "model_fixture, functional_fixture", + [ + ("model_instance_panda_urdf", "functional_model_instance_panda_urdf"), + ("model_instance_panda_mjcf", "functional_model_instance_panda_mjcf"), + ("model_instance_h1", "functional_model_instance_h1"), + ], +) +def test_compare_model_functional_model_outputs( + request, model_fixture, functional_fixture +): + model, data = request.getfixturevalue(model_fixture) + functional_model, _ = request.getfixturevalue(functional_fixture) + compare_model_outputs(model, functional_model, data) diff --git a/tutorial/00_intro.ipynb b/tutorial/00_intro.ipynb index fe1ee06..e8dbbe7 100644 --- a/tutorial/00_intro.ipynb +++ b/tutorial/00_intro.ipynb @@ -1,5 +1,39 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "WHAT IS DARLI\n", + "\n", + "WHAT TO EXPECT NEXT\n", + "\n", + "The model in DARLi is a building block that can be further extended with external forces and contacts, different selector matrices, friction in joints, state space and parametric representations, please follow up to the next steps of tutorial to get in to that.\n", + "\n", + "- General-info\n", + "- Backends\n", + "- Models \n", + "- Floating Base,Conventions \n", + "- Further Read and Structure\n", + "\n", + "- Model of Poly-Articulated system\n", + "- Conventions\n", + "- rnea and aba\n", + "- Floating Base\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "OTHER TUTORS:\n", + "* MODELS, BODIES, SELECTORS ETC\n", + "* FUNCTIONAL, CODE GEN, BATCHED\n", + "* STATE SPACE \n", + "* PARAMETRIC REPRESENTATIONS\n" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -30,10 +64,9 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "%%capture\n", "!pip3 install robot_descriptions\n", - "from robot_descriptions import iiwa_description" + "from robot_descriptions import panda_description, panda_mj_description" ] }, { @@ -65,9 +98,45 @@ "from darli.backend import CasadiBackend, PinocchioBackend\n", "\n", "# Building the Pinnochio backend\n", - "pin_backend = PinocchioBackend(iiwa_description.URDF_PATH)\n", + "pin_backend = PinocchioBackend(panda_description.URDF_PATH)\n", "# Building the CasADi backend\n", - "cas_backend = CasadiBackend(iiwa_description.URDF_PATH)" + "cas_backend = CasadiBackend(panda_mj_description.MJCF_PATH)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cas_backend.nq" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(panda_description.URDF_PATH)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(panda_mj_description.MJCF_PATH)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cas_backend.nq" ] }, { @@ -208,7 +277,7 @@ "metadata": {}, "outputs": [], "source": [ - "casadi_model = Model(CasadiBackend(iiwa_description.URDF_PATH))" + "casadi_model = Model(cas_backend)" ] }, { @@ -324,7 +393,7 @@ "# Functionalal computation\n", "print(\"Functional:\", inertia(cs.SX.sym(\"q\", nq)))\n", "# Numerical computation\n", - "print(\"Numerical:\", inertia(np.random.randn(nq)))" + "# print(\"Numerical:\", inertia(np.random.randn(nq)))" ] }, { @@ -347,7 +416,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.energy" + "casadi_model.energy()" ] }, { @@ -356,13 +425,13 @@ "metadata": {}, "outputs": [], "source": [ - "com_position = model.com.position\n", - "com_velocity = model.com.velocity\n", - "com_jacobian = model.com.jacobian\n", - "com_jacobian_dt = model.com.jacobian_dt\n", - "potential_energy = model.energy.potential\n", - "kinetic_energy = model.energy.kinetic\n", - "lagrangian = model.lagrangian\n", + "com_position = casadi_model.com().position\n", + "com_velocity = casadi_model.com().velocity\n", + "com_jacobian = casadi_model.com().jacobian\n", + "com_jacobian_dt = casadi_model.com().jacobian_dt\n", + "potential_energy = casadi_model.energy().potential\n", + "kinetic_energy = casadi_model.energy().kinetic\n", + "lagrangian = casadi_model.lagrangian()\n", "\n", "# TODO\n", "# momentum" @@ -400,7 +469,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.contact_qforce" + "casadi_model.contact_qforce" ] }, { @@ -409,7 +478,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.inverse_dynamics" + "casadi_model.inverse_dynamics()" ] }, { @@ -436,7 +505,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.contact_qforce" + "casadi_model.contact_qforce" ] }, { @@ -445,7 +514,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.forward_dynamics" + "casadi_model.forward_dynamics()" ] }, { @@ -477,10 +546,10 @@ "source": [ "import numpy as np\n", "\n", - "print(f\"Old input dimensions: {model.nu}\")\n", - "S = np.random.randn(model.nv, model.nv + 2)\n", - "model.update_selector(S)\n", - "print(f\"New input dimensions: {model.nu}\")" + "print(f\"Old input dimensions: {casadi_model.nu}\")\n", + "S = np.random.randn(casadi_model.nv, casadi_model.nv + 2)\n", + "casadi_model.update_selector(S)\n", + "print(f\"New input dimensions: {casadi_model.nu}\")" ] }, { @@ -489,7 +558,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.qfrc_u" + "casadi_model.qfrc_u" ] }, { @@ -498,7 +567,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.forward_dynamics" + "casadi_model.forward_dynamics" ] }, { @@ -507,9 +576,9 @@ "metadata": {}, "outputs": [], "source": [ - "model.update_selector(passive_joints=range(3))\n", - "print(f\"New input dimensions: {model.nu}\")\n", - "print(f\"New selector:\\n {model.selector}\")" + "casadi_model.update_selector(passive_joints=range(3))\n", + "print(f\"New input dimensions: {casadi_model.nu}\")\n", + "print(f\"New selector:\\n {casadi_model.selector}\")" ] }, { @@ -518,7 +587,7 @@ "metadata": {}, "outputs": [], "source": [ - "model.forward_dynamics" + "casadi_model.forward_dynamics" ] }, { @@ -534,8 +603,17 @@ "metadata": {}, "outputs": [], "source": [ - "model.add_body([\"link06\"])\n", - "model.bodies" + "print(casadi_model.backend.description_path)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "casadi_model.add_body([\"FL_calf\"])\n", + "casadi_model.bodies" ] }, { @@ -782,9 +860,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" - }, - "orig_nbformat": 4 + "version": "3.10.12" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/tutorial/01_model.ipynb b/tutorial/01_model.ipynb index b6f8138..72f2f1e 100644 --- a/tutorial/01_model.ipynb +++ b/tutorial/01_model.ipynb @@ -665,9 +665,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" - }, - "orig_nbformat": 4 + "version": "3.10.12" + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/tutorial/02_state_space.ipynb b/tutorial/02_state_space.ipynb index d1cd5b9..ffc8b57 100644 --- a/tutorial/02_state_space.ipynb +++ b/tutorial/02_state_space.ipynb @@ -594,8 +594,7 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" - }, - "orig_nbformat": 4 + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/tutorial/03_functional.ipynb b/tutorial/03_functional.ipynb index 35bcc97..8094225 100644 --- a/tutorial/03_functional.ipynb +++ b/tutorial/03_functional.ipynb @@ -224,8 +224,7 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" - }, - "orig_nbformat": 4 + } }, "nbformat": 4, "nbformat_minor": 2 diff --git a/tutorial/04_parametric.ipynb b/tutorial/04_parametric.ipynb index 1fb3b4d..8d0c169 100644 --- a/tutorial/04_parametric.ipynb +++ b/tutorial/04_parametric.ipynb @@ -37,7 +37,7 @@ "metadata": {}, "outputs": [], "source": [ - "from robot_descriptions import iiwa_description" + "from robot_descriptions import iiwa14_description" ] }, { @@ -95,7 +95,7 @@ "metadata": {}, "outputs": [], "source": [ - "model = Functional(CasadiBackend(iiwa_description.URDF_PATH))" + "model = Functional(CasadiBackend(iiwa14_description.URDF_PATH))" ] }, { @@ -313,9 +313,8 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" - }, - "orig_nbformat": 4 + "version": "3.10.14" + } }, "nbformat": 4, "nbformat_minor": 2