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;
46 FunctionLogger(
const std::string& functionName) : functionName(functionName)
56 std::string functionName;
63 #define NOT_YET_IMPLEMENTED() throw exceptions::user::NotImplementedYetException(__FUNCTION__)
67 #define NOT_YET_IMPLEMENTED() ARMARX_WARNING << "Not implemented: \t" << __FUNCTION__ << "()"
72 #define DO_LOG_FUNCTIONS
73 #ifdef DO_LOG_FUNCTIONS
74 #define LOG_FUNCTION() const FunctionLogger __functionLogger__(__FUNCTION__)
76 #define LOG_FUNCTION() (void)0
82 const fs::path MujocoPhysicsWorld::BASE_MJCF_FILENAME =
83 "ArmarXSimulation/mujoco_base_model.xml";
85 const fs::path MujocoPhysicsWorld::TEMP_DIR = fs::temp_directory_path() /
"MujocoSimulation";
87 const fs::path MujocoPhysicsWorld::TEMP_MODEL_FILE = TEMP_DIR /
"SimulationModel.xml";
89 const fs::path MujocoPhysicsWorld::TEMP_MESH_DIR_REL =
"meshes";
90 const fs::path MujocoPhysicsWorld::TEMP_MESH_DIR = TEMP_DIR / TEMP_MESH_DIR_REL;
92 const std::string MujocoPhysicsWorld::FLOOR_NAME =
"floor";
93 const std::string MujocoPhysicsWorld::OBJECT_CLASS_NAME =
"object";
100 sim.addCallbackListener(*
this);
106 const std::string& floorTexture)
113 fixedTimeStep = std::chrono::milliseconds(stepTimeMs);
114 simMjcf.
setTimeStep(fixedTimeStep.count() / 1000.f);
118 ARMARX_VERBOSE <<
"Activating MuJoCo ... with key file " << MUJOCO_KEY_FILE;
119 mujoco::MujocoSim::ensureActivated(MUJOCO_KEY_FILE);
123 sim.simLoopPrepare();
133 model->opt.timestep = fixedTimeStep.count() / 1000.0;
140 for (
auto& objectItem : objects)
142 objectItem.second.update(model);
150 (void)model, (
void)
data;
156 NOT_YET_IMPLEMENTED();
166 sim.handleLoadRequest();
168 auto start = std::chrono::system_clock::now();
177 std::chrono::milliseconds sleepTime = std::chrono::duration_cast<std::chrono::milliseconds>(
178 end - std::chrono::system_clock::now());
180 std::this_thread::sleep_until(end);
186 return static_cast<int>(sim.model()->opt.timestep * 1000);
189 std::vector<std::string>
193 std::vector<std::string> result;
196 std::back_inserter(result),
197 [](
const auto& item) { return item.first; });
201 std::vector<std::string>
205 std::vector<std::string>
names;
208 std::back_inserter(
names),
209 [](
const auto& item) { return item.first; });
217 simMjcf.
addFloor(enable, floorTexture, FLOOR_NAME, 20);
218 this->floorTextureFile = floorTexture;
224 VirtualRobot::SceneObject::Physics::SimulationType simType)
227 simMjcf.
addObject(
object, simType, OBJECT_CLASS_NAME, TEMP_MESH_DIR);
228 obstacles[
object->getName()] = object;
237 NOT_YET_IMPLEMENTED();
244 NOT_YET_IMPLEMENTED();
259 <<
"\n- (p, i, d): \t(" << pid_p <<
" " << pid_i <<
" " << pid_d <<
")"
260 <<
"\n- static: \t" << staticRobot <<
"\n- self coll.: \t"
266 if (!sim.isModelLoaded())
273 ARMARX_ERROR <<
"More than one robot with identical name is currently not supported.";
279 ARMARX_ERROR <<
"Static robots are currently not supported.";
290 simRobot.mjcf = makeRobotMjcfModel(robot);
293 const fs::path robotModelFile =
297 mjcfDocument.addInclude(robotModelFile);
300 robots[robot->getName()] = std::move(simRobot);
311 const std::map<std::string, float>& angles,
312 const std::map<std::string, float>& velocities)
314 NOT_YET_IMPLEMENTED();
319 const std::map<std::string, float>& angles)
321 NOT_YET_IMPLEMENTED();
326 const std::map<std::string, float>& velocities)
328 NOT_YET_IMPLEMENTED();
333 const std::map<std::string, float>& torques)
335 NOT_YET_IMPLEMENTED();
340 const std::string& robotNodeName,
341 const Eigen::Vector3f& force)
343 NOT_YET_IMPLEMENTED();
348 const std::string& robotNodeName,
349 const Eigen::Vector3f& torque)
351 NOT_YET_IMPLEMENTED();
356 const Eigen::Vector3f& force)
358 NOT_YET_IMPLEMENTED();
363 const Eigen::Vector3f& torque)
365 NOT_YET_IMPLEMENTED();
368 std::map<std::string, float>
371 NOT_YET_IMPLEMENTED();
377 const std::string& nodeName)
379 NOT_YET_IMPLEMENTED();
383 std::map<std::string, float>
386 NOT_YET_IMPLEMENTED();
392 const std::string& nodeName)
394 NOT_YET_IMPLEMENTED();
398 std::map<std::string, float>
401 NOT_YET_IMPLEMENTED();
408 NOT_YET_IMPLEMENTED();
415 NOT_YET_IMPLEMENTED();
423 NOT_YET_IMPLEMENTED();
436 NOT_YET_IMPLEMENTED();
441 const std::string& robotNodeName)
443 NOT_YET_IMPLEMENTED();
449 const std::string& nodeName)
451 NOT_YET_IMPLEMENTED();
457 const std::string& nodeName)
459 NOT_YET_IMPLEMENTED();
465 const std::string& robotNodeName,
466 const Eigen::Vector3f& vel)
468 NOT_YET_IMPLEMENTED();
473 const std::string& robotNodeName,
474 const Eigen::Vector3f& vel)
476 NOT_YET_IMPLEMENTED();
481 const std::string& robotNodeName,
482 const Eigen::Vector3f& vel)
484 NOT_YET_IMPLEMENTED();
489 const std::string& robotNodeName,
490 const Eigen::Vector3f& vel)
492 NOT_YET_IMPLEMENTED();
499 return objects.find(instanceName) != objects.end();
506 return robots.find(robotName) != robots.end();
513 return hasRobot(robotName) &&
getRobot(robotName)->hasRobotNode(robotNodeName);
516 std::vector<VirtualRobot::SceneObjectPtr>
520 std::vector<VirtualRobot::SceneObjectPtr> sceneObjects;
523 std::back_inserter(sceneObjects),
524 [](
const auto& item) { return item.second.sceneObject; });
532 return robots.at(robotName).robot;
535 std::map<std::string, VirtualRobot::RobotPtr>
539 std::map<std::string, VirtualRobot::RobotPtr> res;
540 for (
const auto& item : robots)
542 res[item.first] = item.second.robot;
549 const std::string& nodeName)
551 NOT_YET_IMPLEMENTED();
557 const std::string& nodeName)
559 NOT_YET_IMPLEMENTED();
566 NOT_YET_IMPLEMENTED();
572 const std::string& nodeName,
575 NOT_YET_IMPLEMENTED();
581 NOT_YET_IMPLEMENTED();
587 const std::string& robotNodeName1,
588 const std::string& robotNodeName2)
590 NOT_YET_IMPLEMENTED();
596 const std::string& robotNodeName,
597 const std::string& worldObjectName)
599 NOT_YET_IMPLEMENTED();
603 std::vector<SimDynamics::DynamicsEngine::DynamicsContactInfo>
609 std::vector<SimDynamics::DynamicsEngine::DynamicsContactInfo>
copy;
611 for (
const mjContact& contact : contacts)
613 SimDynamics::DynamicsEngine::DynamicsContactInfo info;
614 info.distance = lengthScaling.
meterToMilli(contact.dist);
615 info.objectAName = sim.model().id2nameGeom(contact.geom1);
616 info.objectBName = sim.model().id2nameGeom(contact.geom2);
618 Eigen::Vector3f pos = mujoco::utils::toVec3(contact.pos);
619 Eigen::Vector3f normalOnB = mujoco::utils::toVec3(contact.frame);
621 info.normalGlobalB = normalOnB;
622 info.posGlobalA = pos +
static_cast<float>(contact.dist / 2) * normalOnB;
623 info.posGlobalB = pos -
static_cast<float>(contact.dist / 2) * normalOnB;
625 info.posGlobalA = lengthScaling.
meterToMilli(info.posGlobalA);
626 info.posGlobalB = lengthScaling.
meterToMilli(info.posGlobalB);
628 info.combinedFriction = contact.friction[0];
629 copy.push_back(info);
637 const std::string& robotName,
638 const std::string& frameName)
640 NOT_YET_IMPLEMENTED();
646 VirtualRobot::SceneObject::Physics::SimulationType simType)
648 NOT_YET_IMPLEMENTED();
653 const std::string& robotName,
654 const std::string& robotNodeName,
655 VirtualRobot::SceneObject::Physics::SimulationType simType)
657 NOT_YET_IMPLEMENTED();
665 const std::string& robotNodeName,
666 const std::string& objectName,
669 NOT_YET_IMPLEMENTED();
675 const std::string& robotNodeName,
676 const std::string& objectName)
678 NOT_YET_IMPLEMENTED();
703 for (
int i = 0; i < sim.data()->ncon; ++i)
705 contacts.push_back(sim.data()->contact[i]);
715 return static_cast<int>(contacts.size());
731 for (
auto& item : objects)
735 if (
object.body.id() >= 0 &&
object.sceneObject && sim.data())
742 bool objectFound =
false;
744 for (ObjectVisuData& visuData :
simVisuData.objects)
746 if (visuData.name == sceneObject->getName())
750 visuData.updated =
true;
758 <<
"' not in synchronized list.";
767 std::map<std::string, PoseBasePtr>& poseMap)
776 poseMap[sceneObject->getName()] =
new Pose(sceneObject->getGlobalPose());
791 std::map<std::string, PoseBasePtr>& objMap)
801 ARMARX_ERROR <<
"Robot '" << robotName <<
"' does not exist in simulation.";
807 for (
const std::string& nodeName : robot.
robot->getRobotNodeNames())
809 const int bodyID = sim.model().name2idBody(nodeName);
810 objMap[nodeName] =
PosePtr(
new Pose(sim.data().getBodyPose(bodyID)));
821 Eigen::Vector3f& linearVelocity,
822 Eigen::Vector3f& angularVelocity)
828 for (
const auto& node : robot.
robot->getConfig()->getNodes())
830 const std::string& nodeName = node->getName();
832 node->isRotationalJoint();
833 const int jointID = sim.model().name2id(mjtObj::mjOBJ_JOINT, nodeName);
835 jointAngles[nodeName] = sim.data().getJointValue1D(jointID);
838 const int actuatorID = sim.model().name2id(mjtObj::mjOBJ_ACTUATOR, nodeName);
839 jointTorques[nodeName] = sim.data().getActivation(actuatorID);
849 NOT_YET_IMPLEMENTED();
853 VirtualRobot::ObstaclePtr
854 MujocoPhysicsWorld::makeFloorObject(mujoco::Model& model,
855 const mujoco::SimGeom& floorGeom)
const
857 Eigen::Vector3f size = lengthScaling.
meterToMilli(model.getGeomSize(floorGeom));
859 VirtualRobot::ObstaclePtr floorObject = VirtualRobot::Obstacle::createBox(
860 size.x(), size.y(), 500, VirtualRobot::VisualizationFactory::Color::Gray());
862 floorObject->setName(FLOOR_NAME);
863 floorObject->getVisualization();
864 floorObject->setSimulationType(VirtualRobot::SceneObject::Physics::eStatic);
869 VirtualRobot::mujoco::RobotMjcf
872 VirtualRobot::mujoco::RobotMjcf mjcf(robot);
875 mjcf.setUseRelativePaths(
false);
877 mjcf.setLengthScale(0.001f);
879 mjcf.setOutputFile(TEMP_DIR / (robot->getName() +
".xml"));
880 mjcf.setOutputMeshRelativeDirectory(TEMP_MESH_DIR_REL / robot->getName());
882 mjcf.build(VirtualRobot::mujoco::WorldMountMode::FREE,
883 VirtualRobot::mujoco::ActuatorType::MOTOR);
886 mjcf::SensorSection sensors = mjcf.getDocument().sensor();
889 mjcf::VelocimeterSensor velocimeter = sensors.addChild<mjcf::VelocimeterSensor>();
899 MujocoPhysicsWorld::reloadModel(
bool request)
902 fs::create_directory(TEMP_DIR);
903 ARMARX_INFO <<
"Saving temporary model file and requesting reload.\n " << TEMP_MODEL_FILE;
904 mjcfDocument.saveFile(TEMP_MODEL_FILE);
908 sim.loadModelRequest(TEMP_MODEL_FILE);
912 sim.loadModel(TEMP_MODEL_FILE);