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
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:
@@ -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
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:
+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)
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:
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
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:
:at:`orthographic`: :at-val:`[false, true], "false"`
+5 -3
View File
@@ -1298,11 +1298,13 @@
| :ref:`global | ? | :class: mjcf-attributes |
| <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:: |
+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.
- 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
^^^^^^^^^
- Inverse dynamics were not being computed correctly when :ref:`tendon armature<tendon-spatial-armature>` was present,
+4 -3
View File
@@ -795,8 +795,8 @@ struct mjLROpt_ { // options for mj_setLengthRange()
mjtNum tolrange; // convergence tolerance (relative to range)
};
typedef struct mjLROpt_ mjLROpt;
struct mjVFS_ { // virtual file system for loading from memory
void* impl_; // internal pointer to VFS memory
struct mjVFS_ { // virtual file system for loading from memory
void* impl_; // internal pointer to VFS memory
};
typedef struct mjVFS_ mjVFS;
struct mjOption_ { // physics options
@@ -844,7 +844,8 @@ struct mjOption_ { // physics options
typedef struct mjOption_ mjOption;
struct mjVisual_ { // visualization options
struct { // global parameters
int orthographic; // is the free camera orthographic (0: no, 1: yes)
int cameraid; // initial camera id (-1: free)
int orthographic; // is the free camera orthographic (0: no, 1: yes)
float fovy; // y field-of-view of free camera (orthographic ? length : degree)
float ipd; // inter-pupilary distance for free camera
float azimuth; // initial azimuth of free camera (degrees)
+4 -3
View File
@@ -452,8 +452,8 @@ typedef struct mjLROpt_ mjLROpt;
//---------------------------------- mjVFS ---------------------------------------------------------
struct mjVFS_ { // virtual file system for loading from memory
void* impl_; // internal pointer to VFS memory
struct mjVFS_ { // virtual file system for loading from memory
void* impl_; // internal pointer to VFS memory
};
typedef struct mjVFS_ mjVFS;
@@ -508,7 +508,8 @@ typedef struct mjOption_ mjOption;
struct mjVisual_ { // visualization options
struct { // global parameters
int orthographic; // is the free camera orthographic (0: no, 1: yes)
int cameraid; // initial camera id (-1: free)
int orthographic; // is the free camera orthographic (0: no, 1: yes)
float fovy; // y field-of-view of free camera (orthographic ? length : degree)
float ipd; // inter-pupilary distance for free camera
float azimuth; // initial azimuth of free camera (degrees)
+5
View File
@@ -278,6 +278,11 @@ STRUCTS: Mapping[str, StructDecl] = dict([
name='global',
type=AnonymousStructDecl(
fields=(
StructFieldDecl(
name='cameraid',
type=ValueType(name='int'),
doc='initial camera id (-1: free)',
),
StructFieldDecl(
name='orthographic',
type=ValueType(name='int'),
+1
View File
@@ -175,6 +175,7 @@ PYBIND11_MODULE(_structs, m) {
});
DefineStructFunctions(mjVisualGlobal);
#define X(var) mjVisualGlobal.def_readwrite(#var, &raw::MjVisualGlobal::var)
X(cameraid);
X(orthographic);
X(fovy);
X(ipd);
+1 -1
View File
@@ -353,7 +353,7 @@ void PhysicsLoop(mj::Simulate& sim) {
// requested slow-down factor
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 =
std::abs(Seconds(elapsedCPU).count()/slowdown - elapsedSim) > syncMisalign;
+10 -2
View File
@@ -1178,8 +1178,16 @@ void MakeUiSections(mj::Simulate* sim, const mjModel* m, const mjData* d) {
// align and scale view
void AlignAndScaleView(mj::Simulate* sim, const mjModel* m) {
// use default free camera parameters
mjv_defaultFreeCamera(m, &sim->cam);
// 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);
}
}
+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
void mj_defaultVisual(mjVisual* vis) {
// global
vis->global.cameraid = -1;
vis->global.orthographic = 0;
vis->global.fovy = 45;
vis->global.ipd = 0.068;
+4 -2
View File
@@ -127,8 +127,9 @@ const char* MJCF[nMJCF][mjXATTRNUM] = {
{"visual", "*", "0"},
{"<"},
{"global", "?", "12", "orthographic", "fovy", "ipd", "azimuth", "elevation", "linewidth",
"glow", "offwidth", "offheight", "realtime", "ellipsoidinertia", "bvactive"},
{"global", "?", "13", "cameraid", "orthographic", "fovy", "ipd", "azimuth", "elevation",
"linewidth", "glow", "offwidth", "offheight", "realtime", "ellipsoidinertia",
"bvactive"},
{"quality", "?", "5", "shadowsize", "offsamples", "numslices", "numstacks",
"numquads"},
{"headlight", "?", "4", "ambient", "diffuse", "specular", "active"},
@@ -2998,6 +2999,7 @@ void mjXReader::Visual(XMLElement* section) {
// global sub-element
if (name == "global") {
ReadAttrInt(elem, "cameraid", &vis->global.cameraid);
if (MapValue(elem, "orthographic", &n, bool_map, 2)) {
vis->global.orthographic = (n == 1);
}
+1
View File
@@ -1130,6 +1130,7 @@ void mjXWriter::Visual(XMLElement* root) {
// global
elem = InsertEnd(section, "global");
WriteAttrInt(elem, "cameraid", vis->global.cameraid, visdef.global.cameraid);
WriteAttrKey(elem, "orthographic",
bool_map, 2, vis->global.orthographic, visdef.global.orthographic);
WriteAttr(elem, "fovy", 1, &vis->global.fovy, &visdef.global.fovy);
+1
View File
@@ -5114,6 +5114,7 @@ public unsafe struct mjOption_ {
[StructLayout(LayoutKind.Sequential)]
public unsafe struct global {
public int cameraid;
public int orthographic;
public float fovy;
public float ipd;