Files
Mujoco_WASM/src/user/user_objects.h
T
Sam Haves 924ee3070a Modify user values in mujoco to allow users to provide cleanup functions to avoid memory leaks.
For the MJCF -> USD plugin, and I suspect other usecases for user values, it's necessary to give ownership of the object to Mujoco. However since they get type erased, we can't clean up the data automatically for the user. Instead this allows c++ clients to provide a cleanup function with their data.

PiperOrigin-RevId: 756832010
Change-Id: I80b8e7822e1a0e399a0d19dcaa57ee69b3ccc16a
2025-05-09 11:03:06 -07:00

1964 lines
62 KiB
C++

// Copyright 2021 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.
#ifndef MUJOCO_SRC_USER_USER_OBJECTS_H_
#define MUJOCO_SRC_USER_USER_OBJECTS_H_
#include <stdbool.h>
#include <algorithm>
#include <cstddef>
#include <array>
#include <functional>
#include <map>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>
#include <mujoco/mjmodel.h>
#include <mujoco/mjplugin.h>
#include <mujoco/mjspec.h>
#include <mujoco/mjtnum.h>
#include "user/user_cache.h"
#include "user/user_util.h"
#include <tiny_obj_loader.h>
using face_vertices_type =
decltype(tinyobj::mesh_t::num_face_vertices)::value_type;
// forward declarations of all mjC/X classes
class mjCError;
class mjCBase;
class mjCBody;
class mjCFrame;
class mjCJoint;
class mjCGeom;
class mjCSite;
class mjCCamera;
class mjCLight;
class mjCHField;
class mjCFlex; // defined in user_mesh.h
class mjCMesh; // defined in user_mesh.h
class mjCSkin; // defined in user_mesh.h
class mjCTexture;
class mjCMaterial;
class mjCPair;
class mjCBodyPair;
class mjCEquality;
class mjCTendon;
class mjCWrap;
class mjCActuator;
class mjCSensor;
class mjCNumeric;
class mjCText;
class mjCTuple;
class mjCDef;
class mjCModel; // defined in user_model.h
class mjXWriter; // defined in xml_native.h
class mjXURDF; // defined in xml_urdf.h
//------------------------- helper constants, classes and functions --------------------------------
// number of positive size parameters for each geom type
const int mjGEOMINFO[mjNGEOMTYPES] = {3, 0, 1, 2, 3, 2, 3, 0};
// error information
class [[nodiscard]] mjCError {
public:
mjCError(const mjCBase* obj = 0,
const char* msg = 0,
const char* str = 0,
int pos1 = 0,
int pos2 = 0);
char message[500]; // error message
bool warning; // is this a warning instead of error
};
// alternative specifications of frame orientation
const char* ResolveOrientation(double* quat, // set frame quat
bool degree, // angle format: degree/radian
const char* sequence, // euler sequence format: "xyz"
const mjsOrientation& orient);
//------------------------- class mjCBoundingVolumeHierarchy ---------------------------------------
// bounding volume
class mjCBoundingVolume {
public:
mjCBoundingVolume(int id, int contype, int conaffinity, const double pos[3],
const double quat[4], const double aabb[6]) : contype_(contype),
conaffinity_(conaffinity), idval_(id) {
std::copy(pos, pos + 3, pos_.begin());
std::copy(aabb, aabb + 6, aabb_.begin());
quat_set_ = quat != nullptr;
if (quat_set_) {
std::copy(quat, quat + 4, quat_.begin());
}
}
mjCBoundingVolume(const int* id, int contype, int conaffinity, const double pos[3],
const double quat[4], const double aabb[6]) : contype_(contype),
conaffinity_(conaffinity), id_(id) {
std::copy(pos, pos + 3, pos_.begin());
std::copy(aabb, aabb + 6, aabb_.begin());
quat_set_ = quat != nullptr;
if (quat_set_) {
std::copy(quat, quat + 4, quat_.begin());
}
}
int Contype() const { return contype_; }
int Conaffinity() const { return conaffinity_; }
const double* AABB() const { return aabb_.data(); }
double AABB(int i) const { return aabb_[i]; }
const double* Pos() const { return pos_.data(); }
double Pos(int i) const { return pos_[i]; }
const double* Quat() const { return quat_set_ ? quat_.data() : nullptr; }
const int* Id() const { return id_ ? id_ : &idval_; }
void SetContype(int val) { contype_ = val; }
void SetConaffinity(int val) { conaffinity_ = val; }
void SetAABB(const double* aabb) { std::copy(aabb, aabb + 6, aabb_.begin()); }
void SetPos(const double* pos) { std::copy(pos, pos + 3, pos_.begin()); }
void SetQuat(const double* quat) {
quat_set_ = true;
std::copy(quat, quat + 4, quat_.begin());
}
void SetId(const int* id) { id_ = id; }
void SetId(int val) { idval_ = val; }
private:
int contype_; // contact type
int conaffinity_; // contact affinity
std::array<double, 6> aabb_; // axis-aligned bounding box (center, size)
std::array<double, 3> pos_; // position (set by user or Compiler)
std::array<double, 4> quat_; // orientation (set by user or Compiler)
bool quat_set_; // boolean flag is quat_ has been set
int idval_; // local id copy for nodes not storing their id's (e.g. faces)
// pointer to object id
const int* id_ = nullptr;
};
// bounding volume hierarchy
struct mjCBoundingVolumeHierarchy_ {
protected:
int nbvh_ = 0;
std::vector<mjtNum> bvh_; // bounding boxes (nbvh x 6)
std::vector<int> child_; // children of each node (nbvh x 2)
std::vector<int> nodeid_; // id of elem contained by the node (nbvh x 1)
std::vector<int*> nodeidptr_; // ptr to id of elem contained by the node (nbvh x 1)
std::vector<int> level_; // levels of each node (nbvh x 1)
std::vector<mjCBoundingVolume> bvleaf_;
std::string name_;
double ipos_[3] = {0, 0, 0};
double iquat_[4] = {1, 0, 0, 0};
};
class mjCBoundingVolumeHierarchy : public mjCBoundingVolumeHierarchy_ {
public:
// make bounding volume hierarchy
void CreateBVH();
void Set(double ipos_element[3], double iquat_element[4]);
void AllocateBoundingVolumes(int nleaf);
void RemoveInactiveVolumes(int nmax);
const mjCBoundingVolume*
AddBoundingVolume(int id, int contype, int conaffinity, const double pos[3],
const double quat[4], const double aabb[6]);
const mjCBoundingVolume*
AddBoundingVolume(const int* id, int contype, int conaffinity, const double pos[3],
const double quat[4], const double aabb[6]);
// public accessors
int Nbvh() const { return nbvh_; }
const std::vector<mjtNum>& Bvh() const { return bvh_; }
const std::vector<int>& Child() const { return child_; }
const std::vector<int>& Nodeid() const { return nodeid_; }
int Nodeid(int id) const { return nodeid_[id]; }
const int* Nodeidptr(int id) const { return nodeidptr_[id]; }
const std::vector<int>& Level() const { return level_; }
int Size() const {
return sizeof(mjCBoundingVolume) * bvleaf_.size()
+ sizeof(mjtNum) * bvh_.size() + sizeof(int) * child_.size()
+ sizeof(int) * nodeid_.size() + sizeof(int) * level_.size();
}
private:
// internal class used during BVH construction, for partial sorting of bounding volumes
struct BVElement {
const mjCBoundingVolume* e;
// position of the element in the BVH axes
double lpos[3];
};
int MakeBVH(std::vector<BVElement>::iterator elements_begin,
std::vector<BVElement>::iterator elements_end, int lev = 0);
};
//------------------------- class mjCBase ----------------------------------------------------------
// Generic functionality for all derived classes
class mjCBase_ : public mjsElement {
public:
int id; // object id
std::string name; // object name
std::string classname; // defaults class name
std::string info; // error message info set by the user
std::string prefix; // prefix for model operations
std::string suffix; // suffix for model operations
};
class mjCBase : public mjCBase_ {
friend class mjCDef;
public:
// load resource if found (fallback to OS filesystem)
static mjResource* LoadResource(const std::string& modelfiledir,
const std::string& filename, const mjVFS* vfs);
// Get and sanitize content type from raw_text if not empty, otherwise parse
// content type from resource_name; throw on failure
static std::string GetAssetContentType(std::string_view resource_name, std::string_view raw_text);
// Add frame transformation
void SetFrame(mjCFrame* _frame);
// Copy spec into private attributes
virtual void CopyFromSpec() {}
// Throws an error if any of the references is missing
virtual void ResolveReferences(const mjCModel* m) {}
// Appends prefix and suffix to reference
virtual void NameSpace(const mjCModel* m);
// Copy plugins instantiated in this object
virtual void CopyPlugin() {}
// Returns parent of this object
virtual mjCBase* GetParent() const { return nullptr; }
// Copy assignment
mjCBase& operator=(const mjCBase& other);
mjCFrame* frame; // pointer to frame transformation
mjCModel* model; // pointer to model that owns object
mjsCompiler* compiler; // pointer to the compiler options
virtual ~mjCBase() = default; // destructor
// reset keyframe references for allowing self-attach
virtual void ForgetKeyframes() {}
virtual void ForgetKeyframes() const {}
// increment and decrement reference count
// release uses the argument to delete the plugin
// which may be still owned by the source spec during shallow attach
virtual void AddRef() { ++refcount; }
virtual int GetRef() { return refcount; }
virtual void Release() {
if (--refcount == 0) {
delete this;
}
}
// Set and get user payload
void SetUserValue(std::string_view key, const void* data,
void (*cleanup)(const void*));
const void* GetUserValue(std::string_view key);
void DeleteUserValue(std::string_view key);
protected:
mjCBase(); // constructor
mjCBase(const mjCBase& other); // copy constructor
// reference count for allowing deleting an attached object
int refcount = 1;
// Arbitrary user value that cleans up the data when destroyed.
struct UserValue {
const void* value = nullptr;
void (*cleanup)(const void*) = nullptr;
UserValue() {}
UserValue(const void* value, void (*cleanup)(const void*))
: value(value), cleanup(cleanup) {}
UserValue(const UserValue& other) = delete;
UserValue& operator=(const UserValue& other) = delete;
UserValue(UserValue&& other) : value(other.value), cleanup(other.cleanup) {
other.value = nullptr;
other.cleanup = nullptr;
}
UserValue& operator=(UserValue&& other) {
if (this != &other) {
if (cleanup && value) {
cleanup(value);
}
value = other.value;
cleanup = other.cleanup;
other.value = nullptr;
other.cleanup = nullptr;
}
return *this;
}
~UserValue() {
if (cleanup && value) {
cleanup(value);
}
}
};
// user payload
std::unordered_map<std::string, UserValue> user_payload_;
};
//------------------------- class mjCBody -----------------------------------------------
// Describes a rigid body
class mjCBody_ : public mjCBase {
protected:
mjCBody* parent;
// variables computed by 'Compile' and 'AddXXX'
int weldid; // top index of body we are welded to
int dofnum; // number of motion dofs for body
int mocapid; // mocap id, -1: not mocap
int contype; // OR over geom contypes
int conaffinity; // OR over geom conaffinities
double margin; // MAX over geom margins
double xpos0[3]; // global position in qpos0
double xquat0[4]; // global orientation in qpos0
// used internally by compiler
int lastdof; // id of last dof
int subtreedofs; // number of dofs in subtree, including self
mjCBoundingVolumeHierarchy tree; // bounding volume hierarchy
// variable-size data
std::string plugin_name;
std::string plugin_instance_name;
std::vector<double> userdata_;
std::vector<double> spec_userdata_;
// variables used for temporarily storing the state of the mocap bodies
std::map<std::string, std::array<mjtNum, 3>> mpos_; // saved mocap_pos
std::map<std::string, std::array<mjtNum, 4>> mquat_; // saved mocap_quat
};
class mjCBody : public mjCBody_, private mjsBody {
friend class mjCJoint;
friend class mjCGeom;
friend class mjCSite;
friend class mjCCamera;
friend class mjCComposite;
friend class mjCFrame;
friend class mjCLight;
friend class mjCFlex;
friend class mjCFlexcomp;
friend class mjCEquality;
friend class mjCPair;
friend class mjCModel;
friend class mjXReader;
friend class mjXWriter;
friend class mjXURDF;
public:
mjCBody(mjCModel*); // constructor
~mjCBody(); // destructor
// API for adding objects to body
mjCBody* AddBody(mjCDef* = 0);
mjCFrame* AddFrame(mjCFrame* = 0);
mjCJoint* AddJoint(mjCDef* = 0);
mjCJoint* AddFreeJoint();
mjCGeom* AddGeom(mjCDef* = 0);
mjCSite* AddSite(mjCDef* = 0);
mjCCamera* AddCamera(mjCDef* = 0);
mjCLight* AddLight(mjCDef* = 0);
// API for adding/removing objects to body
mjCBody& operator+=(const mjCBody& other);
mjCBody& operator+=(const mjCFrame& other);
mjCBody& operator-=(const mjCBody& subtree);
// API for accessing objects
int NumObjects(mjtObj type);
mjCBase* GetObject(mjtObj type, int id);
mjCBase* FindObject(mjtObj type, std::string name, bool recursive = true);
// Propagate suffix and prefix to the whole tree
void NameSpace(const mjCModel* m);
// set explicitinertial to true
void MakeInertialExplicit();
// compute the bounding volume hierarchy of the body.
void ComputeBVH();
// variables set by user
mjsBody spec;
// inherited
using mjCBase::name;
using mjCBase::info;
// used by mjXWriter and mjCModel
const std::vector<double>& get_userdata() { return userdata_; }
// get next child of given type recursively; if `child` is found while traversing the tree,
// then `found` is set to true and the next element encountered is returned;
// returns nullptr if the next child is not found or if `child` is the last element, returns
// the next child after the input `child` otherwise
mjsElement* NextChild(const mjsElement* child, mjtObj type = mjOBJ_UNKNOWN,
bool recursive = false, bool* found = nullptr);
// reset keyframe references for allowing self-attach
void ForgetKeyframes() const;
// create a frame and move all contents of this body into it
mjCFrame* ToFrame();
// get mocap position and quaternion
mjtNum* mpos(const std::string& state_name);
mjtNum* mquat(const std::string& state_name);
mjsFrame* last_attached; // last attached frame to this body
// set parent of this body
void SetParent(mjCBody* _body) { parent = _body; }
mjCBody* GetParent() const { return parent; }
// set model of this body
void SetModel(mjCModel* _model);
// reset ids of all objects in this body
void ResetId();
// getters
std::vector<mjCBody*> Bodies() const { return bodies; }
private:
mjCBody(const mjCBody& other, mjCModel* _model); // copy constructor
mjCBody& operator=(const mjCBody& other); // copy assignment
void Compile(void); // compiler
void InertiaFromGeom(void); // get inertial info from geoms
// objects allocated by Add functions
std::vector<mjCBody*> bodies; // child bodies
std::vector<mjCGeom*> geoms; // geoms attached to this body
std::vector<mjCFrame*> frames; // frames attached to this body
std::vector<mjCJoint*> joints; // joints allowing motion relative to parent
std::vector<mjCSite*> sites; // sites attached to this body
std::vector<mjCCamera*> cameras; // cameras attached to this body
std::vector<mjCLight*> lights; // lights attached to this body
void CopyFromSpec(); // copy spec into attributes
void PointToLocal(void);
void NameSpace_(const mjCModel* m, bool propagate = true);
void CopyPlugin();
// copy src list of elements into dst; set body, model and frame
template <typename T>
void CopyList(std::vector<T*>& dst, const std::vector<T*>& src,
std::map<mjCFrame*, int>& fmap, const mjCFrame* pframe = nullptr);
// gets next child of the same type in this body
template <class T>
mjsElement* GetNext(const std::vector<T*>& list, const mjsElement* child, bool* found);
};
//------------------------- class mjCFrame ---------------------------------------------------------
// Describes a coordinate transformation relative to its parent
class mjCFrame_ : public mjCBase {
protected:
bool compiled; // frame already compiled
};
class mjCFrame : public mjCFrame_, private mjsFrame {
friend class mjCBase;
friend class mjCBody;
friend class mjCGeom;
friend class mjCJoint;
friend class mjCSite;
friend class mjCCamera;
friend class mjCLight;
friend class mjCModel;
public:
mjCFrame(mjCModel* = 0, mjCFrame* = 0);
mjCFrame(const mjCFrame& other);
mjCFrame& operator=(const mjCFrame& other);
mjsFrame spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec(void);
void PointToLocal(void);
void SetParent(mjCBody* _body) { body = _body; }
mjCBody* GetParent() const { return body; }
mjCFrame& operator+=(const mjCBody& other);
bool IsAncestor(const mjCFrame* child) const; // true if child is contained in this frame
mjsBody* last_attached; // last attached body to this frame
private:
void Compile(void); // compiler
mjCBody* body; // body that owns the frame
};
//------------------------- class mjCJoint ---------------------------------------------------------
// Describes a motion degree of freedom of a body relative to its parent
class mjCJoint_ : public mjCBase {
protected:
mjCBody* body; // joint's body
// variable used for temporarily storing the state of the joint
std::map<std::string, std::array<mjtNum, 7>> qpos_; // qpos at the previous step
std::map<std::string, std::array<mjtNum, 6>> qvel_; // qvel at the previous step
// variable-size data
std::vector<double> userdata_;
std::vector<double> spec_userdata_;
};
class mjCJoint : public mjCJoint_, private mjsJoint {
friend class mjCDef;
friend class mjCEquality;
friend class mjCBody;
friend class mjCModel;
friend class mjCSensor;
friend class mjXWriter;
friend class mjXURDF;
public:
mjCJoint(mjCModel* = nullptr, mjCDef* = nullptr);
mjCJoint(const mjCJoint& other);
mjCJoint& operator=(const mjCJoint& other);
mjsJoint spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec(void);
void SetParent(mjCBody* _body) { body = _body; }
mjCBody* GetParent() const { return body; }
// used by mjXWriter and mjCModel
const std::vector<double>& get_userdata() const { return userdata_; }
const double* get_range() const { return range; }
bool is_limited() const;
bool is_actfrclimited() const;
static int nq(mjtJoint joint_type);
static int nv(mjtJoint joint_type);
int nq() const { return nq(spec.type); }
int nv() const { return nv(spec.type); }
mjtNum* qpos(const std::string& state_name);
mjtNum* qvel(const std::string& state_name);
private:
int Compile(void); // compiler; return dofnum
void PointToLocal(void);
// variables that should not be copied during copy assignment
int qposadr_; // address of dof in data->qpos
int dofadr_; // address of dof in data->qvel
};
//------------------------- class mjCGeom ----------------------------------------------------------
// Describes a geometric shape belonging to a body
class mjCGeom_ : public mjCBase {
public:
bool inferinertia; // true if inertia should be computed from geom
protected:
bool visual_; // true: geom does not collide and is unreferenced
int matid; // id of geom's material
mjCMesh* mesh; // geom's mesh
mjCHField* hfield; // geom's hfield
double mass_; // mass
double inertia[3]; // local diagonal inertia
double aabb[6]; // axis-aligned bounding box (center, size)
mjCBody* body; // geom's body
mjtNum fluid[mjNFLUID]; // compile-time fluid-interaction parameters
// variable-size data
std::string plugin_name;
std::string plugin_instance_name;
std::string hfieldname_;
std::string meshname_;
std::string material_;
std::vector<double> userdata_;
std::string spec_hfieldname_;
std::string spec_meshname_;
std::string spec_material_;
std::vector<double> spec_userdata_;
};
class mjCGeom : public mjCGeom_, private mjsGeom {
friend class mjCDef;
friend class mjCMesh;
friend class mjCPair;
friend class mjCBody;
friend class mjCModel;
friend class mjCWrap;
friend class mjXWriter;
friend class mjXURDF;
public:
mjCGeom(mjCModel* = nullptr, mjCDef* = nullptr);
mjCGeom(const mjCGeom& other);
mjCGeom& operator=(const mjCGeom& other);
using mjCBase::name;
mjsGeom spec; // variables set by user
double GetVolume() const; // compute geom volume
void SetInertia(void); // compute and set geom inertia
bool IsVisual(void) const { return visual_; }
void SetNotVisual(void) { visual_ = false; }
void SetParent(mjCBody* _body) { body = _body; }
mjCBody* GetParent() const { return body; }
mjtGeom Type() const { return type; }
// Compute all coefs modeling the interaction with the surrounding fluid.
void SetFluidCoefs(void);
// Compute the kappa coefs of the added inertia due to the surrounding fluid.
double GetAddedMassKappa(double dx, double dy, double dz);
// used by mjXWriter and mjCModel
const std::vector<double>& get_userdata() const { return userdata_; }
const std::string& get_hfieldname() const { return spec_hfieldname_; }
const std::string& get_meshname() const { return spec_meshname_; }
const std::string& get_material() const { return spec_material_; }
void del_material() { spec_material_.clear(); }
private:
void Compile(void); // compiler
double GetRBound(void); // compute bounding sphere radius
void ComputeAABB(void); // compute axis-aligned bounding box
void CopyFromSpec(void);
void PointToLocal(void);
void NameSpace(const mjCModel* m);
void CopyPlugin();
// inherited
using mjCBase::info;
};
//------------------------- class mjCSite ----------------------------------------------------------
// Describes a site on a body
class mjCSite_ : public mjCBase {
protected:
// variable-size data
std::string material_;
std::vector<double> userdata_;
std::string spec_material_;
std::vector<double> spec_userdata_;
// variables computed by 'compile' and 'mjCBody::addSite'
mjCBody* body; // site's body
int matid; // material id for rendering
};
class mjCSite : public mjCSite_, private mjsSite {
friend class mjCDef;
friend class mjCBody;
friend class mjCModel;
friend class mjXWriter;
friend class mjXURDF;
public:
mjCSite(mjCModel* = nullptr, mjCDef* = nullptr);
mjCSite(const mjCSite& other);
mjCSite& operator=(const mjCSite& other);
mjsSite spec; // variables set by user
// site's body
mjCBody* Body() const { return body; }
void SetParent(mjCBody* _body) { body = _body; }
mjCBody* GetParent() const { return body; }
// use strings from mjCBase rather than mjStrings from mjsSite
using mjCBase::name;
using mjCBase::info;
// used by mjXWriter and mjCModel
const std::vector<double>& get_userdata() const { return userdata_; }
const std::string& get_material() const { return material_; }
void del_material() { material_.clear(); }
private:
void Compile(void); // compiler
void CopyFromSpec(); // copy spec into attributes
void PointToLocal(void);
void NameSpace(const mjCModel* m);
};
//------------------------- class mjCCamera --------------------------------------------------------
// Describes a camera, attached to a body
class mjCCamera_ : public mjCBase {
protected:
mjCBody* body; // camera's body
int targetbodyid; // id of target body; -1: none
std::string targetbody_;
std::string spec_targetbody_;
std::vector<double> userdata_;
std::vector<double> spec_userdata_;
};
class mjCCamera : public mjCCamera_, private mjsCamera {
friend class mjCDef;
friend class mjCBody;
friend class mjCModel;
friend class mjCSensor;
friend class mjXWriter;
public:
mjCCamera(mjCModel* = nullptr, mjCDef* = nullptr);
mjCCamera(const mjCCamera& other);
mjCCamera& operator=(const mjCCamera& other);
mjsCamera spec;
using mjCBase::name;
using mjCBase::info;
// used by mjXWriter and mjCModel
const std::string& get_targetbody() const { return targetbody_; }
const std::vector<double>& get_userdata() const { return userdata_; }
void SetParent(mjCBody* _body) { body = _body; }
mjCBody* GetParent() const { return body; }
private:
void Compile(void); // compiler
void CopyFromSpec(void);
void PointToLocal(void);
void NameSpace(const mjCModel* m);
};
//------------------------- class mjCLight ---------------------------------------------------------
// Describes a light, attached to a body
class mjCLight_ : public mjCBase {
protected:
mjCBody* body; // light's body
int targetbodyid; // id of target body; -1: none
std::string targetbody_;
std::string spec_targetbody_;
};
class mjCLight : public mjCLight_, private mjsLight {
friend class mjCDef;
friend class mjCBody;
friend class mjCModel;
friend class mjXWriter;
public:
mjCLight(mjCModel* = nullptr, mjCDef* = nullptr);
mjCLight(const mjCLight& other);
mjCLight& operator=(const mjCLight& other);
mjsLight spec;
using mjCBase::name;
using mjCBase::info;
// used by mjXWriter and mjCModel
const std::string& get_targetbody() const { return targetbody_; }
void SetParent(mjCBody* _body) { body = _body; }
mjCBody* GetParent() const { return body; }
private:
void Compile(void); // compiler
void CopyFromSpec(void);
void PointToLocal(void);
void NameSpace(const mjCModel* m);
};
//------------------------- class mjCFlex ----------------------------------------------------------
// Describes a flex
class mjCFlex_ : public mjCBase {
protected:
int nvert; // number of vertices
int nnode; // number of nodes
int nedge; // number of edges
int nelem; // number of elements
int matid; // material id
bool rigid; // all vertices attached to the same body
bool centered; // all vertices coordinates (0,0,0)
bool interpolated; // vertices are interpolated from nodes
std::vector<int> vertbodyid; // vertex body ids
std::vector<int> nodebodyid; // node body ids
std::vector<std::pair<int, int>> edge; // edge vertex ids
std::vector<int> shell; // shell fragment vertex ids (dim per fragment)
std::vector<int> elemlayer; // element layer (distance from border)
std::vector<int> evpair; // element-vertex pairs
std::vector<double> vertxpos; // global vertex positions
mjCBoundingVolumeHierarchy tree; // bounding volume hierarchy
std::vector<double> elemaabb_; // element bounding volume
std::vector<int> edgeidx_; // element edge ids
std::vector<double> stiffness; // elasticity stiffness matrix
// variable-size data
std::vector<std::string> vertbody_; // vertex body names
std::vector<std::string> nodebody_; // node body names
std::vector<double> vert_; // vertex positions
std::vector<double> node_; // node positions
std::vector<int> elem_; // element vertex ids
std::vector<float> texcoord_; // vertex texture coordinates
std::vector<int> elemtexcoord_; // face texture coordinates (OBJ only)
std::string material_; // name of material used for rendering
std::string spec_material_;
std::vector<std::string> spec_vertbody_;
std::vector<std::string> spec_nodebody_;
std::vector<double> spec_vert_;
std::vector<double> spec_node_;
std::vector<int> spec_elem_;
std::vector<float> spec_texcoord_;
std::vector<int> spec_elemtexcoord_;
};
class mjCFlex: public mjCFlex_, private mjsFlex {
friend class mjCDef;
friend class mjCModel;
friend class mjCFlexcomp;
friend class mjCEquality;
friend class mjXWriter;
public:
mjCFlex(mjCModel* = nullptr);
mjCFlex(const mjCFlex& other);
mjCFlex& operator=(const mjCFlex& other);
mjsFlex spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec(void);
void PointToLocal(void);
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
// used by mjXWriter and mjCModel
const std::string& get_material() const { return material_; }
const std::vector<std::string>& get_vertbody() const { return vertbody_; }
const std::vector<double>& get_vert() const { return vert_; }
const std::vector<double>& get_elemaabb() const { return elemaabb_; }
const std::vector<int>& get_elem() const { return elem_; }
const std::vector<float>& get_texcoord() const { return texcoord_; }
const std::vector<int>& get_elemtexcoord() const { return elemtexcoord_; }
const std::vector<std::string>& get_nodebody() const { return nodebody_; }
bool HasTexcoord() const; // texcoord not null
void DelTexcoord(); // delete texcoord
static constexpr int kNumEdges[3] = {1, 3, 6}; // number of edges per element indexed by dim
private:
void Compile(const mjVFS* vfs); // compiler
void CreateBVH(void); // create flex BVH
void CreateShellPair(void); // create shells and evpairs
std::vector<double> vert0_; // vertex positions in [0, 1]^d in the bounding box
std::vector<double> node0_; // node Cartesian positions
};
//------------------------- class mjCMesh ----------------------------------------------------------
// Describes a mesh
class mjCMesh_ : public mjCBase {
protected:
// variable size attributes
std::string plugin_name;
std::string plugin_instance_name;
std::string content_type_ = ""; // content type of file
std::string file_; // mesh file
mjResource* resource_ = nullptr; // resource for mesh file
std::vector<double> vert_; // vertex data
std::vector<float> normal_; // normal data
std::vector<float> texcoord_; // texcoord data
std::vector<int> face_; // vertex indices
std::vector<int> facenormal_; // normal indices
std::vector<int> facetexcoord_; // texcoord indices
std::string spec_content_type_;
std::string spec_file_;
std::vector<float> spec_vert_;
std::vector<float> spec_normal_;
std::vector<float> spec_texcoord_;
std::vector<int> spec_face_;
std::vector<int> spec_facenormal_;
std::vector<int> spec_facetexcoord_;
// used by the compiler
bool visual_; // true: the mesh is only visual
std::vector< std::pair<int, int> > halfedge_; // half-edge data
// mesh processed flags
bool processed_; // has the mesh been processed yet
bool transformed_; // has the mesh been transformed to CoM and inertial frame
// mesh properties computed by Compile
double pos_[3]; // CoM position
double quat_[4]; // inertia orientation
double boxsz_[3]; // half-sizes of equivalent inertia box
double aamm_[6]; // axis-aligned bounding box in (min, max) format
double volume_; // volume of the mesh
double surface_; // surface of the mesh
// size of mesh data to be copied into mjModel
int szgraph_ = 0; // size of graph data in ints
bool needhull_; // needs convex hull for collisions
int maxhullvert_; // max vertex count of convex hull
mjCBoundingVolumeHierarchy tree_; // bounding volume hierarchy
std::vector<double> face_aabb_; // bounding boxes of all faces
// paths stored during model attachment
mujoco::user::FilePath modelfiledir_;
mujoco::user::FilePath meshdir_;
};
class mjCMesh: public mjCMesh_, private mjsMesh {
friend class mjCModel;
public:
mjCMesh(mjCModel* = nullptr, mjCDef* = nullptr);
mjCMesh(const mjCMesh& other);
mjCMesh& operator=(const mjCMesh& other);
~mjCMesh();
mjsMesh spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec(void);
void PointToLocal(void);
void NameSpace(const mjCModel* m);
// accessors
const mjsPlugin& Plugin() const { return plugin; }
const std::string& ContentType() const { return content_type_; }
const std::string& File() const { return file_; }
const double* Refpos() const { return refpos; }
const double* Refquat() const { return refquat; }
const double* Scale() const { return scale; }
bool SmoothNormal() const { return smoothnormal; }
const std::vector<double>& Vert() const { return vert_; }
double Vert(int i) const { return vert_[i]; }
const std::vector<float>& UserVert() const { return spec_vert_; }
const std::vector<float>& UserNormal() const { return spec_normal_; }
const std::vector<float>& Texcoord() const { return texcoord_; }
const std::vector<int>& FaceTexcoord() const { return facetexcoord_; }
const std::vector<float>& UserTexcoord() const { return spec_texcoord_; }
const std::vector<int>& Face() const { return face_; }
const std::vector<int>& UserFace() const { return spec_face_; }
mjtMeshInertia Inertia() const { return spec.inertia; }
// setters
void SetNeedHull(bool needhull) { needhull_ = needhull; }
// mesh properties computed by Compile
const double* aamm() const { return aamm_; }
// number of vertices, normals, texture coordinates, and faces
int nvert() const { return vert_.size()/3; }
int nnormal() const { return normal_.size()/3; }
int ntexcoord() const { return texcoord_.size()/2; }
int nface() const { return face_.size()/3; }
int npolygon() const { return polygons_.size(); }
int npolygonvert() const {
int acc = 0;
for (const auto& polygon : polygons_) {
acc += polygon.size();
}
return acc;
}
int npolygonmap() const {
int acc = 0;
for (const auto& polygon : polygon_map_) {
acc += polygon.size();
}
return acc;
}
// return size of graph data in ints
int szgraph() const { return szgraph_; }
// bounding volume hierarchy tree
const mjCBoundingVolumeHierarchy& tree() { return tree_; }
void Compile(const mjVFS* vfs); // compiler
double* GetPosPtr(); // get position
double* GetQuatPtr(); // get orientation
double* GetInertiaBoxPtr(); // get inertia box
double GetVolumeRef() const; // get volume
void FitGeom(mjCGeom* geom, double* meshpos); // approximate mesh with simple geom
bool HasTexcoord() const; // texcoord not null
void DelTexcoord(); // delete texcoord
bool IsVisual(void) const { return visual_; } // is geom visual
void SetNotVisual(void) { visual_ = false; } // mark mesh as not visual
void CopyVert(float* arr) const; // copy vert data into array
void CopyNormal(float* arr) const; // copy normal data into array
void CopyFace(int* arr) const; // copy face data into array
void CopyFaceNormal(int* arr) const; // copy face normal data into array
void CopyFaceTexcoord(int* arr) const; // copy face texcoord data into array
void CopyTexcoord(float* arr) const; // copy texcoord data into array
void CopyGraph(int* arr) const; // copy graph data into array
// copy polygon data into array
void CopyPolygons(int* verts, int* adr, int* num, int poly_adr) const;
// copy polygon map data into array
void CopyPolygonMap(int *faces, int* adr, int* num, int poly_adr) const;
// copy polygon normal data into array
void CopyPolygonNormals(mjtNum* arr);
// sets properties of a bounding volume given a face id
void SetBoundingVolume(int faceid);
// load from OBJ, STL, or MSH file; throws mjCError on failure
void LoadFromResource(mjResource* resource, bool remove_repeated = false);
static bool IsObj(std::string_view filename, std::string_view ct = "");
static bool IsSTL(std::string_view filename, std::string_view ct = "");
static bool IsMSH(std::string_view filename, std::string_view ct = "");
bool IsObj() const;
bool IsSTL() const;
bool IsMSH() const;
private:
void TryCompile(const mjVFS* vfs);
// load mesh from cache asset, return true on success (OBJ files are only supported)
bool LoadCachedMesh(mjCCache *cache, const mjResource* resource);
// store mesh into asset cache (OBJ files are only supported)
void CacheMesh(mjCCache *cache, const mjResource* resource);
// convert vertices to double precision and remove repeated vertices if requested
void ProcessVertices(const std::vector<float>& vert, bool remove_repeated = false);
void LoadOBJ(mjResource* resource, bool remove_repeated); // load mesh in wavefront OBJ format
void LoadSTL(mjResource* resource); // load mesh in STL BIN format
void LoadMSH(mjResource* resource, bool remove_repeated); // load mesh in MSH BIN format
void LoadSDF(); // generate mesh using marching cubes
void MakeGraph(); // make graph of convex hull
void CopyGraph(); // copy graph into face data
void MakeNormal(); // compute vertex normals
void MakeCenter(); // compute face circumcircle data
void Process(); // compute inertial properties
void ApplyTransformations(); // apply user transformations
double ComputeFaceCentroid(double[3]) const; // compute centroid of all faces
void CheckInitialMesh() const; // check if initial mesh is valid
void CopyPlugin();
void Rotate(double quat[4]); // rotate mesh by quaternion
void Transform(double pos[3], double quat[4]); // transform mesh by position and quaternion
void MakePolygons(); // compute the polygon sides of the mesh
void MakePolygonNormals(); // compute the normals of the polygons
// computes the inertia matrix of the mesh given the type of inertia
double ComputeInertia(double inert[6], const double CoM[3]) const;
int* GraphFaces() const {
return graph_ + 2 + 3*(graph_[0] + graph_[1]);
}
// mesh data to be copied into mjModel
double* center_; // face circumcenter data (3*nface)
int* graph_; // convex graph data
// mesh data for collision detection
std::vector<std::vector<int>> polygons_; // polygons of the mesh
std::vector<double> polygon_normals_; // normals of the polygons
std::vector<std::vector<int>> polygon_map_; // map from vertex to polygon
// compute the volume and center-of-mass of the mesh given the face centroid
double ComputeVolume(double CoM[3], const double facecen[3]) const;
// compute the surface area and center-of-mass of the mesh given the face centroid
double ComputeSurfaceArea(double CoM[3], const double facecen[3]) const;
};
//------------------------- class mjCSkin ---------------------------------------------------------
// Describes a skin
class mjCSkin_ : public mjCBase {
protected:
// variable size attributes
std::string file_;
std::string material_;
std::vector<float> vert_;
std::vector<float> texcoord_;
std::vector<int> face_;
std::vector<std::string> bodyname_;
std::vector<float> bindpos_;
std::vector<float> bindquat_;
std::vector<std::vector<int>> vertid_;
std::vector<std::vector<float>> vertweight_;
std::string spec_file_;
std::string spec_material_;
std::vector<float> spec_vert_;
std::vector<float> spec_texcoord_;
std::vector<int> spec_face_;
std::vector<std::string> spec_bodyname_;
std::vector<float> spec_bindpos_;
std::vector<float> spec_bindquat_;
std::vector<std::vector<int>> spec_vertid_;
std::vector<std::vector<float>> spec_vertweight_;
int matid; // material id
std::vector<int> bodyid; // body ids
// paths stored during model attachment
mujoco::user::FilePath modelfiledir_;
mujoco::user::FilePath meshdir_;
};
class mjCSkin: public mjCSkin_, private mjsSkin {
friend class mjCModel;
friend class mjXWriter;
public:
mjCSkin(mjCModel* = nullptr);
mjCSkin(const mjCSkin& other);
mjCSkin& operator=(const mjCSkin& other);
~mjCSkin();
mjsSkin spec;
using mjCBase::name;
using mjCBase::info;
const std::string& File() const { return file_; }
const std::string& get_material() const { return material_; }
const std::vector<float>& get_vert() const { return vert_; }
const std::vector<float>& get_texcoord() const { return texcoord_; }
const std::vector<int>& get_face() const { return face_; }
const std::vector<std::string>& get_bodyname() const { return bodyname_; }
const std::vector<float>& get_bindpos() const { return bindpos_; }
const std::vector<float>& get_bindquat() const { return bindquat_; }
const std::vector<std::vector<int>>& get_vertid() const { return vertid_; }
const std::vector<std::vector<float>>& get_vertweight() const { return vertweight_; }
void del_material() { material_.clear(); }
void CopyFromSpec();
void PointToLocal();
private:
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
void Compile(const mjVFS* vfs); // compiler
void LoadSKN(mjResource* resource); // load skin in SKN BIN format
};
//------------------------- class mjCHField --------------------------------------------------------
// Describes a height field
class mjCHField_ : public mjCBase {
protected:
std::vector<float> data; // elevation data, row-major format
std::string file_;
std::string content_type_;
std::vector<float> userdata_;
std::string spec_file_;
std::string spec_content_type_;
std::vector<float> spec_userdata_;
// paths stored during model attachment
mujoco::user::FilePath modelfiledir_;
mujoco::user::FilePath meshdir_;
};
class mjCHField : public mjCHField_, private mjsHField {
friend class mjCGeom;
friend class mjCModel;
friend class mjXWriter;
public:
mjCHField(mjCModel* model);
mjCHField(const mjCHField& other);
mjCHField& operator=(const mjCHField& other);
~mjCHField();
mjsHField spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec(void);
void PointToLocal(void);
void NameSpace(const mjCModel* m);
std::string File() const { return file_; }
// getter for user data
std::vector<float>& get_userdata() { return userdata_; }
private:
void Compile(const mjVFS* vfs); // compiler
void LoadCustom(mjResource* resource); // load from custom format
void LoadPNG(mjResource* resource); // load from PNG format
};
//------------------------- class mjCTexture -------------------------------------------------------
// Describes a texture
class mjCTexture_ : public mjCBase {
protected:
std::vector<std::byte> data_; // texture data (rgb, roughness, etc.)
std::string file_;
std::string content_type_;
std::vector<std::string> cubefiles_;
std::string spec_file_;
std::string spec_content_type_;
std::vector<std::string> spec_cubefiles_;
// paths stored during model attachment
mujoco::user::FilePath modelfiledir_;
mujoco::user::FilePath texturedir_;
};
class mjCTexture : public mjCTexture_, private mjsTexture {
friend class mjCModel;
friend class mjXReader;
friend class mjXWriter;
public:
mjCTexture(mjCModel*);
mjCTexture(const mjCTexture& other);
mjCTexture& operator=(const mjCTexture& other);
~mjCTexture();
mjsTexture spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec(void);
void PointToLocal(void);
void NameSpace(const mjCModel* m);
std::string File() const { return file_; }
std::string get_content_type() const { return content_type_; }
std::vector<std::string> get_cubefiles() const { return cubefiles_; }
private:
void Compile(const mjVFS* vfs); // compiler
void Builtin2D(void); // make builtin 2D
void BuiltinCube(void); // make builtin cube
void Load2D(std::string filename, const mjVFS* vfs); // load 2D from file
void LoadCubeSingle(std::string filename, const mjVFS* vfs); // load cube from single file
void LoadCubeSeparate(const mjVFS* vfs); // load cube from separate files
void LoadFlip(std::string filename, const mjVFS* vfs, // load and flip
std::vector<unsigned char>& image,
unsigned int& w, unsigned int& h);
void LoadPNG(mjResource* resource,
std::vector<unsigned char>& image,
unsigned int& w, unsigned int& h);
void LoadCustom(mjResource* resource,
std::vector<unsigned char>& image,
unsigned int& w, unsigned int& h);
bool clear_data_; // if true, data_ is empty and should be filled by Compile
};
//------------------------- class mjCMaterial ------------------------------------------------------
// Describes a material for rendering
class mjCMaterial_ : public mjCBase {
protected:
int texid[mjNTEXROLE]; // id of material's textures
std::vector<std::string> textures_;
std::vector<std::string> spec_textures_;
};
class mjCMaterial : public mjCMaterial_, private mjsMaterial {
friend class mjCDef;
friend class mjCModel;
friend class mjXWriter;
public:
mjCMaterial(mjCModel* = nullptr, mjCDef* = nullptr);
mjCMaterial(const mjCMaterial& other);
mjCMaterial& operator=(const mjCMaterial& other);
mjsMaterial spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec();
void PointToLocal();
void NameSpace(const mjCModel* m);
const std::string& get_texture(int i) const { return textures_[i]; }
void del_textures() { for (auto& t : textures_) t.clear(); }
private:
void Compile(void); // compiler
};
//------------------------- class mjCPair ----------------------------------------------------------
// Predefined geom pair for collision detection
class mjCPair_ : public mjCBase {
protected:
int signature; // body1<<16 + body2
std::string geomname1_;
std::string geomname2_;
std::string spec_geomname1_;
std::string spec_geomname2_;
};
class mjCPair : public mjCPair_, private mjsPair {
friend class mjCDef;
friend class mjCBody;
friend class mjCModel;
friend class mjXWriter;
public:
mjCPair(mjCModel* = nullptr, mjCDef* = nullptr);
mjCPair(const mjCPair& other);
mjCPair& operator=(const mjCPair& other);
mjsPair spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec();
void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
const std::string& get_geomname1() const { return geomname1_; }
const std::string& get_geomname2() const { return geomname2_; }
int GetSignature(void) {
return signature;
}
private:
void Compile(void); // compiler
mjCGeom* geom1; // geom1
mjCGeom* geom2; // geom2
};
//------------------------- class mjCBodyPair ------------------------------------------------------
// Body pair specification, use to exclude pairs
class mjCBodyPair_ : public mjCBase {
protected:
int body1; // id of body1
int body2; // id of body2
int signature; // body1<<16 + body2
std::string bodyname1_; // name of geom 1
std::string bodyname2_; // name of geom 2
std::string spec_bodyname1_;
std::string spec_bodyname2_;
};
class mjCBodyPair : public mjCBodyPair_, private mjsExclude {
friend class mjCBody;
friend class mjCModel;
public:
mjCBodyPair(mjCModel*);
mjCBodyPair(const mjCBodyPair& other);
mjCBodyPair& operator=(const mjCBodyPair& other);
mjsExclude spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec();
void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
std::string get_bodyname1() const { return bodyname1_; }
std::string get_bodyname2() const { return bodyname2_; }
int GetSignature() {
return signature;
}
private:
void Compile(); // compiler
};
//------------------------- class mjCEquality ------------------------------------------------------
// Describes an equality constraint
class mjCEquality_ : public mjCBase {
protected:
int obj1id;
int obj2id;
std::string name1_;
std::string name2_;
std::string spec_name1_;
std::string spec_name2_;
};
class mjCEquality : public mjCEquality_, private mjsEquality {
friend class mjCDef;
friend class mjCBody;
friend class mjCModel;
friend class mjXWriter;
public:
mjCEquality(mjCModel* = 0, mjCDef* = 0);
mjCEquality(const mjCEquality& other);
mjCEquality& operator=(const mjCEquality& other);
mjsEquality spec;
using mjCBase::name;
using mjCBase::info;
void CopyFromSpec();
void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
private:
void Compile(void); // compiler
};
//------------------------- class mjCTendon --------------------------------------------------------
// Describes a tendon
class mjCTendon_ : public mjCBase {
protected:
int matid; // material id for rendering
// variable-size data
std::string material_;
std::string spec_material_;
std::vector<double> userdata_;
std::vector<double> spec_userdata_;
};
class mjCTendon : public mjCTendon_, private mjsTendon {
friend class mjCDef;
friend class mjCModel;
friend class mjXWriter;
public:
mjCTendon(mjCModel* = nullptr, mjCDef* = nullptr);
mjCTendon(const mjCTendon& other);
mjCTendon& operator=(const mjCTendon& other);
~mjCTendon();
mjsTendon spec;
using mjCBase::name;
using mjCBase::info;
void set_material(std::string _material) { material_ = _material; }
const std::string& get_material() const { return material_; }
void del_material() { material_.clear(); }
// API for adding wrapping objects
void WrapSite(std::string name, std::string_view info = ""); // site
void WrapGeom(std::string name, std::string side, std::string_view info = ""); // geom
void WrapJoint(std::string name, double coef, std::string_view info = ""); // joint
void WrapPulley(double divisor, std::string_view info = ""); // pulley
// API for access to wrapping objects
int NumWraps() const; // number of wraps
const mjCWrap* GetWrap(int i) const; // pointer to wrap
std::vector<mjCWrap*> path; // wrapping objects
// used by mjXWriter and mjCModel
const std::vector<double>& get_userdata() const { return userdata_; }
const double* get_range() { return range; }
void CopyFromSpec();
void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
void SetModel(mjCModel* _model);
bool is_limited() const;
bool is_actfrclimited() const;
private:
void Compile(void); // compiler
};
//------------------------- class mjCWrap ----------------------------------------------------------
// Describes a tendon wrap object
class mjCWrap_ : public mjCBase {
public:
mjtWrap type; // wrap object type
int sideid; // side site id; -1 if not applicable
double prm; // parameter: divisor, coefficient
std::string sidesite; // name of side site
};
class mjCWrap : public mjCWrap_, private mjsWrap {
friend class mjCTendon;
friend class mjCModel;
public:
mjsWrap spec;
using mjCBase::info;
void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
mjCBase* obj; // wrap object pointer
private:
mjCWrap(mjCModel*, mjCTendon*); // constructor
mjCWrap(const mjCWrap& other); // copy constructor
mjCWrap& operator=(const mjCWrap& other); // copy assignment
mjCTendon* tendon; // tendon owning this wrap
};
//------------------------- class mjCPlugin --------------------------------------------------------
// Describes an instance of a plugin
class mjCPlugin_ : public mjCBase {
public:
int nstate; // state size for the plugin instance
std::map<std::string, std::string, std::less<>> config_attribs; // raw config attributes from XML
std::vector<char> flattened_attributes; // config attributes flattened in plugin-declared order;
protected:
std::string plugin_name;
};
class mjCPlugin : public mjCPlugin_ {
friend class mjCModel;
friend class mjXWriter;
public:
mjCPlugin(mjCModel*);
mjCPlugin(const mjCPlugin& other);
mjCPlugin& operator=(const mjCPlugin& other);
void PointToLocal();
mjsPlugin spec;
mjCBase* parent; // parent object (only used when generating error message)
int plugin_slot; // global registered slot number of the plugin
private:
void Compile(void); // compiler
};
//------------------------- class mjCActuator ------------------------------------------------------
// Describes an actuator
class mjCActuator_ : public mjCBase {
protected:
int trnid[2]; // id of transmission target
// variable used for temporarily storing the state of the actuator
int actadr_; // address of dof in data->act
int actdim_; // number of dofs in data->act
std::map<std::string, std::vector<mjtNum>> act_; // act at the previous step
std::map<std::string, mjtNum> ctrl_; // ctrl at the previous step
// variable-size data
std::string plugin_name;
std::string plugin_instance_name;
std::string target_;
std::string slidersite_;
std::string refsite_;
std::vector<double> userdata_;
std::string spec_target_;
std::string spec_slidersite_;
std::string spec_refsite_;
std::vector<double> spec_userdata_;
};
class mjCActuator : public mjCActuator_, private mjsActuator {
friend class mjCDef;
friend class mjCModel;
friend class mjXWriter;
public:
mjCActuator(mjCModel* = nullptr, mjCDef* = nullptr);
mjCActuator(const mjCActuator& other);
mjCActuator& operator=(const mjCActuator& other);
mjsActuator spec;
using mjCBase::name;
using mjCBase::info;
// used by mjXWriter and mjCModel
const std::vector<double>& get_userdata() const { return userdata_; }
const std::string& get_target() const { return spec_target_; }
const std::string& get_slidersite() const { return spec_slidersite_; }
const std::string& get_refsite() const { return spec_refsite_; }
bool is_ctrllimited() const;
bool is_forcelimited() const;
bool is_actlimited() const;
std::vector<mjtNum>& act(const std::string& state_name);
mjtNum& ctrl(const std::string& state_name);
private:
void Compile(void); // compiler
void CopyFromSpec();
void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
void CopyPlugin();
// reset keyframe references for allowing self-attach
void ForgetKeyframes();
mjCBase* ptarget; // transmission target
};
//------------------------- class mjCSensor --------------------------------------------------------
// Describes a sensor
class mjCSensor_ : public mjCBase {
protected:
int refid; // id of reference frame
// variable-size data
std::string plugin_name;
std::string plugin_instance_name;
std::string objname_;
std::string refname_;
std::vector<double> userdata_;
std::string spec_objname_;
std::string spec_refname_;
std::vector<double> spec_userdata_;
};
class mjCSensor : public mjCSensor_, private mjsSensor {
friend class mjCDef;
friend class mjCModel;
friend class mjXWriter;
public:
mjCSensor(mjCModel*);
mjCSensor(const mjCSensor& other);
mjCSensor& operator=(const mjCSensor& other);
mjsSensor spec;
using mjCBase::name;
using mjCBase::info;
// used by mjXWriter and mjCModel
const std::vector<double>& get_userdata() { return userdata_; }
const std::string& get_objname() { return spec_objname_; }
const std::string& get_refname() { return spec_refname_; }
private:
void Compile(void); // compiler
void CopyFromSpec();
void PointToLocal();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
void CopyPlugin();
mjCBase* obj; // sensorized object
mjCBase* ref; // sensorized reference
};
//------------------------- class mjCNumeric -------------------------------------------------------
// Describes a custom data field
class mjCNumeric_ : public mjCBase {
protected:
std::vector<double> data_;
std::vector<double> spec_data_;
};
class mjCNumeric : public mjCNumeric_, private mjsNumeric {
friend class mjCModel;
friend class mjXWriter;
public:
mjCNumeric(mjCModel*);
mjCNumeric(const mjCNumeric& other);
mjCNumeric& operator=(const mjCNumeric& other);
~mjCNumeric();
mjsNumeric spec;
using mjCBase::name;
using mjCBase::info;
void PointToLocal();
void CopyFromSpec();
private:
void Compile(void); // compiler
};
//------------------------- class mjCText ----------------------------------------------------------
// Describes a custom text field
class mjCText_ : public mjCBase {
protected:
std::string data_;
std::string spec_data_;
};
class mjCText : public mjCText_, private mjsText {
friend class mjCModel;
friend class mjXWriter;
public:
mjCText(mjCModel*);
mjCText(const mjCText& other);
mjCText& operator=(const mjCText& other);
~mjCText();
mjsText spec;
using mjCBase::name;
using mjCBase::info;
void PointToLocal();
void CopyFromSpec();
private:
void Compile(void); // compiler
};
//------------------------- class mjCTuple ---------------------------------------------------------
// Describes a custom tuple field
class mjCTuple_ : public mjCBase {
protected:
std::vector<mjCBase*> obj; // object pointers
std::vector<mjtObj> objtype_;
std::vector<std::string> objname_;
std::vector<double> objprm_;
std::vector<mjtObj> spec_objtype_;
std::vector<std::string> spec_objname_;
std::vector<double> spec_objprm_;
};
class mjCTuple : public mjCTuple_, private mjsTuple {
friend class mjCModel;
friend class mjXWriter;
public:
mjCTuple(mjCModel*);
mjCTuple(const mjCTuple& other);
mjCTuple& operator=(const mjCTuple& other);
~mjCTuple();
mjsTuple spec;
using mjCBase::name;
using mjCBase::info;
void PointToLocal();
void CopyFromSpec();
void ResolveReferences(const mjCModel* m);
void NameSpace(const mjCModel* m);
private:
void Compile(void); // compiler
};
//------------------------- class mjCKey -----------------------------------------------------------
// Describes a keyframe
class mjCKey_ : public mjCBase {
protected:
std::vector<double> qpos_;
std::vector<double> qvel_;
std::vector<double> act_;
std::vector<double> mpos_;
std::vector<double> mquat_;
std::vector<double> ctrl_;
std::vector<double> spec_qpos_;
std::vector<double> spec_qvel_;
std::vector<double> spec_act_;
std::vector<double> spec_mpos_;
std::vector<double> spec_mquat_;
std::vector<double> spec_ctrl_;
};
class mjCKey : public mjCKey_, private mjsKey {
friend class mjCModel;
friend class mjXWriter;
public:
mjCKey(mjCModel*);
mjCKey(const mjCKey& other);
mjCKey& operator=(const mjCKey& other);
~mjCKey();
mjsKey spec;
using mjCBase::name;
using mjCBase::info;
void PointToLocal();
void CopyFromSpec();
private:
void Compile(const mjModel* m); // compiler
};
//------------------------- class mjCDef -----------------------------------------------------------
// Describes one set of defaults
class mjCDef : public mjsElement {
friend class mjXWriter;
public:
mjCDef();
mjCDef(mjCModel*);
mjCDef(const mjCDef& other);
mjCDef& operator=(const mjCDef& other);
mjCDef& operator+=(const mjCDef& other);
void CopyWithoutChildren(const mjCDef& other);
void PointToLocal(void);
void CopyFromSpec(void);
void NameSpace(const mjCModel* m);
void Compile(const mjCModel* model);
// accessors
mjCJoint& Joint() { return joint_; }
mjCGeom& Geom() { return geom_; }
mjCSite& Site() { return site_; }
mjCCamera& Camera() { return camera_; }
mjCLight& Light() { return light_; }
mjCFlex& Flex() { return flex_; }
mjCMesh& Mesh() { return mesh_; }
mjCMaterial& Material() { return material_; }
mjCPair& Pair() { return pair_; }
mjCEquality& Equality() { return equality_; }
mjCTendon& Tendon() { return tendon_; }
mjCActuator& Actuator() { return actuator_; }
// identifiers
std::string name; // class name
int id; // id of this default
mjCDef* parent; // id of parent class
std::vector<mjCDef*> child; // child classes
mjsDefault spec;
mjCModel* model; // pointer to model that owns object
private:
mjCJoint joint_;
mjCGeom geom_;
mjCSite site_;
mjCCamera camera_;
mjCLight light_;
mjCFlex flex_;
mjCMesh mesh_;
mjCMaterial material_;
mjCPair pair_;
mjCEquality equality_;
mjCTendon tendon_;
mjCActuator actuator_;
};
#endif // MUJOCO_SRC_USER_USER_OBJECTS_H_