Source code for embodichain.lab.sim.objects.backends.articulation_drive

# ----------------------------------------------------------------------------
# Copyright (c) 2021-2026 DexForce Technology Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ----------------------------------------------------------------------------
"""Backend-specific joint-drive accessors for articulations."""

from __future__ import annotations

import numpy as np

__all__ = ["apply_joint_drive", "read_drive_properties"]


[docs] def read_drive_properties(entity: object, *, is_newton: bool) -> tuple[object, ...]: """Read backend-native joint drive values.""" if is_newton: return tuple(entity.get_newton_drive()) return tuple(entity.get_drive())
[docs] def apply_joint_drive( entity: object, *, is_newton: bool, joint_ids: object, row_index: int, resolved_drive_type: str | None, target_mode_value: int | None, stiffness: object | None = None, damping: object | None = None, max_effort: object | None = None, max_velocity: object | None = None, friction: object | None = None, armature: object | None = None, ) -> None: """Translate and apply one public joint-drive row for a backend.""" def _drive_arg(value: object) -> float | np.ndarray: result = value[row_index].detach().cpu().numpy() return result.item() if result.size == 1 else result if is_newton: if resolved_drive_type == "acceleration" and target_mode_value in {1, 2, 3}: raise NotImplementedError( "Newton Spawn does not have an exact equivalent of the Default " "acceleration drive. Use drive_type='force' or disable the drive." ) drive_args: dict[str, object] = {"joint_ids": joint_ids} if target_mode_value is not None: drive_args["target_mode"] = target_mode_value if stiffness is not None: drive_args["target_ke"] = _drive_arg(stiffness) if damping is not None: drive_args["target_kd"] = _drive_arg(damping) if max_effort is not None: drive_args["effort_limit"] = _drive_arg(max_effort) if max_velocity is not None: drive_args["velocity_limit"] = _drive_arg(max_velocity) if friction is not None: drive_args["friction"] = _drive_arg(friction) if armature is not None: drive_args["armature"] = _drive_arg(armature) if target_mode_value in {0, 4}: drive_args["target_ke"] = 0.0 drive_args["target_kd"] = 0.0 elif target_mode_value == 2: drive_args["target_ke"] = 0.0 entity.set_newton_drive(**drive_args) return drive_args = {"joint_ids": joint_ids} default_drive_type = resolved_drive_type if target_mode_value in {0, 4}: default_drive_type = "none" elif target_mode_value in {1, 2, 3} and default_drive_type is None: default_drive_type = "force" if default_drive_type is not None: # Import lazily to keep this backend helper independent of the object # facade and avoid importing simulation utility modules at package load. from embodichain.lab.sim.utility.sim_utils import get_dexsim_drive_type drive_args["drive_type"] = get_dexsim_drive_type(default_drive_type) if stiffness is not None: drive_args["stiffness"] = _drive_arg(stiffness) if damping is not None: drive_args["damping"] = _drive_arg(damping) if max_effort is not None: drive_args["max_force"] = _drive_arg(max_effort) if max_velocity is not None: drive_args["max_velocity"] = _drive_arg(max_velocity) if friction is not None: drive_args["joint_friction"] = _drive_arg(friction) if armature is not None: drive_args["armature"] = _drive_arg(armature) if target_mode_value in {0, 4}: drive_args["stiffness"] = 0.0 drive_args["damping"] = 0.0 elif target_mode_value == 2: drive_args["stiffness"] = 0.0 entity.set_drive(**drive_args)