27 #include <VirtualRobot/MathTools.h>
28 #include <VirtualRobot/XML/BaseIO.h>
29 #include <VirtualRobot/XML/RobotIO.h>
34 #define MAX_SIM_TIME_WARNING 25
38 #ifdef MUJOCO_PHYSICS_WORLD
42 #include <SimoxUtility/algorithm/string/string_tools.h>
43 #include <SimoxUtility/json.h>
44 #include <VirtualRobot/Scene.h>
45 #include <VirtualRobot/SceneObject.h>
46 #include <VirtualRobot/XML/ObjectIO.h>
47 #include <VirtualRobot/math/Helpers.h>
53 #include <RobotAPI/interface/core/GeometryBase.h>
65 #include <SimDynamics/DynamicsEngine/DynamicsObject.h>
66 #include <SimDynamics/DynamicsEngine/DynamicsRobot.h>
75 defineOptionalProperty<std::string>(
76 "SimoxSceneFileName",
"",
"Simox/VirtualRobot scene file name, e.g. myScene.xml");
77 defineOptionalProperty<bool>(
"FloorPlane",
true,
"Enable floor plane.");
78 defineOptionalProperty<std::string>(
"FloorTexture",
"",
"Texture file for floor.");
79 defineOptionalProperty<std::string>(
80 "LongtermMemory.SnapshotName",
"",
"Name of snapshot to load the scene")
81 .setCaseInsensitive(
true);
82 defineOptionalProperty<bool>(
83 "LoadSnapshotToWorkingMemory",
true,
"Load the snapshot also into the WorkingMemory");
84 defineOptionalProperty<bool>(
"LoadAgentsFromSnapshot",
86 "Also load the agents from the snapshot into the WorkingMemory");
88 defineOptionalProperty<std::string>(
89 "WorkingMemoryName",
"WorkingMemory",
"Name of WorkingMemory")
90 .setCaseInsensitive(
true);
91 defineOptionalProperty<std::string>(
92 "CommonStorageName",
"CommonStorage",
"Name of CommonStorage")
93 .setCaseInsensitive(
true);
94 defineOptionalProperty<std::string>(
95 "PriorKnowledgeName",
"PriorKnowledge",
"Name of PriorKnowledge")
96 .setCaseInsensitive(
true);
97 defineOptionalProperty<std::string>(
98 "LongtermMemoryName",
"LongtermMemory",
"Name of LongtermMemory")
99 .setCaseInsensitive(
true);
101 defineOptionalProperty<std::string>(
"Scene.ObjectPackage",
102 "PriorKnowledgeData",
103 "Package to search for object models."
104 "Used when loading scenes from JSON files.");
105 defineOptionalProperty<std::string>(
"Scene.Path",
107 "Path to one or multiple JSON scene file(s) to load.\n"
108 "Example: 'PriorKnowledgeData/scenes/MyScene.json'.\n"
109 "Multiple paths are separated by semicolons (';').\n"
110 "The package to load a scene from is automatically"
111 "extracted from its first path segment.");
113 defineOptionalProperty<SimulatorType>(
"SimulationType",
115 "Simulation type (Supported: Bullet, Kinematics, Mujoco)")
119 .setCaseInsensitive(
true);
129 defineOptionalProperty<std::string>(
130 "RobotFileName" + postfix,
132 "Simox/VirtualRobot robot file name, e.g. robot_model.xml");
133 defineOptionalProperty<std::string>(
134 "RobotInstanceName" + postfix,
"",
"Name of this robot instance");
135 defineOptionalProperty<bool>(
136 "RobotIsStatic" + postfix,
138 "A static robot does not move due to the physical environment (i.e. no gravity). \n"
139 "It is a static (but kinematic) object in the world.");
140 defineOptionalProperty<bool>(
"ReportRobotPose",
false,
"Report the global robot pose.");
141 defineOptionalProperty<bool>(
142 "RobotCollisionModel" + postfix,
false,
"Show the collision model of the robot.");
143 defineOptionalProperty<float>(
144 "InitialRobotPose.x" + postfix, 0.f,
"x component of initial robot position (mm)");
145 defineOptionalProperty<float>(
146 "InitialRobotPose.y" + postfix, 0.f,
"y component of initial robot position (mm)");
147 defineOptionalProperty<float>(
148 "InitialRobotPose.z" + postfix, 0.f,
"z component of initial robot position (mm)");
149 defineOptionalProperty<float>(
"InitialRobotPose.roll" + postfix,
151 "Initial robot pose: roll component of RPY angles (radian)");
152 defineOptionalProperty<float>(
"InitialRobotPose.pitch" + postfix,
154 "Initial robot pose: pitch component of RPY angles (radian)");
155 defineOptionalProperty<float>(
"InitialRobotPose.yaw" + postfix,
157 "Initial robot pose: yaw component of RPY angles (radian)");
158 defineOptionalProperty<std::string>(
159 "InitialRobotConfig" + postfix,
161 "Initial robot config as comma separated list (RobotNodeName:value)");
163 defineOptionalProperty<std::string>(
164 "InitialNamedRobotConfig" + postfix,
166 "Initial named robot config, e.g., `Home`.");
168 defineOptionalProperty<float>(
169 "RobotScaling" + postfix, 1.0f,
"Scaling of the robot (1 = no scaling).");
170 defineOptionalProperty<double>(
171 "RobotControllerPID.p" + postfix, 10.0,
"Setup robot controllers: PID paramter p.");
172 defineOptionalProperty<double>(
173 "RobotControllerPID.i" + postfix, 0.0,
"Setup robot controllers: PID paramter i.");
174 defineOptionalProperty<double>(
175 "RobotControllerPID.d" + postfix, 0.0,
"Setup robot controllers: PID paramter d.");
176 defineOptionalProperty<bool>(
177 "RobotSelfCollisions" + postfix,
179 "If false, the robot bodies will not collide with other bodies of this \n"
180 "robot but with all other bodies in the world. \n"
181 "If true, the robot bodies will collide with all other bodies \n"
182 "(This needs an accurately modelled robot model without self collisions \n"
183 "if the robot does not move.)");
185 defineOptionalProperty<int>(
186 "FixedTimeStepLoopNrSteps",
188 "The maximum number of internal simulation loops (fixed time step mode).\n"
189 "After max number of time steps, the remaining time is interpolated.");
190 defineOptionalProperty<int>(
191 "FixedTimeStepStepTimeMS",
193 "The simulation's internal timestep (fixed time step mode). \n"
194 "This property determines the precision of the simulation. \n"
195 "Needs to be set to bigger values for slow PCs, but the simulation results might be bad. "
196 "Smaller value for higher precision, but slower calculation.");
197 defineOptionalProperty<int>(
"StepTimeMS", 25,
"The simulation's time progress per step. ");
198 defineOptionalProperty<bool>(
201 "If true the timestep is adjusted to the computing power of the host and \n"
202 "the time progress in real time. Can result in bad results on slow PCs. \n"
203 "The property StepTimeMS has then no effect. FixedTimeStepStepTimeMS needs \n"
204 "to be adjusted if real time cannot be achieved on slower PCs.");
205 defineOptionalProperty<float>(
208 "If not zero and the real time mode is off, the simulator will not run \n"
209 "\tfaster than real-time * MaxRealTime even if the machine is fast enough \n"
210 "\t(a sleep is inserted to slow down the simulator - the precision remains unchanged).\n"
211 "\tIf set to 2, the simulator will not run faster than double speed. \n"
212 "\tIf set to 0.5, the simulator will not run faster than half speed. \n"
213 "\tIf set to 0, the simulator will run as fast as possible.\n");
215 defineOptionalProperty<bool>(
218 "Enable robot logging. If true, the complete robot state is logged to a file each step.");
220 defineOptionalProperty<int>(
"ReportVisuFrequency",
222 "How often should the visualization data be published. Value is "
223 "given in Hz. (0 to disable)");
224 defineOptionalProperty<std::string>(
225 "ReportVisuTopicName",
226 "SimulatorVisuUpdates",
227 "The topic on which the visualization updates are published.");
228 defineOptionalProperty<int>(
229 "ReportDataFrequency",
231 "How often should the robot data be published. Value is given in Hz. (0 to disable)");
232 defineOptionalProperty<std::string>(
235 "Fixate objects or parts of a robot in the world. Comma separated list. \n"
236 "Define objects by their name, robots can be defined with robotName:RobotNodeName");
237 defineOptionalProperty<bool>(
"DrawCoMVisu",
239 "If true the CoM of each robot is drawn as a circle on the ground "
240 "after each simulation cycle.");
282 std::string snapshotName = getProperty<std::string>(
"LongtermMemory.SnapshotName").getValue();
284 if (!snapshotName.empty())
286 ARMARX_LOG <<
"UsingProxy LongtermMemory for snapshot " << snapshotName;
287 usingProxy(getProperty<std::string>(
"WorkingMemoryName").getValue());
288 usingProxy(getProperty<std::string>(
"LongtermMemoryName").getValue());
289 usingProxy(getProperty<std::string>(
"CommonStorageName").getValue());
290 usingProxy(getProperty<std::string>(
"PriorKnowledgeName").getValue());
294 ARMARX_LOG <<
"Not using LongtermMemoryProxy";
297 bool floorPlane = getProperty<bool>(
"FloorPlane").getValue();
298 std::string floorTexture = getProperty<std::string>(
"FloorTexture");
303 simulatorType = getProperty<SimulatorType>(
"SimulationType");
313 const int stepTimeMs = getProperty<int>(
"StepTimeMS");
314 const float maxRealTime = getProperty<float>(
"MaxRealTime");
318 switch (simulatorType)
323 kw->initialize(stepTimeMs, maxRealTime, floorPlane, floorTexture);
329 int bulletFixedTimeStepMS = getProperty<int>(
"FixedTimeStepStepTimeMS").getValue();
330 int bulletFixedTimeStepMaxNrLoops =
331 getProperty<int>(
"FixedTimeStepLoopNrSteps").getValue();
333 bw->initialize(stepTimeMs,
334 bulletFixedTimeStepMS,
335 bulletFixedTimeStepMaxNrLoops,
344 #ifdef MUJOCO_PHYSICS_WORLD
348 mw->initialize(stepTimeMs, floorPlane, floorTexture);
352 ARMARX_ERROR <<
"Simulator type 'mujoco' is not supported, since simulator was built "
354 <<
"\nGet the package MujocoX from: https://gitlab.com/h2t/mujoco .";
367 Simulator::addRobotsFromProperties()
376 if (!getProperty<std::string>(
"RobotFileName" + postfix).isSet() ||
377 getProperty<std::string>(
"RobotFileName" + postfix).getValue().
empty())
382 std::string robotFile = getProperty<std::string>(
"RobotFileName" + postfix).getValue();
385 VirtualRobot::MathTools::rpy2eigen4f(
386 getProperty<float>(
"InitialRobotPose.roll" + postfix).
getValue(),
387 getProperty<float>(
"InitialRobotPose.pitch" + postfix).
getValue(),
388 getProperty<float>(
"InitialRobotPose.yaw" + postfix).
getValue(),
392 Eigen::Vector3f(getProperty<float>(
"InitialRobotPose.x" + postfix).
getValue(),
393 getProperty<float>(
"InitialRobotPose.y" + postfix).
getValue(),
394 getProperty<float>(
"InitialRobotPose.z" + postfix).
getValue());
397 std::map<std::string, float> initConfig;
399 if(getProperty<std::string>(
"InitialNamedRobotConfig" + postfix).isSet())
401 std::string confStr =
402 getProperty<std::string>(
"InitialNamedRobotConfig" + postfix).getValue();
407 std::string robFileGlobal = robotFile;
411 ARMARX_ERROR <<
"Could not find robot file " << robotFile;
414 const auto robot = VirtualRobot::RobotIO::loadRobot(robFileGlobal, VirtualRobot::BaseIO::eStructure);
417 const std::optional<std::map<std::string, float>> namedConfig =
418 robot->getConfiguration(confStr);
421 <<
"Could not find named robot config " <<
QUOTED(confStr) <<
" in robot file "
424 initConfig = namedConfig.value();
426 if (getProperty<std::string>(
"InitialRobotConfig" + postfix).isSet())
429 << getProperty<std::string>(
"InitialRobotConfig" + postfix).getValue()
430 <<
" because InitialNamedRobotConfig is set.";
434 else if (getProperty<std::string>(
"InitialRobotConfig" + postfix).isSet())
437 std::string confStr =
438 getProperty<std::string>(
"InitialRobotConfig" + postfix).getValue();
439 std::vector<std::string> confList =
Split(confStr,
",",
true,
true);
440 for (
auto& pos : confList)
443 std::vector<std::string> d =
Split(pos,
":",
true,
true);
449 std::string name = d.at(0);
451 initConfig[name] =
static_cast<float>(atof(d.at(1).c_str()));
452 ARMARX_INFO <<
"1:'" << name <<
"', 2:" << initConfig[name];
457 double pid_p = getProperty<double>(
"RobotControllerPID.p" + postfix).getValue();
458 double pid_i = getProperty<double>(
"RobotControllerPID.i" + postfix).getValue();
459 double pid_d = getProperty<double>(
"RobotControllerPID.d" + postfix).getValue();
461 std::string robotInstanceName =
462 getProperty<std::string>(
"RobotInstanceName" + postfix).getValue();
464 bool staticRobot = getProperty<bool>(
"RobotIsStatic" + postfix).getValue();
465 bool colModelRobot = getProperty<bool>(
"RobotCollisionModel" + postfix).getValue();
466 float scaling = getProperty<float>(
"RobotScaling" + postfix).getValue();
467 bool selfCollisions = getProperty<bool>(
"RobotSelfCollisions" + postfix);
468 if (!robotFile.empty())
470 std::string robFileGlobal = robotFile;
474 ARMARX_ERROR <<
"Could not find robot file " << robotFile;
478 ARMARX_INFO <<
"Adding robot with name '" << robotInstanceName <<
"' from file "
498 Simulator::addSceneFromFile(
const std::string& sceneFile)
503 ARMARX_ERROR <<
"Could not find scene file " << sceneFile;
515 Simulator::addSceneFromMemorySnapshot(
const std::string& snapshotName)
520 ARMARX_ERROR <<
"No connection to memory - cannot add snapshot!";
523 memoryPrx = getProxy<WorkingMemoryInterfacePrx>(
524 getProperty<std::string>(
"WorkingMemoryName").
getValue());
529 getProperty<std::string>(
"LongtermMemoryName").
getValue());
530 WorkingMemorySnapshotInterfacePrx snapshotInterfacePrx;
534 ARMARX_LOG <<
"Loading snapshot " << snapshotName;
538 snapshotInterfacePrx =
541 if (getProperty<bool>(
"LoadSnapshotToWorkingMemory").
getValue())
543 if (snapshotInterfacePrx)
549 ARMARX_ERROR <<
"Could not get snapshot segment from longterm memory...";
553 catch (memoryx::SnapshotNotFoundException&)
555 ARMARX_ERROR <<
"Could not find snapshot: " << snapshotName;
559 ARMARX_ERROR <<
"Failed to load snapshot with name:" << snapshotName;
564 ARMARX_ERROR <<
"Could not get PriorKnowledge/LongtermMemory/WorkingMemory Proxy";
569 ARMARX_LOG <<
"Found and opened snapshot " << snapshotName;
574 ARMARX_ERROR <<
"Failed to open snapshot " << snapshotName;
579 Simulator::addSceneFromSdfFile(
const std::string& scenePath)
583 if (!cmakeFinder.packageFound())
585 ARMARX_WARNING <<
"Could not find CMake package " << scenePackage <<
".";
589 std::filesystem::path dataDir = cmakeFinder.getDataDir();
590 std::filesystem::path path = dataDir / scenePath;
593 sdf::SDFPtr sdfFile(
new sdf::SDF());
596 std::filesystem::path modelDirectory = path.parent_path();
598 const std::string modelURI =
"model://";
600 auto findFileCallback = [
this, &modelURI](
const std::string& uri) -> std::string
602 std::stringstream ss;
603 ss <<
"Find '" << uri <<
"' ... -> ";
605 const std::string classIDStr = simox::alg::remove_prefix(uri, modelURI);
610 if (std::optional<PackageFileLocation> modelPath = info->getModel())
612 std::filesystem::path result = modelPath->absolutePath.parent_path();
626 parser.AddURIPath(modelURI, modelDirectory.string());
627 parser.SetFindCallback(findFileCallback);
630 sdf::Errors errors = root.Load(path.string(),
parser);
632 for (
auto const& error : errors)
643 if (root.WorldCount() == 0)
649 if (root.WorldCount() > 1)
655 sdf::World* world = root.WorldByIndex(0);
656 auto addSceneObject = [&](sdf::Model* model)
658 const std::string name = model->Name();
661 ARMARX_WARNING <<
"Object with name \"" << name <<
"\" already exists.";
665 const std::string uri = model->Uri();
668 ARMARX_WARNING <<
"No URI set for object \"" << name <<
"\" in SDF.";
674 const std::filesystem::path modelPath = findFileCallback(uri);
676 gz::math::Pose3d pose = model->RawPose();
678 const float meterToMillimeter = 1000.0F;
680 Eigen::Vector3f position;
681 position.x() =
static_cast<float>(pose.Pos().X() * meterToMillimeter);
682 position.y() =
static_cast<float>(pose.Pos().Y() * meterToMillimeter);
683 position.z() =
static_cast<float>(pose.Pos().Z() * meterToMillimeter);
686 orientation.x() =
static_cast<float>(pose.Rot().X());
687 orientation.y() =
static_cast<float>(pose.Rot().Y());
688 orientation.z() =
static_cast<float>(pose.Rot().Z());
689 orientation.w() =
static_cast<float>(pose.Rot().W());
691 auto isStatic = model->Static();
693 std::string robotFilename = modelPath.filename().generic_string() +
".urdf";
694 std::filesystem::path robotPath = modelPath / robotFilename;
696 std::string xmlFilename = modelPath.filename().generic_string() +
".xml";
697 std::filesystem::path xmlPath = modelPath / xmlFilename;
699 if (std::filesystem::exists(xmlPath))
701 ARMARX_INFO <<
"Loading object '" << name <<
"' from object XML file " << xmlPath;
702 VirtualRobot::ManipulationObjectPtr simoxObject =
703 VirtualRobot::ObjectIO::loadManipulationObject(xmlPath.string());
705 simoxObject->setGlobalPose(simox::math::pose(position, orientation));
707 VirtualRobot::SceneObject::Physics::SimulationType simType =
708 isStatic ? VirtualRobot::SceneObject::Physics::eKinematic
709 : VirtualRobot::SceneObject::Physics::eDynamic;
711 simoxObject->setSimulationType(simType);
712 simoxObject->setFilename(xmlPath.string());
713 simoxObject->setName(name);
716 simoxObject, simType, xmlPath.string(), name, {}, scenePackage);
718 else if (std::filesystem::exists(robotPath))
720 ARMARX_INFO <<
"Loading object '" << name <<
"' from robot URDF file " << xmlPath;
723 robot->setGlobalPose(simox::math::pose(position, orientation));
725 VirtualRobot::SceneObject::Physics::SimulationType simType =
726 isStatic ? VirtualRobot::SceneObject::Physics::eKinematic
727 : VirtualRobot::SceneObject::Physics::eDynamic;
729 robot->setSimulationType(simType);
730 robot->setFilename(robotPath.string());
731 robot->setName(name);
733 physicsWorld->addRobot(robot, 10.0, 0.0, 0.0, robotPath.string(), isStatic);
738 <<
"Not adding object '" << name
739 <<
"' because neither object XML nor robot URDF file exist. (Tried object XML = "
740 << xmlPath <<
" and robot URDF = " << robotPath <<
")";
746 addSceneObject(world->ModelByIndex(
index));
751 Simulator::addSceneFromJsonFile(
const std::string& scenePath)
753 std::string mutScenePath = scenePath;
756 mutScenePath +=
".json";
761 if (!cmakeFinder.packageFound())
763 ARMARX_WARNING <<
"Could not find CMake package " << scenePackage <<
".";
767 std::filesystem::path dataDir = cmakeFinder.getDataDir();
768 std::filesystem::path path = dataDir / scenePath;
773 scene = simox::json::read<armarx::objects::Scene>(path);
775 catch (
const simox::json::error::JsonError& e)
777 ARMARX_WARNING <<
"Loading scene snapshot failed: \n" << e.what();
781 std::map<ObjectID, int> idCounters;
782 for (
const auto&
object : scene.
objects)
790 addJsonSceneObject(
object, idCounters);
796 std::map<ObjectID, int>& idCounters)
799 const std::string name =
802 :
object.instanceName)
807 ARMARX_INFO <<
"Object with name \"" << name <<
"\" already exists.";
811 ARMARX_INFO <<
"Adding object with name \"" << name <<
"\" to scene.";
814 VirtualRobot::ManipulationObjectPtr simoxObject =
815 VirtualRobot::ObjectIO::loadManipulationObject(objectInfo->simoxXML().absolutePath);
816 simoxObject->setGlobalPose(simox::math::pose(
object.position,
object.orientation));
818 VirtualRobot::SceneObject::Physics::SimulationType simType;
819 if (
object.isStatic.has_value())
821 simType = *
object.isStatic ? VirtualRobot::SceneObject::Physics::eKinematic
822 : VirtualRobot::SceneObject::Physics::eDynamic;
826 simType = VirtualRobot::SceneObject::Physics::eKinematic;
830 simoxObject->setSimulationType(simType);
832 simoxObject->setName(name);
839 Simulator::fixateRobotNode(
const std::string& robotName,
const std::string& robotNodeName)
841 ARMARX_VERBOSE <<
"Fixing robot node" << robotName <<
"." << robotNodeName;
843 robotName, robotNodeName, VirtualRobot::SceneObject::Physics::eStatic);
847 Simulator::fixateObject(
const std::string& objectName)
850 physicsWorld->setObjectSimType(objectName, VirtualRobot::SceneObject::Physics::eStatic);
858 addRobotsFromProperties();
860 std::string sceneFile = getProperty<std::string>(
"SimoxSceneFileName").getValue();
861 if (!sceneFile.empty())
863 addSceneFromFile(sceneFile);
866 std::string snapshotName = getProperty<std::string>(
"LongtermMemory.SnapshotName").getValue();
867 if (!snapshotName.empty())
869 addSceneFromMemorySnapshot(snapshotName);
872 std::string objectPackage = getProperty<std::string>(
"Scene.ObjectPackage").getValue();
875 std::string scenePaths = getProperty<std::string>(
"Scene.Path").getValue();
876 if (!scenePaths.empty())
881 std::filesystem::path path = scenePath;
882 std::string sdfExtension =
".sdf";
884 if (path.has_extension() && path.extension().string() == sdfExtension)
886 ARMARX_INFO <<
"Loading scene from SDF file '" << scenePath <<
"' ...";
887 addSceneFromSdfFile(scenePath);
891 ARMARX_INFO <<
"Loading scene from JSON file '" << scenePath <<
"' ...";
892 addSceneFromJsonFile(scenePath);
898 std::string fixedObjects = getProperty<std::string>(
"FixedObjects").getValue();
899 if (!fixedObjects.empty())
901 std::vector<std::string> objects =
Split(fixedObjects,
",;");
902 for (
auto o : objects)
904 std::vector<std::string> rob =
Split(o,
":");
908 fixateRobotNode(rob.at(0), rob.at(1));
924 SimulatedRobotState state;
926 state.hasRobot =
true;
927 state.timestampInMicroSeconds =
timestamp.toMicroSeconds();
939 if (forceTorqueSensor.enable)
941 ForceTorqueData& ftData = state.forceTorqueValues.emplace_back();
942 ftData.force =
new Vector3(forceTorqueSensor.currentForce);
943 ftData.torque =
new Vector3(forceTorqueSensor.currentTorque);
944 ftData.sensorName = forceTorqueSensor.sensorName;
945 ftData.nodeName = forceTorqueSensor.robotNodeName;
958 <<
"Was able to find a reference to the CommonStorage. Continue with existing "
959 "connection to memory.";
962 CommonStorageInterfacePrx commonStoragePrx =
965 if (commonStoragePrx)
968 <<
"Was able to find a reference to the CommonStorage. Reset GridFSManager and "
969 "continue with memory.";
975 <<
"Could not get CommonStorage Proxy - continuing without memory";
988 entityDrawerPrx = getTopic<memoryx::EntityDrawerInterfacePrx>(
"DebugDrawerUpdates");
990 int hzVisu = getProperty<int>(
"ReportVisuFrequency").getValue();
991 int hzData = getProperty<int>(
"ReportDataFrequency").getValue();
992 std::string top = getProperty<std::string>(
"ReportVisuTopicName").getValue();
996 ARMARX_DEBUG <<
"Starting periodic simulation task in ArmarX Simulator";
998 timeTopicPrx = ManagedIceObject::getTopic<TimeServerListenerPrx>(TIME_TOPIC_NAME);
1001 ARMARX_DEBUG <<
"Starting periodic visualization report task in ArmarX Simulator";
1015 int cycleTime = 1000 / hzVisu;
1022 ARMARX_DEBUG <<
"Starting periodic data report task in ArmarX Simulator";
1031 int cycleTime = 1000 / hzData;
1094 IceUtil::ThreadControl threadControl = getThreadControl();
1099 threadControl.join();
1110 auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
1111 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
1147 const std::string segmentName =
"objectInstances";
1151 PersistentEntitySegmentBasePrx segInstances = snapshotInterfacePrx->getSegment(segmentName);
1155 ARMARX_ERROR <<
"Segment not found in snapshot: " << segmentName;
1160 PersistentObjectClassSegmentBasePrx classesSegmentPrx =
1163 if (!classesSegmentPrx)
1165 ARMARX_ERROR <<
"Classes Segment not found in PriorKnowledge";
1170 EntityIdList ids = segInstances->getAllEntityIds();
1174 for (EntityIdList::const_iterator it = ids.begin(); it != ids.end(); ++it)
1176 EntityBasePtr snapEntity = segInstances->getEntityById(*it);
1178 std::string
id = snapInstance->getId();
1179 bool ok = snapInstance->hasAttribute(
"classes");
1184 <<
" has no classes attribute, could not load iv files, skipping";
1188 std::string classesName = snapInstance->getAttributeValue(
"classes")->getString();
1190 EntityBasePtr classesEntity = classesSegmentPrx->getEntityByName(classesName);
1194 ARMARX_ERROR <<
"Classes Segment does not know class with name : " << classesName;
1198 ObjectClassPtr objectClass = ObjectClassPtr::dynamicCast(classesEntity);
1202 ARMARX_ERROR <<
"Could not cast class entity : " << classesName;
1214 m.block(0, 3, 3, 1) = objPos->toEigen();
1222 m.block(0, 0, 3, 3) = objOrient->toEigen();
1228 VirtualRobot::ManipulationObjectPtr mo = sw->getManipulationObject()->clone(
1229 sw->getManipulationObject()
1234 std::string instanceName = snapInstance->getName();
1238 instanceName = snapInstance->getName() +
"_" +
to_string(i);
1241 if (instanceName != snapInstance->getName())
1243 ARMARX_INFO <<
"Object instance with name '" << snapInstance->getName()
1244 <<
"'' already exists - using '" << instanceName <<
"'";
1247 mo->getSimulationType() == VirtualRobot::SceneObject::Physics::eStatic;
1248 addObject(objectClass, instanceName, poseGlobal, isStatic);
1259 if (getProperty<bool>(
"LoadAgentsFromSnapshot").getValue())
1272 const std::string segmentName =
"agentInstances";
1276 PersistentEntitySegmentBasePrx segInstances = snapshotInterfacePrx->getSegment(segmentName);
1280 ARMARX_ERROR <<
"Segment not found in snapshot: " << segmentName;
1284 EntityIdList ids = segInstances->getAllEntityIds();
1287 for (EntityIdList::const_iterator it = ids.begin(); it != ids.end(); ++it)
1289 EntityBasePtr snapEntity = segInstances->getEntityById(*it);
1292 auto agentName = snapAgent->getName();
1293 std::string agentModelFile = snapAgent->getAgentFilePath();
1294 std::string absModelFile;
1297 ARMARX_INFO <<
"Robot with name '" << agentName <<
"' already exists.";
1303 <<
"'- file not found: " << agentModelFile;
1309 if (
addRobot(agentName, absModelFile, snapAgent->getPose()->toEigen(), agentModelFile)
1328 const Ice::Current&)
1330 physicsWorld->actuateRobotJoints(robotName, angles, velocities);
1336 const Ice::Current&)
1338 physicsWorld->actuateRobotJointsPos(robotName, angles);
1344 const Ice::Current&)
1346 physicsWorld->actuateRobotJointsVel(robotName, velocities);
1352 const Ice::Current&)
1354 physicsWorld->actuateRobotJointsTorque(robotName, torques);
1359 const PoseBasePtr& globalPose,
1360 const Ice::Current&)
1363 qa.x = globalPose->orientation->qx;
1364 qa.y = globalPose->orientation->qy;
1365 qa.z = globalPose->orientation->qz;
1366 qa.w = globalPose->orientation->qw;
1368 gp(0, 3) = globalPose->position->x;
1369 gp(1, 3) = globalPose->position->y;
1370 gp(2, 3) = globalPose->position->z;
1376 const std::string& robotNodeName,
1377 const Vector3BasePtr& force,
1378 const Ice::Current&)
1380 Vector3Ptr v3p = Vector3Ptr::dynamicCast(force);
1381 physicsWorld->applyForceRobotNode(robotName, robotNodeName, v3p->toEigen());
1386 const std::string& robotNodeName,
1387 const Vector3BasePtr& torque,
1388 const Ice::Current&)
1390 Vector3Ptr v3p = Vector3Ptr::dynamicCast(torque);
1391 physicsWorld->applyTorqueRobotNode(robotName, robotNodeName, v3p->toEigen());
1396 const Vector3BasePtr& force,
1397 const Ice::Current&)
1399 Vector3Ptr v3p = Vector3Ptr::dynamicCast(force);
1400 physicsWorld->applyForceObject(objectName, v3p->toEigen());
1405 const Vector3BasePtr& torque,
1406 const Ice::Current&)
1408 Vector3Ptr v3p = Vector3Ptr::dynamicCast(torque);
1409 physicsWorld->applyTorqueObject(objectName, v3p->toEigen());
1414 const std::string& instanceName,
1415 const PoseBasePtr& globalPose,
1417 const Ice::Current&)
1422 ARMARX_WARNING <<
"Cannot add object - no connection to common storage";
1425 auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
1426 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
1431 ObjectClassPtr objectClass = ObjectClassPtr::dynamicCast(objectClassBase);
1435 ARMARX_ERROR <<
"Object with instance name \"" << instanceName <<
"\" already exists";
1441 ARMARX_ERROR <<
"Invalid object class; could not create object with instance name "
1449 VirtualRobot::ManipulationObjectPtr mo =
1450 sw->getManipulationObject();
1454 ARMARX_ERROR <<
"Could not retrieve manipulation object of object class "
1455 << objectClass->getName();
1462 mo->setName(instanceName);
1464 ARMARX_LOG <<
"Adding manipulation object " << mo->getName() <<
" of class "
1465 << objectClass->getName();
1469 qa.x = globalPose->orientation->qx;
1470 qa.y = globalPose->orientation->qy;
1471 qa.z = globalPose->orientation->qz;
1472 qa.w = globalPose->orientation->qw;
1474 gp(0, 3) = globalPose->position->x;
1475 gp(1, 3) = globalPose->position->y;
1476 gp(2, 3) = globalPose->position->z;
1477 mo->setGlobalPose(gp);
1478 VirtualRobot::SceneObject::Physics::SimulationType simType =
1479 (isStatic) ? VirtualRobot::SceneObject::Physics::eKinematic
1480 : VirtualRobot::SceneObject::Physics::eDynamic;
1481 physicsWorld->addObstacle(mo, simType, std::string(), objectClassBase->getName());
1491 const std::string& instanceName,
1492 const PoseBasePtr& globalPose,
1494 const Ice::Current&)
1496 ARMARX_INFO <<
"Add object from packagePath " << packagePath <<
": " << instanceName;
1502 auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
1503 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
1509 ARMARX_ERROR <<
"Could not find file: \"" << packagePath.path <<
"\".";
1519 ARMARX_ERROR <<
"Object with instance name \"" << instanceName <<
"\" already exists";
1524 VirtualRobot::ManipulationObjectPtr mo =
1525 VirtualRobot::ObjectIO::loadManipulationObject(
filename);
1536 mo->setName(instanceName);
1542 qa.x = globalPose->orientation->qx;
1543 qa.y = globalPose->orientation->qy;
1544 qa.z = globalPose->orientation->qz;
1545 qa.w = globalPose->orientation->qw;
1547 gp(0, 3) = globalPose->position->x;
1548 gp(1, 3) = globalPose->position->y;
1549 gp(2, 3) = globalPose->position->z;
1550 mo->setGlobalPose(gp);
1551 VirtualRobot::SceneObject::Physics::SimulationType simType =
1552 (isStatic) ? VirtualRobot::SceneObject::Physics::eKinematic
1553 : VirtualRobot::SceneObject::Physics::eDynamic;
1567 const DrawColor& color,
1568 const std::string& instanceName,
1569 const PoseBasePtr& globalPose,
1571 const Ice::Current&)
1575 auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
1576 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
1583 ARMARX_ERROR <<
"Object with instance name \"" << instanceName <<
"\" already exists";
1587 if (depth <= 0 || width <= 0 || height <= 0)
1589 ARMARX_ERROR <<
"Invalid properties; could not create object with instance name "
1598 c.transparency = color.a;
1599 VirtualRobot::ObstaclePtr o = VirtualRobot::Obstacle::createBox(width, height, depth,
c);
1609 o->setName(instanceName);
1611 ARMARX_LOG <<
"Adding box object " << o->getName();
1617 qa.x = globalPose->orientation->qx;
1618 qa.y = globalPose->orientation->qy;
1619 qa.z = globalPose->orientation->qz;
1620 qa.w = globalPose->orientation->qw;
1622 gp(0, 3) = globalPose->position->x;
1623 gp(1, 3) = globalPose->position->y;
1624 gp(2, 3) = globalPose->position->z;
1625 o->setGlobalPose(gp);
1626 VirtualRobot::SceneObject::Physics::SimulationType simType =
1627 (isStatic) ? VirtualRobot::SceneObject::Physics::eStatic
1628 : VirtualRobot::SceneObject::Physics::eDynamic;
1630 BoxVisuPrimitivePtr bp(
new BoxVisuPrimitive());
1633 bp->height = height;
1635 bp->massKG = massKG;
1638 physicsWorld->addObstacle(o, simType, std::string(), std::string(), bp);
1651 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
1660 auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
1661 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
1667 ARMARX_ERROR <<
"Object with instance name \"" << instanceName <<
"\" does not exist";
1671 ARMARX_LOG <<
"Removing object " << instanceName;
1675 ARMARX_ERROR <<
"Could not remove object with instance name \"" << instanceName <<
"\"";
1687 const PoseBasePtr& globalPose,
1688 const Ice::Current&)
1691 q.x = globalPose->orientation->qx;
1692 q.y = globalPose->orientation->qy;
1693 q.z = globalPose->orientation->qz;
1694 q.w = globalPose->orientation->qw;
1696 gp(0, 3) = globalPose->position->x;
1697 gp(1, 3) = globalPose->position->y;
1698 gp(2, 3) = globalPose->position->z;
1705 SimulationType type,
1706 const Ice::Current&)
1708 VirtualRobot::SceneObject::Physics::SimulationType st =
1709 VirtualRobot::SceneObject::Physics::eDynamic;
1710 if (type == armarx::Kinematic)
1712 st = VirtualRobot::SceneObject::Physics::eKinematic;
1714 ARMARX_DEBUG <<
"setting simulation type of " << objectName <<
" to " << st;
1744 const std::string& nodeName,
1745 const Ice::Current&)
1747 return physicsWorld->getRobotJointAngle(robotName, nodeName);
1753 return physicsWorld->getRobotJointVelocities(robotName);
1758 const std::string& nodeName,
1759 const Ice::Current&)
1761 return physicsWorld->getRobotJointVelocity(robotName, nodeName);
1773 return physicsWorld->getRobotForceTorqueSensors(robotName);
1778 const std::string& nodeName,
1779 const Ice::Current&)
1781 return physicsWorld->getRobotJointLimitLo(robotName, nodeName);
1786 const std::string& nodeName,
1787 const Ice::Current&)
1789 return physicsWorld->getRobotJointLimitHi(robotName, nodeName);
1801 const std::string& nodeName,
1802 const Ice::Current&)
1804 return physicsWorld->getRobotMaxTorque(robotName, nodeName);
1809 const std::string& nodeName,
1811 const Ice::Current&)
1813 physicsWorld->setRobotMaxTorque(robotName, nodeName, maxTorque);
1818 const std::string& robotNodeName,
1819 const Ice::Current&)
1827 const std::string& nodeName,
1828 const Ice::Current&)
1836 const std::string& nodeName,
1837 const Ice::Current&)
1845 const std::string& robotNodeName,
1846 const Vector3BasePtr& vel,
1847 const Ice::Current&)
1849 Eigen::Vector3f newVel = Vector3Ptr::dynamicCast(vel)->toEigen();
1850 physicsWorld->setRobotLinearVelocity(robotName, robotNodeName, newVel);
1855 const std::string& robotNodeName,
1856 const Vector3BasePtr& vel,
1857 const Ice::Current&)
1859 Vector3Ptr newVel = Vector3Ptr::dynamicCast(vel);
1860 physicsWorld->setRobotAngularVelocity(robotName, robotNodeName, newVel->toEigen());
1865 const std::string& robotNodeName,
1866 const Vector3BasePtr& vel,
1867 const Ice::Current&)
1869 Eigen::Vector3f newVel = Vector3Ptr::dynamicCast(vel)->toEigen();
1870 physicsWorld->setRobotLinearVelocityRobotRootFrame(robotName, robotNodeName, newVel);
1875 const std::string& robotNodeName,
1876 const Vector3BasePtr& vel,
1877 const Ice::Current&)
1879 Eigen::Vector3f newVel = Vector3Ptr::dynamicCast(vel)->toEigen();
1880 physicsWorld->setRobotAngularVelocityRobotRootFrame(robotName, robotNodeName, newVel);
1891 const std::string& robotNodeName,
1892 const Ice::Current&)
1895 return physicsWorld->hasRobotNode(robotName, robotNodeName);
1907 const std::string& robotNodeName,
1908 const std::string& objectName,
1909 const Ice::Current&)
1911 ARMARX_VERBOSE <<
"Object released " << robotName <<
"," << objectName;
1912 physicsWorld->objectReleased(robotName, robotNodeName, objectName);
1917 const std::string& robotNodeName,
1918 const std::string& objectName,
1919 const Ice::Current&)
1921 ARMARX_VERBOSE <<
"Object grasped" << robotName <<
"," << objectName;
1922 physicsWorld->objectGrasped(robotName, robotNodeName, objectName);
1928 return static_cast<float>(
physicsWorld->getCurrentSimTime());
1940 SimulatorInformation
1945 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
1946 SimulatorInformation res;
1951 std::vector<std::string> robNames =
physicsWorld->getRobotNames();
1952 res.nrRobots =
static_cast<int>(robNames.size());
1954 res.nrActuatedJoints =
physicsWorld->getRobotJointAngleCount();
1958 res.simTimeStepMeasuredMS =
physicsWorld->getSimulationStepTimeMeasured();
1959 res.simTimeStepDurationMS =
physicsWorld->getSimulationStepDuration();
1961 res.simTimeFactor = 0;
1962 if (res.simTimeStepMeasuredMS > 0)
1964 res.simTimeFactor = res.simTimeStepDurationMS / res.simTimeStepMeasuredMS;
1967 std::vector<VirtualRobot::SceneObjectPtr> objects =
physicsWorld->getObjects();
1973 ovd.name = o->getName();
1975 ovd.objectPoses[ovd.name] = p;
1976 VirtualRobot::Obstacle* ob =
dynamic_cast<VirtualRobot::Obstacle*
>(o.get());
1980 ovd.filename = ob->getFilename();
1983 if (o->getSimulationType() == VirtualRobot::SceneObject::Physics::eStatic)
1985 ovd.staticObject =
true;
1989 ovd.staticObject =
false;
1992 res.objects.push_back(ovd);
1995 for (
auto& r : robNames)
2004 ovd.robotFile = rob->getFilename();
2007 res.robots.push_back(ovd);
2033 ARMARX_ERROR <<
"Could not find file: \"" << packagePath.path <<
"\".";
2039 const std::string& robFileGlobal,
2041 const std::string& robFile,
2048 std::map<std::string, float> initConfig,
2049 bool selfCollisions)
2051 ARMARX_DEBUG <<
"Add robot from file " << robFileGlobal;
2052 auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
2053 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
2080 return robotInstanceName;
2090 for (
auto& rob : syncData.
robots)
2093 std::string top = rob.robotTopicName;
2099 rob.simulatorRobotListenerPrx = getTopic<SimulatorRobotListenerInterfacePrx>(top);
2102 for (
auto& fti : rob.forceTorqueSensors)
2104 ARMARX_INFO <<
"Offering topic " << fti.topicName;
2109 ARMARX_INFO <<
"Connecting to topic " << fti.topicName;
2110 fti.prx = getTopic<SimulatorForceTorqueListenerInterfacePrx>(fti.topicName);
2130 ObjectClassInformationSequence
2132 const std::string& frameName,
2133 const std::string& className,
2134 const Ice::Current&)
2136 auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
2137 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
2141 ObjectClassInformationSequence result;
2144 for (
const auto&
object : objects)
2146 ObjectClassInformation inf;
2148 inf.timestampMicroSeconds =
2150 inf.className = className;
2151 inf.manipulationObjectName = object;
2160 inf.pose =
physicsWorld->toFramedPose(worldPose, robotName, frameName);
2163 result.push_back(inf);
2171 const std::string& robotNodeName,
2172 const std::string& worldObjectName,
2173 const Ice::Current&)
2175 return physicsWorld->getDistance(robotName, robotNodeName, worldObjectName);
2180 const std::string& robotNodeName1,
2181 const std::string& robotNodeName2,
2182 const Ice::Current&)
2184 return physicsWorld->getRobotNodeDistance(robotName, robotNodeName1, robotNodeName2);
2190 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
2265 startTime = IceUtil::Time::now();
2267 sleepTimeMS =
static_cast<int>(
2269 static_cast<float>((IceUtil::Time::now() - startTime).toMilliSeconds()));
2271 if (sleepTimeMS < 0)
2274 <<
" milliseconds too long!";
2278 usleep(
static_cast<unsigned int>(sleepTimeMS * 1000));
2318 return static_cast<long>(
physicsWorld->getCurrentSimTime() * 1000);
2326 if (getProperty<bool>(
"RealTimeMode"))
2335 IceUtil::Time durationSim = IceUtil::Time::now() - startTime;
2340 << durationSim.toMilliSecondsDouble();
2343 ARMARX_DEBUG <<
"*** Step Physics, MS:" << durationSim.toMilliSecondsDouble();
2345 startTime = IceUtil::Time::now();
2348 IceUtil::Time durationSync = IceUtil::Time::now() - startTime;
2351 auto lockData =
physicsWorld->getScopedSyncLock(__FUNCTION__);
2373 SceneVisuData reportData =
physicsWorld->copySceneVisuData();
2389 const auto lockEngine =
physicsWorld->getScopedEngineLock(__FUNCTION__);
2390 const auto lockSync =
physicsWorld->getScopedSyncLock(__FUNCTION__);
2395 std::vector<SimDynamics::DynamicsEngine::DynamicsContactInfo> contacts =
2397 VirtualRobot::ColorMap cm(VirtualRobot::ColorMap::eHot);
2398 float maxImpulse = 2.0f;
2399 float arrowLength = 50.0f;
2403 for (
auto&
c : contacts)
2405 std::stringstream ss;
2406 ss <<
"Contact_" << i;
2411 std::string name = ss.str();
2412 std::string name2 = name +
"_2";
2415 if (!
c.objectAName.empty())
2417 objA =
c.objectAName;
2426 if (!
c.objectBName.empty())
2428 objB =
c.objectBName;
2435 ARMARX_DEBUG <<
"CONTACT " << name <<
", objects: " << objA <<
"-" << objB
2436 <<
", impulse:" <<
c.appliedImpulse;
2437 float intensity =
static_cast<float>(
c.appliedImpulse);
2439 if (intensity > maxImpulse)
2441 intensity = maxImpulse;
2444 intensity /= maxImpulse;
2452 Eigen::Vector3f dir2 = -(
c.normalGlobalB);
2467 std::stringstream ss;
2468 ss <<
"Contact_" << j;
2469 std::string name = ss.str();
2470 std::string name2 = name +
"_2";
2478 if (getProperty<bool>(
"DrawCoMVisu"))
2485 "CoM",
"GlobalCoM_" + name, pos, DrawColor{0.f, 0.f, 1.f, 0.5f}, 20);
2525 ctx[
"origin"] =
"simulation";
2531 header.timestampInMicroSeconds = reportData.
timestamp.toMicroSeconds();
2533 TransformStamped globalRobotPose;
2534 globalRobotPose.header = header;
2535 globalRobotPose.transform = r.
pose;
2568 ContactInfoSequence result;
2570 for (
auto& contact : contacts)
2572 ContactInformation contactInfo;
2573 contactInfo.objectNameA = contact.objectAName;
2574 contactInfo.objectNameB = contact.objectBName;
2575 contactInfo.posGlobalA =
new Vector3(contact.posGlobalA);
2576 contactInfo.posGlobalB =
new Vector3(contact.posGlobalB);
2577 result.push_back(contactInfo);
2592 std::string instanceName;
2595 return instanceName;
2602 const Ice::Current&)
2605 std::string name = instanceName;
2621 std::string instanceName;
2624 return instanceName;
2631 for (
auto& robot : report.
robots)
2633 if (robot.robotName == robotName)
2635 return stateFromRobotInfo(robot, report.
timestamp);
2639 return SimulatedRobotState();