# Copyright 2025 DeepMind Technologies Limited## 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.# =============================================================================="""Inverse dynamics functions."""fromjaximportnumpyasjpfrommujoco.mjx._srcimportderivativefrommujoco.mjx._srcimportforwardfrommujoco.mjx._srcimportsensorfrommujoco.mjx._srcimportsmoothfrommujoco.mjx._srcimportsolverfrommujoco.mjx._srcimportsupport# pylint: disable=g-importing-memberfrommujoco.mjx._src.typesimportDatafrommujoco.mjx._src.typesimportDisableBitfrommujoco.mjx._src.typesimportEnableBitfrommujoco.mjx._src.typesimportImplfrommujoco.mjx._src.typesimportIntegratorTypefrommujoco.mjx._src.typesimportModeldefdiscrete_acc(m:Model,d:Data)->Data:"""Convert discrete-time qacc to continuous-time qacc."""ifm.opt.integrator==IntegratorType.RK4:raiseRuntimeError('discrete inverse dynamics is not supported by RK4 integrator')elifm.opt.integrator==IntegratorType.EULER:dsbl_eulerdamp=m.opt.disableflags&DisableBit.EULERDAMPno_dof_damping=(m.dof_damping==0).all()ifdsbl_eulerdamporno_dof_damping:returnd# set qfrc = (M + h*diag(B)) * qaccqfrc=support.mul_m(m,d,d.qacc)qfrc+=m.opt.timestep*m.dof_damping*d.qaccelifm.opt.integrator==IntegratorType.IMPLICITFAST:qm=support.full_m(m,d)# compute analytical derivative qDeriv; skip rne derivativeqderiv=derivative.deriv_smooth_vel(m,d)ifqderivisnotNone:# M = M - dt*qDerivqm-=m.opt.timestep*qderiv# set qfrc = (M - dt*qDeriv) * qaccqfrc=qm@d.qaccelse:raiseNotImplementedError(f'integrator {m.opt.integrator} not implemented.')# solve for qacc: qfrc = M * qaccqacc=smooth.solve_m(m,d,qfrc)returnd.replace(qacc=qacc)definv_constraint(m:Model,d:Data)->Data:"""Inverse constraint solver."""# no constraintsifd._impl.efc_J.size==0:# pytype: disable=attribute-errorreturnd.replace(qfrc_constraint=jp.zeros(m.nv))# updatectx=solver.Context.create(m,d,grad=False)returnd.tree_replace({'qfrc_constraint':ctx.qfrc_constraint,'_impl.efc_force':ctx.efc_force,})