Add "cameraid" attribute to visual/global specifying the default camera to use at model load.

PiperOrigin-RevId: 773783069
Change-Id: I2fff2abdceedc982d89cee8d14b95abceea1c113
This commit is contained in:
Yuval Tassa
2025-06-20 11:39:59 -07:00
committed by Copybara-Service
parent 7dc7a349c5
commit 14dc7c2a60
15 changed files with 58 additions and 16 deletions
+2 -2
View File
@@ -418,7 +418,7 @@ and :math:`\dot q` is the generalized velocity ``mjData.qvel``, then :math:`h =
.. mujoco-include:: mj_name2id .. mujoco-include:: mj_name2id
Get id of object with the specified mjtObj type and name, returns -1 if id not found. Get id of object with the specified :ref:`mjtObj` type and name, returns -1 if id not found.
.. _mj_id2name: .. _mj_id2name:
@@ -427,7 +427,7 @@ Get id of object with the specified mjtObj type and name, returns -1 if id not f
.. mujoco-include:: mj_id2name .. mujoco-include:: mj_id2name
Get name of object with the specified mjtObj type and id, returns NULL if name not found. Get name of object with the specified :ref:`mjtObj` type and id, returns ``NULL`` if name not found.
.. _mj_fullM: .. _mj_fullM:
+8
View File
@@ -231,6 +231,14 @@ generalized velocities to subtree angular momentum. More precisely if :math:`h`
body index ``body`` in ``mjData.subtree_angmom`` (reported by the :ref:`subtreeangmom<sensor-subtreeangmom>` sensor) body index ``body`` in ``mjData.subtree_angmom`` (reported by the :ref:`subtreeangmom<sensor-subtreeangmom>` sensor)
and :math:`\dot q` is the generalized velocity ``mjData.qvel``, then :math:`h = H \dot q`. and :math:`\dot q` is the generalized velocity ``mjData.qvel``, then :math:`h = H \dot q`.
.. _mj_name2id:
Get id of object with the specified :ref:`mjtObj` type and name, returns -1 if id not found.
.. _mj_id2name:
Get name of object with the specified :ref:`mjtObj` type and id, returns ``NULL`` if name not found.
.. _mj_geomDistance: .. _mj_geomDistance:
Returns the smallest signed distance between two geoms and optionally the segment from ``geom1`` to ``geom2``. Returns the smallest signed distance between two geoms and optionally the segment from ``geom1`` to ``geom2``.
+6
View File
@@ -7534,6 +7534,12 @@ coordinated visual settings corresponding to a "theme", and then include this fi
While all settings in mjVisual are global, the settings here could not be fit into any of the other subsections. So this While all settings in mjVisual are global, the settings here could not be fit into any of the other subsections. So this
is effectively a miscellaneous subsection. is effectively a miscellaneous subsection.
.. _visual-global-cameraid:
:at:`cameraid`: :at-val:`int, "-1"`
The id of the camera used when initially loading the model in the visualizer. The default value of -1 means the free
camera. In order to specify a :ref:`modeled camera<body-camera>`, use the camera's id as given by :ref:`mj_name2id`.
.. _visual-global-orthographic: .. _visual-global-orthographic:
:at:`orthographic`: :at-val:`[false, true], "false"` :at:`orthographic`: :at-val:`[false, true], "false"`
+5 -3
View File
@@ -1298,11 +1298,13 @@
| :ref:`global | ? | :class: mjcf-attributes | | :ref:`global | ? | :class: mjcf-attributes |
| <visual-global>` | | | | <visual-global>` | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`orthographic<visual-global-orthographic>` | :ref:`fovy<visual-global-fovy>` | :ref:`ipd<visual-global-ipd>` | :ref:`azimuth<visual-global-azimuth>` | | | | | | :ref:`cameraid<visual-global-cameraid>` | :ref:`orthographic<visual-global-orthographic>` | :ref:`fovy<visual-global-fovy>` | :ref:`ipd<visual-global-ipd>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`elevation<visual-global-elevation>` | :ref:`linewidth<visual-global-linewidth>` | :ref:`glow<visual-global-glow>` | :ref:`offwidth<visual-global-offwidth>` | | | | | | :ref:`azimuth<visual-global-azimuth>` | :ref:`elevation<visual-global-elevation>` | :ref:`linewidth<visual-global-linewidth>` | :ref:`glow<visual-global-glow>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`offheight<visual-global-offheight>` | :ref:`realtime<visual-global-realtime>` | :ref:`ellipsoidinertia<visual-global-ellipsoidinertia>` | :ref:`bvactive<visual-global-bvactive>` | | | | | | :ref:`offwidth<visual-global-offwidth>` | :ref:`offheight<visual-global-offheight>` | :ref:`realtime<visual-global-realtime>` | :ref:`ellipsoidinertia<visual-global-ellipsoidinertia>` | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
| | | | :ref:`bvactive<visual-global-bvactive>` | | | | |
| | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | | | | +-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ |
+------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------+----+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| |_| visual |br| |_| |L| | | .. table:: | | |_| visual |br| |_| |L| | | .. table:: |
+5
View File
@@ -12,6 +12,11 @@ Upcoming version (not yet released)
`:ref:mjs_detach` was added in order to remove an element from the spec without deleting it. `:ref:mjs_detach` was added in order to remove an element from the spec without deleting it.
- The Python functions ``element.delete`` have been replaced by ``spec.delete(element)``. - The Python functions ``element.delete`` have been replaced by ``spec.delete(element)``.
General
^^^^^^^
- Added support for setting the initial camera in the viewer using
:ref:`visual/global/cameraid<visual-global-cameraid>`.
Bug fixes Bug fixes
^^^^^^^^^ ^^^^^^^^^
- Inverse dynamics were not being computed correctly when :ref:`tendon armature<tendon-spatial-armature>` was present, - Inverse dynamics were not being computed correctly when :ref:`tendon armature<tendon-spatial-armature>` was present,
+1
View File
@@ -844,6 +844,7 @@ struct mjOption_ { // physics options
typedef struct mjOption_ mjOption; typedef struct mjOption_ mjOption;
struct mjVisual_ { // visualization options struct mjVisual_ { // visualization options
struct { // global parameters struct { // global parameters
int cameraid; // initial camera id (-1: free)
int orthographic; // is the free camera orthographic (0: no, 1: yes) int orthographic; // is the free camera orthographic (0: no, 1: yes)
float fovy; // y field-of-view of free camera (orthographic ? length : degree) float fovy; // y field-of-view of free camera (orthographic ? length : degree)
float ipd; // inter-pupilary distance for free camera float ipd; // inter-pupilary distance for free camera
+1
View File
@@ -508,6 +508,7 @@ typedef struct mjOption_ mjOption;
struct mjVisual_ { // visualization options struct mjVisual_ { // visualization options
struct { // global parameters struct { // global parameters
int cameraid; // initial camera id (-1: free)
int orthographic; // is the free camera orthographic (0: no, 1: yes) int orthographic; // is the free camera orthographic (0: no, 1: yes)
float fovy; // y field-of-view of free camera (orthographic ? length : degree) float fovy; // y field-of-view of free camera (orthographic ? length : degree)
float ipd; // inter-pupilary distance for free camera float ipd; // inter-pupilary distance for free camera
+5
View File
@@ -278,6 +278,11 @@ STRUCTS: Mapping[str, StructDecl] = dict([
name='global', name='global',
type=AnonymousStructDecl( type=AnonymousStructDecl(
fields=( fields=(
StructFieldDecl(
name='cameraid',
type=ValueType(name='int'),
doc='initial camera id (-1: free)',
),
StructFieldDecl( StructFieldDecl(
name='orthographic', name='orthographic',
type=ValueType(name='int'), type=ValueType(name='int'),
+1
View File
@@ -175,6 +175,7 @@ PYBIND11_MODULE(_structs, m) {
}); });
DefineStructFunctions(mjVisualGlobal); DefineStructFunctions(mjVisualGlobal);
#define X(var) mjVisualGlobal.def_readwrite(#var, &raw::MjVisualGlobal::var) #define X(var) mjVisualGlobal.def_readwrite(#var, &raw::MjVisualGlobal::var)
X(cameraid);
X(orthographic); X(orthographic);
X(fovy); X(fovy);
X(ipd); X(ipd);
+1 -1
View File
@@ -353,7 +353,7 @@ void PhysicsLoop(mj::Simulate& sim) {
// requested slow-down factor // requested slow-down factor
double slowdown = 100 / sim.percentRealTime[sim.real_time_index]; double slowdown = 100 / sim.percentRealTime[sim.real_time_index];
// misalignment condition: distance from target sim time is bigger than syncmisalign // misalignment condition: distance from target sim time is bigger than syncMisalign
bool misaligned = bool misaligned =
std::abs(Seconds(elapsedCPU).count()/slowdown - elapsedSim) > syncMisalign; std::abs(Seconds(elapsedCPU).count()/slowdown - elapsedSim) > syncMisalign;
+9 -1
View File
@@ -1178,9 +1178,17 @@ void MakeUiSections(mj::Simulate* sim, const mjModel* m, const mjData* d) {
// align and scale view // align and scale view
void AlignAndScaleView(mj::Simulate* sim, const mjModel* m) { void AlignAndScaleView(mj::Simulate* sim, const mjModel* m) {
// use default free camera parameters // if the id is valid, use the initial fixed camera
if (m->vis.global.cameraid >= 0 && m->vis.global.cameraid < m->ncam) {
sim->cam.fixedcamid = m->vis.global.cameraid;
sim->cam.type = mjCAMERA_FIXED;
}
// otherwise use default free camera
else {
mjv_defaultFreeCamera(m, &sim->cam); mjv_defaultFreeCamera(m, &sim->cam);
} }
}
// copy state to clipboard as key // copy state to clipboard as key
+1
View File
@@ -183,6 +183,7 @@ static void setf4(float* rgba, float r, float g, float b, float a) {
// set visual options to default values // set visual options to default values
void mj_defaultVisual(mjVisual* vis) { void mj_defaultVisual(mjVisual* vis) {
// global // global
vis->global.cameraid = -1;
vis->global.orthographic = 0; vis->global.orthographic = 0;
vis->global.fovy = 45; vis->global.fovy = 45;
vis->global.ipd = 0.068; vis->global.ipd = 0.068;
+4 -2
View File
@@ -127,8 +127,9 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"visual", "*", "0"}, {"visual", "*", "0"},
{"<"}, {"<"},
{"global", "?", "12", "orthographic", "fovy", "ipd", "azimuth", "elevation", "linewidth", {"global", "?", "13", "cameraid", "orthographic", "fovy", "ipd", "azimuth", "elevation",
"glow", "offwidth", "offheight", "realtime", "ellipsoidinertia", "bvactive"}, "linewidth", "glow", "offwidth", "offheight", "realtime", "ellipsoidinertia",
"bvactive"},
{"quality", "?", "5", "shadowsize", "offsamples", "numslices", "numstacks", {"quality", "?", "5", "shadowsize", "offsamples", "numslices", "numstacks",
"numquads"}, "numquads"},
{"headlight", "?", "4", "ambient", "diffuse", "specular", "active"}, {"headlight", "?", "4", "ambient", "diffuse", "specular", "active"},
@@ -2998,6 +2999,7 @@ void mjXReader::Visual(XMLElement* section) {
// global sub-element // global sub-element
if (name == "global") { if (name == "global") {
ReadAttrInt(elem, "cameraid", &vis->global.cameraid);
if (MapValue(elem, "orthographic", &n, bool_map, 2)) { if (MapValue(elem, "orthographic", &n, bool_map, 2)) {
vis->global.orthographic = (n == 1); vis->global.orthographic = (n == 1);
} }
+1
View File
@@ -1130,6 +1130,7 @@ void mjXWriter::Visual(XMLElement* root) {
// global // global
elem = InsertEnd(section, "global"); elem = InsertEnd(section, "global");
WriteAttrInt(elem, "cameraid", vis->global.cameraid, visdef.global.cameraid);
WriteAttrKey(elem, "orthographic", WriteAttrKey(elem, "orthographic",
bool_map, 2, vis->global.orthographic, visdef.global.orthographic); bool_map, 2, vis->global.orthographic, visdef.global.orthographic);
WriteAttr(elem, "fovy", 1, &vis->global.fovy, &visdef.global.fovy); WriteAttr(elem, "fovy", 1, &vis->global.fovy, &visdef.global.fovy);
+1
View File
@@ -5114,6 +5114,7 @@ public unsafe struct mjOption_ {
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public unsafe struct global { public unsafe struct global {
public int cameraid;
public int orthographic; public int orthographic;
public float fovy; public float fovy;
public float ipd; public float ipd;