diff --git a/doc/APIreference/functions.rst b/doc/APIreference/functions.rst index e90a46db..238d65b8 100644 --- a/doc/APIreference/functions.rst +++ b/doc/APIreference/functions.rst @@ -4113,6 +4113,15 @@ mjs_findFrame Find frame by name. +.. _mjs_findKeyframe: + +mjs_findKeyframe +~~~~~~~~~~~~~~~~ + +.. mujoco-include:: mjs_findKeyframe + +Find keyframe by name. + .. _mjs_getDefault: mjs_getDefault diff --git a/doc/includes/references.h b/doc/includes/references.h index e28671f8..27e54dbb 100644 --- a/doc/includes/references.h +++ b/doc/includes/references.h @@ -3544,6 +3544,7 @@ mjsBody* mjs_findBody(mjSpec* s, const char* name); mjsBody* mjs_findChild(mjsBody* body, const char* name); mjsMesh* mjs_findMesh(mjSpec* s, const char* name); mjsFrame* mjs_findFrame(mjSpec* s, const char* name); +mjsKey* mjs_findKeyframe(mjSpec* s, const char* name); mjsDefault* mjs_getDefault(mjsElement* element); mjsDefault* mjs_findDefault(mjSpec* s, const char* classname); mjsDefault* mjs_getSpecDefault(mjSpec* s); diff --git a/include/mujoco/mujoco.h b/include/mujoco/mujoco.h index 09641110..120518ff 100644 --- a/include/mujoco/mujoco.h +++ b/include/mujoco/mujoco.h @@ -1530,6 +1530,9 @@ MJAPI mjsMesh* mjs_findMesh(mjSpec* s, const char* name); // Find frame by name. MJAPI mjsFrame* mjs_findFrame(mjSpec* s, const char* name); +// Find keyframe by name. +MJAPI mjsKey* mjs_findKeyframe(mjSpec* s, const char* name); + // Get default corresponding to an element. MJAPI mjsDefault* mjs_getDefault(mjsElement* element); diff --git a/introspect/functions.py b/introspect/functions.py index 0bd071c3..2aa42c88 100644 --- a/introspect/functions.py +++ b/introspect/functions.py @@ -9703,6 +9703,28 @@ FUNCTIONS: Mapping[str, FunctionDecl] = dict([ ), doc='Find frame by name.', )), + ('mjs_findKeyframe', + FunctionDecl( + name='mjs_findKeyframe', + return_type=PointerType( + inner_type=ValueType(name='mjsKey'), + ), + parameters=( + FunctionParameterDecl( + name='s', + type=PointerType( + inner_type=ValueType(name='mjSpec'), + ), + ), + FunctionParameterDecl( + name='name', + type=PointerType( + inner_type=ValueType(name='char', is_const=True), + ), + ), + ), + doc='Find keyframe by name.', + )), ('mjs_getDefault', FunctionDecl( name='mjs_getDefault', diff --git a/python/mujoco/specs.cc b/python/mujoco/specs.cc index a0e95cd2..ce5ece39 100644 --- a/python/mujoco/specs.cc +++ b/python/mujoco/specs.cc @@ -144,6 +144,12 @@ PYBIND11_MODULE(_specs, m) { return mjs_findFrame(self.ptr, name.c_str()); }, py::return_value_policy::reference_internal); + mjSpec.def( + "find_keyframe", + [](MjSpec& self, std::string& name) -> raw::MjsKey* { + return mjs_findKeyframe(self.ptr, name.c_str()); + }, + py::return_value_policy::reference_internal); mjSpec.def( "find_default", [](MjSpec& self, std::string& classname) -> raw::MjsDefault* { diff --git a/src/user/user_api.cc b/src/user/user_api.cc index e84fff66..704acd53 100644 --- a/src/user/user_api.cc +++ b/src/user/user_api.cc @@ -530,6 +530,15 @@ mjsFrame* mjs_findFrame(mjSpec* s, const char* name) { +// find keyframe by name +mjsKey* mjs_findKeyframe(mjSpec* s, const char* name) { + mjCModel* model = static_cast(s->element); + mjCKey* key = (mjCKey*)model->FindObject(mjOBJ_KEY, std::string(name)); + return key ? &(static_cast(key)->spec) : nullptr; +} + + + // set frame void mjs_setFrame(mjsElement* dest, mjsFrame* frame) { if (!frame) { diff --git a/src/user/user_api.h b/src/user/user_api.h index 676fe469..000f0154 100644 --- a/src/user/user_api.h +++ b/src/user/user_api.h @@ -194,6 +194,9 @@ MJAPI mjsMesh* mjs_findMesh(mjSpec* s, const char* name); // Find frame by name. MJAPI mjsFrame* mjs_findFrame(mjSpec* s, const char* name); +// Find keyframe by name. +MJAPI mjsKey* mjs_findKeyframe(mjSpec* s, const char* name); + // Get default corresponding to an element. MJAPI mjsDefault* mjs_getDefault(mjsElement* element);