25 #ifdef MUJOCO_PHYSICS_WORLD
31 #include <VirtualRobot/math/Helpers.h>
36 #include <MujocoX/libraries/Simulation/utils/eigen_conversion.h>
39 namespace fs = std::filesystem;
47 FunctionLogger(
const std::string& functionName) : functionName(functionName)
55 std::string functionName;
64 #define NOT_YET_IMPLEMENTED() \
65 throw exceptions::user::NotImplementedYetException(__FUNCTION__)
69 #define NOT_YET_IMPLEMENTED() ARMARX_WARNING << "Not implemented: \t" << __FUNCTION__ << "()"
74 #define DO_LOG_FUNCTIONS
75 #ifdef DO_LOG_FUNCTIONS
76 #define LOG_FUNCTION() const FunctionLogger __functionLogger__(__FUNCTION__)
78 #define LOG_FUNCTION() (void) 0
84 const fs::path MujocoPhysicsWorld::BASE_MJCF_FILENAME =
85 "ArmarXSimulation/mujoco_base_model.xml";
87 const fs::path MujocoPhysicsWorld::TEMP_DIR =
88 fs::temp_directory_path() /
"MujocoSimulation";
90 const fs::path MujocoPhysicsWorld::TEMP_MODEL_FILE =
91 TEMP_DIR /
"SimulationModel.xml";
93 const fs::path MujocoPhysicsWorld::TEMP_MESH_DIR_REL =
95 const fs::path MujocoPhysicsWorld::TEMP_MESH_DIR =
96 TEMP_DIR / TEMP_MESH_DIR_REL;
98 const std::string MujocoPhysicsWorld::FLOOR_NAME =
"floor";
99 const std::string MujocoPhysicsWorld::OBJECT_CLASS_NAME =
"object";
107 sim.addCallbackListener(*
this);
111 int stepTimeMs,
bool floorEnabled,
const std::string& floorTexture)
118 fixedTimeStep = std::chrono::milliseconds(stepTimeMs);
119 simMjcf.
setTimeStep(fixedTimeStep.count() / 1000.f);
123 ARMARX_VERBOSE <<
"Activating MuJoCo ... with key file " << MUJOCO_KEY_FILE;
124 mujoco::MujocoSim::ensureActivated(MUJOCO_KEY_FILE);
128 sim.simLoopPrepare();
138 model->opt.timestep = fixedTimeStep.count() / 1000.0;
145 for (
auto& objectItem : objects)
147 objectItem.second.update(model);
154 (void) model, (
void)
data;
160 NOT_YET_IMPLEMENTED();
170 sim.handleLoadRequest();
172 auto start = std::chrono::system_clock::now();
181 std::chrono::milliseconds sleepTime = std::chrono::duration_cast<std::chrono::milliseconds>(
182 end - std::chrono::system_clock::now());
184 std::this_thread::sleep_until(end);
189 return static_cast<int>(sim.model()->opt.timestep * 1000);
195 std::vector<std::string> result;
196 std::transform(obstacles.begin(), obstacles.end(), std::back_inserter(result),
197 [](
const auto & item)
207 std::vector<std::string>
names;
209 [](
const auto & item)
220 simMjcf.
addFloor(enable, floorTexture, FLOOR_NAME, 20);
221 this->floorTextureFile = floorTexture;
227 VirtualRobot::SceneObject::Physics::SimulationType simType)
230 simMjcf.
addObject(
object, simType, OBJECT_CLASS_NAME, TEMP_MESH_DIR);
231 obstacles[
object->getName()] = object;
239 NOT_YET_IMPLEMENTED();
245 NOT_YET_IMPLEMENTED();
251 double pid_p,
double pid_i,
double pid_d,
252 const std::string&
filename,
bool staticRobot,
bool selfCollisions)
257 <<
"\n- (p, i, d): \t(" << pid_p <<
" " << pid_i <<
" " << pid_d <<
")"
258 <<
"\n- static: \t" << staticRobot
259 <<
"\n- self coll.: \t" << selfCollisions
265 if (!sim.isModelLoaded())
272 ARMARX_ERROR <<
"More than one robot with identical name is currently not supported.";
278 ARMARX_ERROR <<
"Static robots are currently not supported.";
289 simRobot.mjcf = makeRobotMjcfModel(robot);
293 TEMP_DIR, simRobot.mjcf.getOutputFile());
296 mjcfDocument.addInclude(robotModelFile);
299 robots[robot->getName()] = std::move(simRobot);
311 const std::string& robotName,
312 const std::map<std::string, float>& angles,
313 const std::map<std::string, float>& velocities)
315 NOT_YET_IMPLEMENTED();
319 const std::string& robotName,
const std::map<std::string, float>& angles)
321 NOT_YET_IMPLEMENTED();
325 const std::string& robotName,
const std::map<std::string, float>& velocities)
327 NOT_YET_IMPLEMENTED();
331 const std::string& robotName,
const std::map<std::string, float>& torques)
333 NOT_YET_IMPLEMENTED();
338 const std::string& robotName,
const std::string& robotNodeName,
339 const Eigen::Vector3f& force)
341 NOT_YET_IMPLEMENTED();
345 const std::string& robotName,
const std::string& robotNodeName,
346 const Eigen::Vector3f& torque)
348 NOT_YET_IMPLEMENTED();
353 const std::string& objectName,
const Eigen::Vector3f& force)
355 NOT_YET_IMPLEMENTED();
359 const std::string& objectName,
const Eigen::Vector3f& torque)
361 NOT_YET_IMPLEMENTED();
366 const std::string& robotName)
368 NOT_YET_IMPLEMENTED();
373 const std::string& robotName,
const std::string& nodeName)
375 NOT_YET_IMPLEMENTED();
381 const std::string& robotName)
383 NOT_YET_IMPLEMENTED();
388 const std::string& robotName,
const std::string& nodeName)
390 NOT_YET_IMPLEMENTED();
396 const std::string& robotName)
398 NOT_YET_IMPLEMENTED();
403 const std::string& robotName)
405 NOT_YET_IMPLEMENTED();
412 const std::string& objectName)
414 NOT_YET_IMPLEMENTED();
421 NOT_YET_IMPLEMENTED();
426 const std::string& robotName)
434 NOT_YET_IMPLEMENTED();
439 const std::string& robotName,
const std::string& robotNodeName)
441 NOT_YET_IMPLEMENTED();
446 const std::string& robotName,
const std::string& nodeName)
448 NOT_YET_IMPLEMENTED();
453 const std::string& robotName,
const std::string& nodeName)
455 NOT_YET_IMPLEMENTED();
461 const std::string& robotName,
const std::string& robotNodeName,
const Eigen::Vector3f& vel)
463 NOT_YET_IMPLEMENTED();
467 const std::string& robotName,
const std::string& robotNodeName,
const Eigen::Vector3f& vel)
469 NOT_YET_IMPLEMENTED();
474 const std::string& robotName,
const std::string& robotNodeName,
const Eigen::Vector3f& vel)
476 NOT_YET_IMPLEMENTED();
480 const std::string& robotName,
const std::string& robotNodeName,
const Eigen::Vector3f& vel)
482 NOT_YET_IMPLEMENTED();
489 return objects.find(instanceName) != objects.end();
496 return robots.find(robotName) != robots.end();
502 return hasRobot(robotName) &&
getRobot(robotName)->hasRobotNode(robotNodeName);
509 std::vector<VirtualRobot::SceneObjectPtr> sceneObjects;
510 std::transform(objects.begin(), objects.end(), std::back_inserter(sceneObjects),
511 [](
const auto & item)
513 return item.second.sceneObject;
522 return robots.at(robotName).robot;
528 std::map<std::string, VirtualRobot::RobotPtr> res;
529 for (
const auto& item : robots)
531 res[item.first] = item.second.robot;
538 const std::string& robotName,
const std::string& nodeName)
540 NOT_YET_IMPLEMENTED();
545 const std::string& robotName,
const std::string& nodeName)
547 NOT_YET_IMPLEMENTED();
553 const std::string& robotName,
const std::string& nodeName)
555 NOT_YET_IMPLEMENTED();
560 const std::string& robotName,
const std::string& nodeName,
float maxTorque)
562 NOT_YET_IMPLEMENTED();
568 NOT_YET_IMPLEMENTED();
574 const std::string& robotName,
const std::string& robotNodeName1,
575 const std::string& robotNodeName2)
577 NOT_YET_IMPLEMENTED();
582 const std::string& robotName,
const std::string& robotNodeName,
583 const std::string& worldObjectName)
585 NOT_YET_IMPLEMENTED();
595 std::vector<SimDynamics::DynamicsEngine::DynamicsContactInfo>
copy;
597 for (
const mjContact& contact : contacts)
599 SimDynamics::DynamicsEngine::DynamicsContactInfo info;
600 info.distance = lengthScaling.
meterToMilli(contact.dist);
601 info.objectAName = sim.model().id2nameGeom(contact.geom1);
602 info.objectBName = sim.model().id2nameGeom(contact.geom2);
604 Eigen::Vector3f pos = mujoco::utils::toVec3(contact.pos);
605 Eigen::Vector3f normalOnB = mujoco::utils::toVec3(contact.frame);
607 info.normalGlobalB = normalOnB;
608 info.posGlobalA = pos +
static_cast<float>(contact.dist / 2) * normalOnB;
609 info.posGlobalB = pos -
static_cast<float>(contact.dist / 2) * normalOnB;
611 info.posGlobalA = lengthScaling.
meterToMilli(info.posGlobalA);
612 info.posGlobalB = lengthScaling.
meterToMilli(info.posGlobalB);
614 info.combinedFriction = contact.friction[0];
615 copy.push_back(info);
624 const std::string& frameName)
626 NOT_YET_IMPLEMENTED();
632 const std::string& objectName, VirtualRobot::SceneObject::Physics::SimulationType simType)
634 NOT_YET_IMPLEMENTED();
639 const std::string& robotName,
const std::string& robotNodeName,
640 VirtualRobot::SceneObject::Physics::SimulationType simType)
642 NOT_YET_IMPLEMENTED();
656 const std::string& robotName,
const std::string& robotNodeName,
659 NOT_YET_IMPLEMENTED();
664 const std::string& robotName,
const std::string& robotNodeName,
665 const std::string& objectName)
667 NOT_YET_IMPLEMENTED();
690 for (
int i = 0; i < sim.data()->ncon; ++i)
692 contacts.push_back(sim.data()->contact[i]);
701 return static_cast<int>(contacts.size());
716 for (
auto& item : objects)
720 if (
object.body.id() >= 0 &&
object.sceneObject && sim.data())
727 bool objectFound =
false;
729 for (ObjectVisuData& visuData :
simVisuData.objects)
731 if (visuData.name == sceneObject->getName())
735 visuData.updated =
true;
742 ARMARX_WARNING <<
"Object '" << sceneObject->getName() <<
"' not in synchronized list.";
752 std::map<std::string, PoseBasePtr>& poseMap)
761 poseMap[sceneObject->getName()] =
new Pose(sceneObject->getGlobalPose());
776 const std::string& robotName,
777 std::map<std::string, PoseBasePtr>& objMap)
787 ARMARX_ERROR <<
"Robot '" << robotName <<
"' does not exist in simulation.";
793 for (
const std::string& nodeName : robot.
robot->getRobotNodeNames())
795 const int bodyID = sim.model().name2idBody(nodeName);
796 objMap[nodeName] =
PosePtr(
new Pose(sim.data().getBodyPose(bodyID)));
803 const std::string& robotName,
807 Eigen::Vector3f& linearVelocity,
808 Eigen::Vector3f& angularVelocity)
814 for (
const auto& node : robot.
robot->getConfig()->getNodes())
816 const std::string& nodeName = node->getName();
818 node->isRotationalJoint();
819 const int jointID = sim.model().name2id(mjtObj::mjOBJ_JOINT, nodeName);
821 jointAngles[nodeName] = sim.data().getJointValue1D(jointID);
824 const int actuatorID = sim.model().name2id(mjtObj::mjOBJ_ACTUATOR, nodeName);
825 jointTorques[nodeName] = sim.data().getActivation(actuatorID);
836 NOT_YET_IMPLEMENTED();
841 VirtualRobot::ObstaclePtr MujocoPhysicsWorld::makeFloorObject(
842 mujoco::Model& model,
const mujoco::SimGeom& floorGeom)
const
844 Eigen::Vector3f size = lengthScaling.
meterToMilli(model.getGeomSize(floorGeom));
846 VirtualRobot::ObstaclePtr floorObject = VirtualRobot::Obstacle::createBox(
847 size.x(), size.y(), 500,
848 VirtualRobot::VisualizationFactory::Color::Gray());
850 floorObject->setName(FLOOR_NAME);
851 floorObject->getVisualization();
852 floorObject->setSimulationType(VirtualRobot::SceneObject::Physics::eStatic);
857 VirtualRobot::mujoco::RobotMjcf MujocoPhysicsWorld::makeRobotMjcfModel(
const VirtualRobot::RobotPtr& robot)
const
859 VirtualRobot::mujoco::RobotMjcf mjcf(robot);
862 mjcf.setUseRelativePaths(
false);
864 mjcf.setLengthScale(0.001f);
866 mjcf.setOutputFile(TEMP_DIR / (robot->getName() +
".xml"));
867 mjcf.setOutputMeshRelativeDirectory(TEMP_MESH_DIR_REL / robot->getName());
869 mjcf.build(VirtualRobot::mujoco::WorldMountMode::FREE,
870 VirtualRobot::mujoco::ActuatorType::MOTOR);
873 mjcf::SensorSection sensors = mjcf.getDocument().sensor();
876 mjcf::VelocimeterSensor velocimeter = sensors.addChild<mjcf::VelocimeterSensor>();
885 void MujocoPhysicsWorld::reloadModel(
bool request)
888 fs::create_directory(TEMP_DIR);
889 ARMARX_INFO <<
"Saving temporary model file and requesting reload.\n "
891 mjcfDocument.saveFile(TEMP_MODEL_FILE);
895 sim.loadModelRequest(TEMP_MODEL_FILE);
899 sim.loadModel(TEMP_MODEL_FILE);