SimMjcf.cpp
Go to the documentation of this file.
1 #include "SimMjcf.h"
2 
3 #include <VirtualRobot/CollisionDetection/CollisionModel.h>
4 #include <VirtualRobot/Visualization/TriMeshModel.h>
5 #include <VirtualRobot/Visualization/VisualizationNode.h>
6 #include <VirtualRobot/XML/mujoco/Mesh.h>
7 #include <VirtualRobot/XML/mujoco/MeshConverter.h>
8 #include <VirtualRobot/math/Helpers.h>
9 
11 
12 #include "LengthScaling.h"
13 
14 
15 using namespace armarx;
16 
17 SimMJCF::SimMJCF(mjcf::Document& document,
18  const LengthScaling& lengthScaling,
19  const std::string& loggingTag) :
20  document(document), scaling(lengthScaling)
21 {
22  Logging::setTag(loggingTag);
23 }
24 
25 void
26 SimMJCF::includeBaseFile(const std::string& path, const std::string& relativeFrom)
27 {
28  std::string absolute = path;
29  ArmarXDataPath::getAbsolutePath(path, absolute);
30 
31  std::filesystem::path absol = absolute;
32  absol.relative_path();
33 
34  if (std::filesystem::exists(absolute))
35  {
36  std::string relative = ArmarXDataPath::relativeTo(relativeFrom, absolute);
37  document.addInclude(relative);
38  }
39  else
40  {
41  ARMARX_WARNING << "Base MJCF file does not exist: " << absolute
42  << "\nProceeding without including the base MJCF.";
43  }
44 }
45 
46 void
47 SimMJCF::addObjectDefaults(const std::string& className)
48 {
49  mjcf::DefaultClass objectClass = document.default_().getClass(className);
50 
51  mjcf::Geom geom = objectClass.addChild<mjcf::Geom>();
52  geom.rgba = Eigen::Vector4f::Ones();
53 
54  mjcf::Joint joint = objectClass.addChild<mjcf::Joint>();
55  joint.frictionloss = 1;
56 
57  mjcf::Mesh mesh = objectClass.addChild<mjcf::Mesh>();
58  mesh.scale = scaling.milliToMeter(Eigen::Vector3f::Ones().eval());
59 }
60 
61 void
62 SimMJCF::setTimeStep(float timestep)
63 {
64  document.option().timestep = timestep;
65 }
66 
67 void
68 SimMJCF::addFloor(bool enabled, const std::string& texture, const std::string& name, float size)
69 {
70  if (enabled)
71  {
72  ARMARX_INFO << "Adding floor (texture: " << texture << ")";
73 
74  // add default class
75  mjcf::DefaultClass defaults = document.default_().getClass(name);
76  mjcf::Geom defaultGeom = defaults.addChild<mjcf::Geom>();
77  defaultGeom.type = "plane";
78  defaultGeom.size = Eigen::Vector3f(size, size, 5);
79  defaultGeom.material = name;
80 
81  // add texture
82  bool addDefaultTexture = true;
83 
84  if (!texture.empty())
85  {
86  std::string absolute = texture;
87  ArmarXDataPath::getAbsolutePath(texture, absolute);
88 
89  if (std::filesystem::exists(absolute))
90  {
91  document.asset().addTextureFile(name, absolute);
92  addDefaultTexture = false;
93  }
94  else
95  {
96  ARMARX_WARNING << "Texture file does not exist: " << absolute
97  << "\nProceeding with generated floor texture";
98  }
99  }
100  if (addDefaultTexture)
101  {
102  mjcf::Texture texture = document.asset().addChild<mjcf::Texture>();
103  texture.name = name;
104  texture.type = "2d";
105  texture.builtin = "checker";
106  texture.width = 512;
107  texture.height = 512;
108  texture.rgb1 = {.35f, .375f, .4f};
109  texture.rgb2 = {.10f, .150f, .2f};
110  }
111 
112  // add material
113  mjcf::Material material = document.asset().addMaterial(name, name);
114  material.reflectance = 0.3f;
115  material.texrepeat = {1, 1};
116  material.texuniform = true;
117 
118  // add body and geom
119  mjcf::Body body = document.worldbody().addBody(name);
120  body.childclass = name;
121 
122  mjcf::Geom geom = body.addChild<mjcf::Geom>();
123  geom.name = name;
124  geom.pos = Eigen::Vector3f::Zero();
125  }
126 }
127 
128 void
130  VirtualRobot::SceneObject::Physics::SimulationType simType,
131  const std::string& className,
132  const std::filesystem::path& meshDir)
133 {
134  const std::string objectName = object->getName();
135 
136  if (object->getParent())
137  {
138  ARMARX_WARNING << "Object has parent, which is currently not implemented.";
139  }
140 
141  std::string meshName;
142 
143  if (false && object->getVisualization())
144  {
145  ARMARX_INFO << "Has visualization";
146  ARMARX_INFO << "Visu filename: " << object->getVisualization()->getFilename();
147  ARMARX_INFO << "Num faces: " << object->getVisualization()->getNumFaces();
148  ARMARX_INFO << "Has tri mesh?: "
149  << object->getVisualization()->getTriMeshModel().operator bool();
150  ARMARX_INFO << "Primitives: " << object->getVisualization()->primitives.size();
151  }
152 
153  if (object->getCollisionModel())
154  {
155  VirtualRobot::CollisionModelPtr collisionModel = object->getCollisionModel();
156 
157  const std::string colModelName = collisionModel->getName();
158 
159  const std::string filename = colModelName + ".msh";
160  const std::filesystem::path meshFilePath = meshDir / filename;
161 
162  try
163  {
164  // does nothing if already exists
165  std::filesystem::create_directory(meshDir);
166  }
167  catch (const std::filesystem::filesystem_error& e)
168  {
169  ARMARX_ERROR << "Could not create temporary mesh dir " << meshDir << "."
170  << "\nReason: " << e.what();
171  }
172 
173  if (std::filesystem::is_regular_file(meshFilePath))
174  {
175  ARMARX_VERBOSE << "Collision model " << colModelName << " already converted.";
176  }
177  else
178  {
179  VirtualRobot::TriMeshModelPtr meshModel = collisionModel->getTriMeshModel();
180  if (meshModel)
181  {
182  ARMARX_VERBOSE << "Converting collision model " << colModelName << " ("
183  << meshModel->faces.size() << " faces) ...";
184 
185  VirtualRobot::mujoco::Mesh mjMesh =
186  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:26
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:407
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
GfxTL::Orientation
ScalarT Orientation(const VectorXD< 2, ScalarT > &p1, const VectorXD< 2, ScalarT > &p2, const VectorXD< 2, ScalarT > &c)
Definition: Orientation.h:10
armarx::SimMJCF::addFloor
void addFloor(bool enabled, const std::string &texture, const std::string &name, float size)
Definition: SimMjcf.cpp:68
armarx::SimMJCF::SimMJCF
SimMJCF(mjcf::Document &document, const LengthScaling &scaling, const std::string &loggingTag="SimMJCF")
Definition: SimMjcf.cpp:17
SimMjcf.h
armarx::LengthScaling::milliToMeter
float milliToMeter() const
Get the scaling factor for: meter = millimeter * factor.
Definition: LengthScaling.cpp:36
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:129
enabled
std::atomic< bool > * enabled
Definition: RemoteGuiWidgetController.cpp:75
filename
std::string filename
Definition: VisualizationRobot.cpp:86
Eigen::Quaternionf
Quaternion< float, 0 > Quaternionf
Definition: EigenForwardDeclarations.h:61
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::SimMJCF::setTimeStep
void setTimeStep(float timestep)
Definition: SimMjcf.cpp:62
LengthScaling.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
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:109
armarx::Logging::setTag
void setTag(const LogTag &tag)
Definition: Logging.cpp:54
armarx::navigation::core::Position
Eigen::Vector3f Position
Definition: basic_types.h:36
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
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:27
armarx::SimMJCF::addObjectDefaults
void addObjectDefaults(const std::string &className)
Definition: SimMjcf.cpp:47