25#ifdef MUJOCO_PHYSICS_WORLD
31#include <VirtualRobot/math/Helpers.h>
36#include <MujocoX/libraries/Simulation/utils/eigen_conversion.h>
39namespace 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)
110 simMjcf.includeBaseFile(BASE_MJCF_FILENAME, TEMP_DIR);
111 simMjcf.addObjectDefaults(OBJECT_CLASS_NAME);
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;
138 floor.sceneObject = makeFloorObject(model, floor.geom);
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;
194 std::transform(obstacles.begin(),
196 std::back_inserter(result),
197 [](
const auto& item) { return item.first; });
201 std::vector<std::string>
205 std::vector<std::string>
names;
206 std::transform(robots.begin(),
208 std::back_inserter(names),
209 [](
const auto& item) { return item.first; });
217 simMjcf.addFloor(enable, floorTexture, FLOOR_NAME, 20);
218 this->floorTextureFile = floorTexture;
223 VirtualRobot::SceneObjectPtr
object,
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();
253 const std::string& filename,
258 ARMARX_IMPORTANT <<
"Adding robot " << robot->getName() <<
"\n- filename: \t" << filename
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.";
288 mujoco::SimRobot simRobot(robot);
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();
421 const Eigen::Matrix4f& globalPose)
423 NOT_YET_IMPLEMENTED();
434 const Eigen::Matrix4f& globalPose)
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;
521 std::transform(objects.begin(),
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,
667 Eigen::Matrix4f& storeLocalTransform)
669 NOT_YET_IMPLEMENTED();
675 const std::string& robotNodeName,
676 const std::string& objectName)
678 NOT_YET_IMPLEMENTED();
682 VirtualRobot::SceneObjectPtr
687 if (floor.sceneObject && sim.data())
689 floor.updateSceneObjectPose(sim.data());
691 return floor.sceneObject;
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)
733 mujoco::SimObject&
object = item.second;
735 if (
object.body.id() >= 0 &&
object.sceneObject && sim.data())
737 object.updateSceneObjectPose(sim.data(), lengthScaling.meterToMilli());
740 VirtualRobot::SceneObjectPtr sceneObject =
object.sceneObject;
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());
778 for (VirtualRobot::SceneObjectPtr& child : sceneObject->getChildren())
791 std::map<std::string, PoseBasePtr>& objMap)
801 ARMARX_ERROR <<
"Robot '" << robotName <<
"' does not exist in simulation.";
805 mujoco::SimRobot& robot = robots.at(robotName);
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)));
818 NameValueMap& jointAngles,
819 NameValueMap& jointVelocities,
820 NameValueMap& jointTorques,
821 Eigen::Vector3f& linearVelocity,
822 Eigen::Vector3f& angularVelocity)
826 mujoco::SimRobot& robot = robots.at(robotName);
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);
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.
void setTag(const LogTag &tag)
virtual bool removeObstacleEngine(const std::string &name) override
virtual ForceTorqueDataSeq getRobotForceTorqueSensors(const std::string &robotName) override
virtual bool objectReleasedEngine(const std::string &robotName, const std::string &robotNodeName, const std::string &objectName) override
remove a joint
virtual float getRobotJointVelocity(const std::string &robotName, const std::string &nodeName) override
virtual void applyTorqueRobotNode(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &torque) override
virtual bool synchronizeSceneObjectPoses(VirtualRobot::SceneObjectPtr currentObjEngine, std::map< std::string, PoseBasePtr > &objMap) override
virtual void setupFloorEngine(bool enable, const std::string &floorTexture) override
virtual void stepPhysicsFixedTimeStep() override
Perform one simulation step.
virtual bool hasObject(const std::string &instanceName) override
virtual VirtualRobot::SceneObjectPtr getFloor() override
virtual void setRobotPose(const std::string &robotName, const Eigen::Matrix4f &globalPose) override
virtual VirtualRobot::RobotPtr getRobot(const std::string &robotName) override
virtual void setRobotNodeSimType(const std::string &robotName, const std::string &robotNodeName, VirtualRobot::SceneObject::Physics::SimulationType simType) override
virtual void setRobotAngularVelocity(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
virtual float getRobotMass(const std::string &robotName) override
virtual bool addObstacleEngine(VirtualRobot::SceneObjectPtr o, VirtualRobot::SceneObject::Physics::SimulationType simType) override
virtual bool getRobotStatus(const std::string &robotName, NameValueMap &jointAngles, NameValueMap &jointVelocities, NameValueMap &jointTorques, Eigen::Vector3f &linearVelocity, Eigen::Vector3f &angularVelocity) override
virtual bool objectGraspedEngine(const std::string &robotName, const std::string &robotNodeName, const std::string &objectName, Eigen::Matrix4f &storeLocalTransform) override
create a joint
virtual std::vector< std::string > getObstacleNames() override
virtual void applyForceObject(const std::string &objectName, const Eigen::Vector3f &force) override
virtual void applyForceRobotNode(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &force) override
virtual std::vector< VirtualRobot::SceneObjectPtr > getObjects() override
virtual void onLoadModel(mujoco::Model &model) override
Sets time step and fetches entity IDs.
virtual void setRobotLinearVelocity(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
virtual Eigen::Vector3f getRobotLinearVelocity(const std::string &robotName, const std::string &nodeName) override
virtual float getRobotMaxTorque(const std::string &robotName, const std::string &nodeName) override
virtual void setObjectSimType(const std::string &objectName, VirtualRobot::SceneObject::Physics::SimulationType simType) override
virtual std::vector< std::string > getRobotNames() override
virtual void stepPhysicsRealTime() override
Perform one simulation step.
virtual int getFixedTimeStepMS() override
virtual int getContactCount() override
virtual void setRobotAngularVelocityRobotRootFrame(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
void initialize(int stepTimeMs, bool floorEnabled, const std::string &floorTexture)
Initialize *this.
virtual void actuateRobotJointsTorque(const std::string &robotName, const std::map< std::string, float > &torques) override
virtual void actuateRobotJointsVel(const std::string &robotName, const std::map< std::string, float > &velocities) override
virtual void setRobotLinearVelocityRobotRootFrame(const std::string &robotName, const std::string &robotNodeName, const Eigen::Vector3f &vel) override
virtual bool hasRobot(const std::string &robotName) override
virtual float getRobotJointLimitLo(const std::string &robotName, const std::string &nodeName) override
virtual std::map< std::string, float > getRobotJointVelocities(const std::string &robotName) override
virtual bool removeRobotEngine(const std::string &robotName) override
virtual Eigen::Matrix4f getObjectPose(const std::string &objectName) override
virtual DistanceInfo getDistance(const std::string &robotName, const std::string &robotNodeName, const std::string &worldObjectName) override
virtual bool synchronizeRobotNodePoses(const std::string &robotName, std::map< std::string, PoseBasePtr > &objMap) override
virtual float getRobotJointAngle(const std::string &robotName, const std::string &nodeName) override
virtual void actuateRobotJointsPos(const std::string &robotName, const std::map< std::string, float > &angles) override
virtual std::map< std::string, VirtualRobot::RobotPtr > getRobots() override
virtual std::map< std::string, float > getRobotJointTorques(const std::string &robotName) override
virtual bool synchronizeObjects() override
virtual Eigen::Matrix4f getRobotPose(const std::string &robotName) override
virtual DistanceInfo getRobotNodeDistance(const std::string &robotName, const std::string &robotNodeName1, const std::string &robotNodeName2) override
virtual std::vector< SimDynamics::DynamicsEngine::DynamicsContactInfo > copyContacts() override
virtual void actuateRobotJoints(const std::string &robotName, const std::map< std::string, float > &angles, const std::map< std::string, float > &velocities) override
virtual bool addRobotEngine(VirtualRobot::RobotPtr robot, double pid_p, double pid_i, double pid_d, const std::string &filename, bool staticRobot, bool selfCollisions) override
virtual FramedPosePtr toFramedPose(const Eigen::Matrix4f &globalPose, const std::string &robotName, const std::string &frameName) override
toFramedPose Constructs a framed pose
virtual void onMakeData(mujoco::Model &model, mujoco::Data &data) override
virtual bool updateForceTorqueSensor(ForceTorqueInfo &ftInfo) override
virtual void setRobotMaxTorque(const std::string &robotName, const std::string &nodeName, float maxTorque) override
virtual Eigen::Matrix4f getRobotNodePose(const std::string &robotName, const std::string &robotNodeName) override
virtual bool synchronizeSimulationDataEngine() override
According to other SimulatedWorlds, this method's only job is to update contacts.
virtual Eigen::Vector3f getRobotAngularVelocity(const std::string &robotName, const std::string &nodeName) override
virtual void setObjectPose(const std::string &objectName, const Eigen::Matrix4f &globalPose) override
virtual void applyTorqueObject(const std::string &objectName, const Eigen::Vector3f &torque) override
virtual float getRobotJointLimitHi(const std::string &robotName, const std::string &nodeName) override
virtual bool hasRobotNode(const std::string &robotName, const std::string &robotNodeName) override
virtual std::map< std::string, float > getRobotJointAngles(const std::string &robotName) override
SceneVisuData simVisuData
virtual ScopedRecursiveLockPtr getScopedSyncLock(const std::string &callStr)
virtual ScopedRecursiveLockPtr getScopedEngineLock(const std::string &callStr)
std::shared_ptr< ScopedRecursiveLock > ScopedRecursiveLockPtr
VirtualRobot::RobotPtr robot
The VirtualRobot robot.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
std::shared_ptr< class Robot > RobotPtr
const KinematicUnitDatafieldCreator jointVelocities("jointVelocities")
const KinematicUnitDatafieldCreator jointAngles("jointAngles")
const KinematicUnitDatafieldCreator jointTorques("jointTorques")
const simox::meta::IntEnumNames names
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< Pose > PosePtr
IceInternal::Handle< FramedPose > FramedPosePtr