SimMjcf.cpp
Go to the documentation of this file.
1 #include "SimMjcf.h"
2 
3 #include <VirtualRobot/math/Helpers.h>
4 #include <VirtualRobot/CollisionDetection/CollisionModel.h>
5 #include <VirtualRobot/Visualization/TriMeshModel.h>
6 #include <VirtualRobot/Visualization/VisualizationNode.h>
7 #include <VirtualRobot/XML/mujoco/Mesh.h>
8 #include <VirtualRobot/XML/mujoco/MeshConverter.h>
9 
11 
12 #include "LengthScaling.h"
13 
14 
15 using namespace armarx;
16 
17 
18 
19 SimMJCF::SimMJCF(mjcf::Document& document,
20  const LengthScaling& lengthScaling,
21  const std::string& loggingTag) :
22  document(document),
23  scaling(lengthScaling)
24 {
25  Logging::setTag(loggingTag);
26 }
27 
28 
29 void SimMJCF::includeBaseFile(const std::string& path,
30  const std::string& relativeFrom)
31 {
32  std::string absolute = path;
33  ArmarXDataPath::getAbsolutePath(path, absolute);
34 
35  std::filesystem::path absol = absolute;
36  absol.relative_path();
37 
38  if (std::filesystem::exists(absolute))
39  {
40  std::string relative = ArmarXDataPath::relativeTo(relativeFrom, absolute);
41  document.addInclude(relative);
42  }
43  else
44  {
45  ARMARX_WARNING << "Base MJCF file does not exist: " << absolute
46  << "\nProceeding without including the base MJCF.";
47  }
48 }
49 
50 
51 void SimMJCF::addObjectDefaults(const std::string& className)
52 {
53  mjcf::DefaultClass objectClass = document.default_().getClass(className);
54 
55  mjcf::Geom geom = objectClass.addChild<mjcf::Geom>();
56  geom.rgba = Eigen::Vector4f::Ones();
57 
58  mjcf::Joint joint = objectClass.addChild<mjcf::Joint>();
59  joint.frictionloss = 1;
60 
61  mjcf::Mesh mesh = objectClass.addChild<mjcf::Mesh>();
62  mesh.scale = scaling.milliToMeter(Eigen::Vector3f::Ones().eval());
63 }
64 
65 void SimMJCF::setTimeStep(float timestep)
66 {
67  document.option().timestep = timestep;
68 }
69 
70 void SimMJCF::addFloor(bool enabled, const std::string& texture,
71  const std::string& name, float size)
72 {
73  if (enabled)
74  {
75  ARMARX_INFO << "Adding floor (texture: " << texture << ")";
76 
77  // add default class
78  mjcf::DefaultClass defaults = document.default_().getClass(name);
79  mjcf::Geom defaultGeom = defaults.addChild<mjcf::Geom>();
80  defaultGeom.type = "plane";
81  defaultGeom.size = Eigen::Vector3f(size, size, 5);
82  defaultGeom.material = name;
83 
84  // add texture
85  bool addDefaultTexture = true;
86 
87  if (!texture.empty())
88  {
89  std::string absolute = texture;
90  ArmarXDataPath::getAbsolutePath(texture, absolute);
91 
92  if (std::filesystem::exists(absolute))
93  {
94  document.asset().addTextureFile(name, absolute);
95  addDefaultTexture = false;
96  }
97  else
98  {
99  ARMARX_WARNING << "Texture file does not exist: " << absolute
100  << "\nProceeding with generated floor texture";
101  }
102  }
103  if (addDefaultTexture)
104  {
105  mjcf::Texture texture = document.asset().addChild<mjcf::Texture>();
106  texture.name = name;
107  texture.type = "2d";
108  texture.builtin = "checker";
109  texture.width = 512;
110  texture.height = 512;
111  texture.rgb1 = { .35f, .375f, .4f };
112  texture.rgb2 = { .10f, .150f, .2f };
113  }
114 
115  // add material
116  mjcf::Material material = document.asset().addMaterial(name, name);
117  material.reflectance = 0.3f;
118  material.texrepeat = { 1, 1 };
119  material.texuniform = true;
120 
121  // add body and geom
122  mjcf::Body body = document.worldbody().addBody(name);
123  body.childclass = name;
124 
125  mjcf::Geom geom = body.addChild<mjcf::Geom>();
126  geom.name = name;
127  geom.pos = Eigen::Vector3f::Zero();
128  }
129 }
130 
132  VirtualRobot::SceneObject::Physics::SimulationType simType,
133  const std::string& className,
134  const std::filesystem::path& meshDir)
135 {
136  const std::string objectName = object->getName();
137 
138  if (object->getParent())
139  {
140  ARMARX_WARNING << "Object has parent, which is currently not implemented.";
141  }
142 
143  std::string meshName;
144 
145  if (false && object->getVisualization())
146  {
147  ARMARX_INFO << "Has visualization";
148  ARMARX_INFO << "Visu filename: " << object->getVisualization()->getFilename();
149  ARMARX_INFO << "Num faces: " << object->getVisualization()->getNumFaces();
150  ARMARX_INFO << "Has tri mesh?: " << object->getVisualization()->getTriMeshModel().operator bool();
151  ARMARX_INFO << "Primitives: " << object->getVisualization()->primitives.size();
152  }
153 
154  if (object->getCollisionModel())
155  {
156  VirtualRobot::CollisionModelPtr collisionModel = object->getCollisionModel();
157 
158  const std::string colModelName = collisionModel->getName();
159 
160  const std::string filename = colModelName + ".msh";
161  const std::filesystem::path meshFilePath = meshDir / filename;
162 
163  try
164  {
165  // does nothing if already exists
166  std::filesystem::create_directory(meshDir);
167  }
168  catch (const std::filesystem::filesystem_error& e)
169  {
170  ARMARX_ERROR << "Could not create temporary mesh dir " << meshDir << "."
171  << "\nReason: " << e.what();
172  }
173 
174  if (std::filesystem::is_regular_file(meshFilePath))
175  {
176  ARMARX_VERBOSE << "Collision model " << colModelName << " already converted.";
177  }
178  else
179  {
180  VirtualRobot::TriMeshModelPtr meshModel = collisionModel->getTriMeshModel();
181  if (meshModel)
182  {
183  ARMARX_VERBOSE << "Converting collision model " << colModelName
184  << " (" << meshModel->faces.size() << " faces) ...";
185 
186  VirtualRobot::mujoco::Mesh mjMesh = VirtualRobot::mujoco::MeshConverter::fromVirtualRobot(*meshModel);
187  mjMesh.write(meshFilePath.string());
188  }
189  }
190 
191  meshName = colModelName;
192 
193  // add the mesh as asset
194  if (!document.asset().hasChild<mjcf::Mesh>("name", meshName))
195  {
196  mjcf::Mesh mesh = document.asset().addMesh(meshName, meshFilePath.string());
197  mesh.class_ = className;
198  }
199  }
200 
201  mjcf::Body body = document.worldbody().addBody(objectName);
202  body.childclass = className;
203  body.pos = scaling.milliToMeter(math::Helpers::Position(object->getGlobalPose()).eval());
204  body.quat = Eigen::Quaternionf(math::Helpers::Orientation(object->getGlobalPose()));
205 
206  mjcf::Geom geom = body.addGeomMesh(meshName);
207  geom.name = objectName;
208 
209  if (object->getFriction() > 0)
210  {
211  Eigen::Vector3f friction = geom.friction;
212  friction(0) = object->getFriction();
213  geom.friction = friction;
214  }
215 
216  mjcf::Inertial inertial = body.addInertial();
217  inertial.mass = object->getMass();
218  inertial.pos = scaling.milliToMeter(object->getCoMLocal());
219  inertial.inertiaFromMatrix(object->getInertiaMatrix());
220 
221  switch (simType)
222  {
223  case VirtualRobot::SceneObject::Physics::SimulationType::eKinematic:
224  // make it a mocap body
225  body.mocap = true;
226  break;
227 
228  case VirtualRobot::SceneObject::Physics::SimulationType::eDynamic:
229  // add free joint
230  {
231  mjcf::Joint joint = body.addJoint();
232  joint.name = objectName;
233  joint.type = "free";
234  }
235  break;
236 
237  case VirtualRobot::SceneObject::Physics::SimulationType::eStatic:
238  case VirtualRobot::SceneObject::Physics::SimulationType::eUnknown:
239  // do nothing
240  break;
241  }
242 }
armarx::SimMJCF::includeBaseFile
void includeBaseFile(const std::string &path, const std::string &relativeFrom)
Definition: SimMjcf.cpp:29
armarx::ArmarXDataPath::relativeTo
static std::string relativeTo(const std::string &from, const std::string &to)
Transform an absolute filepath into a relative path of the other absolute filepath.
Definition: ArmarXDataPath.cpp:410
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
GfxTL::Orientation
ScalarT Orientation(const VectorXD< 2, ScalarT > &p1, const VectorXD< 2, ScalarT > &p2, const VectorXD< 2, ScalarT > &c)
Definition: Orientation.h:9
armarx::SimMJCF::addFloor
void addFloor(bool enabled, const std::string &texture, const std::string &name, float size)
Definition: SimMjcf.cpp:70
armarx::SimMJCF::SimMJCF
SimMJCF(mjcf::Document &document, const LengthScaling &scaling, const std::string &loggingTag="SimMJCF")
Definition: SimMjcf.cpp:19
SimMjcf.h
armarx::LengthScaling::milliToMeter
float milliToMeter() const
Get the scaling factor for: meter = millimeter * factor.
Definition: LengthScaling.cpp:32
armarx::SimMJCF::addObject
void addObject(VirtualRobot::SceneObjectPtr object, VirtualRobot::SceneObject::Physics::SimulationType simType, const std::string &className, const std::filesystem::path &meshDir)
Definition: SimMjcf.cpp:131
enabled
std::atomic< bool > * enabled
Definition: RemoteGuiWidgetController.cpp:75
filename
std::string filename
Definition: VisualizationRobot.cpp:83
Eigen::Quaternionf
Quaternion< float, 0 > Quaternionf
Definition: EigenForwardDeclarations.h:61
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::SimMJCF::setTimeStep
void setTimeStep(float timestep)
Definition: SimMjcf.cpp:65
LengthScaling.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
scene3D::SceneObjectPtr
boost::intrusive_ptr< SceneObject > SceneObjectPtr
Definition: PointerDefinitions.h:40
armarx::ArmarXDataPath::getAbsolutePath
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
Definition: ArmarXDataPath.cpp:111
armarx::Logging::setTag
void setTag(const LogTag &tag)
Definition: Logging.cpp:55
armarx::navigation::core::Position
Eigen::Vector3f Position
Definition: basic_types.h:36
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
ArmarXDataPath.h
armarx::LengthScaling
Definition: LengthScaling.h:6
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::SimMJCF::addObjectDefaults
void addObjectDefaults(const std::string &className)
Definition: SimMjcf.cpp:51