25#include <VirtualRobot/MathTools.h>
26#include <VirtualRobot/RobotNodeSet.h>
43#include <simox/control/geodesics/util.h>
44#include <simox/control/robot/NodeInterface.h>
45#include <simox/control/environment/collision.h>
46#include <simox/control/utils/primitive.h>
52 NJointControllerRegistration<NJointTaskspaceObjectCollisionAvoidanceImpedanceController>
54 "NJointTaskspaceObjectCollisionAvoidanceImpedanceController");
59 const NJointControllerConfigPtr& config,
63 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
65 userCfgWithColl = CollisionCtrlCfg::FromAron(cfg->config);
67 coll = std::make_shared<core::ObjectCollisionAvoidanceBase>(
rtGetRobot(), userCfgWithColl.coll);
68 collReady.store(
true);
75 return "NJointTaskspaceObjectCollisionAvoidanceImpedanceController";
81 double time_measure = IceUtil::Time::now().toMicroSecondsDouble();
83 double time_update_status = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
85 arm->controller.run(arm->rtConfig, arm->rtStatus);
86 double time_run_rt = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
91 coll->rtLimbControllerRun(arm->kinematicChainName,
92 arm->rtStatus.jointPosition,
93 arm->rtStatus.qvelFiltered,
94 arm->rtConfig.torqueLimit,
95 arm->rtStatus.desiredJointTorque);
97 double time_coll_run = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
102 coll->collLimb.at(arm->kinematicChainName).rts.desiredJointTorques);
108 double time_set_target = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
110 time_measure = IceUtil::Time::now().toMicroSecondsDouble() - time_measure;
112 if (time_measure > 200)
115 "time_update_status: %.2f\n"
116 "run_rt_limb: %.2f\n"
117 "run_coll_rt_limb: %.2f\n"
118 "set_target_limb: %.2f\n"
121 time_run_rt - time_update_status,
122 time_coll_run - time_run_rt,
123 time_set_target - time_coll_run,
125 .deactivateSpam(1.0f);
131 const IceUtil::Time& sensorValuesTimestamp,
132 const IceUtil::Time& timeSinceLastIteration)
134 double deltaT = timeSinceLastIteration.toSecondsDouble();
136 if (collReady.load())
139 coll->updateRtConfigFromUser();
140 coll->updateRtCollisionObjects();
141 coll->rtCollisionChecking();
143 for (
auto& pair :
limb)
145 this->
limbRT(pair.second, deltaT);
149 hands->updateRTStatus(deltaT);
157 Eigen::Matrix3d rotation = transformation.block<3,3>(0,0);
158 Eigen::Vector3d translation = transformation.block<3,1>(0,3);
167 const ::armarx::aron::data::dto::DictPtr& dto,
168 const Ice::Current& iceCurrent)
171 auto cfg = common::control_law::arondto::ObjectCollisionAvoidanceConfigDict::FromAron(dto);
172 coll->setUserCfg(cfg);
178 size_t numCollisionObjects = 0;
180 numCollisionObjects += pair.second.size();
183 std::vector<hpp::fcl::CollisionObject> allCollisionObjects;
184 allCollisionObjects.reserve(numCollisionObjects);
186 allCollisionObjects.insert(allCollisionObjects.end(), pair.second.begin(), pair.second.end());
189 coll->updateUserCollisionObjects(allCollisionObjects);
194 const std::string& primitiveSourceName,
195 const ::armarx::aron::data::dto::DictPtr& dto,
196 const Ice::Current& iceCurrent)
199 auto scene = common::control_law::arondto::CollisionScene::FromAron(dto);
200 auto boxes = scene.boxes;
201 auto spheres = scene.spheres;
202 auto cylinders = scene.cylinders;
203 auto capsules = scene.capsules;
204 auto ellipsoids = scene.ellipsoids;
208 collisionObjects.emplace(primitiveSourceName, std::vector<hpp::fcl::CollisionObject>());
210 std::vector<hpp::fcl::CollisionObject>& collisionObjectsOfSource =
collisionObjects[primitiveSourceName];
211 collisionObjectsOfSource.clear();
212 collisionObjectsOfSource.reserve(boxes.size() + spheres.size() + cylinders.size() + capsules.size() + ellipsoids.size());
214 for (
auto box : boxes)
216 collisionObjectsOfSource.push_back(
217 simox::control::environment::createCollisionObject(
218 simox::control::utils::primitive::Box{.lengthX = box.lengthX, .lengthY = box.lengthY, .lengthZ = box.lengthZ},
219 matrixToIsometry(box.transformation)
224 for (
auto sphere : spheres)
226 collisionObjectsOfSource.push_back(
227 simox::control::environment::createCollisionObject(
228 simox::control::utils::primitive::Sphere{.radius = sphere.radius},
229 matrixToIsometry(sphere.transformation)
234 for (
auto cylinder : cylinders)
236 collisionObjectsOfSource.push_back(
237 simox::control::environment::createCollisionObject(
238 simox::control::utils::primitive::Cylinder{.radius = cylinder.radius, .lengthY = cylinder.lengthY},
239 matrixToIsometry(cylinder.transformation)
244 for (
auto capsule : capsules)
246 collisionObjectsOfSource.push_back(
247 simox::control::environment::createCollisionObject(
248 simox::control::utils::primitive::Capsule{.radius = capsule.radius, .lengthY = capsule.lengthY},
249 matrixToIsometry(capsule.transformation)
254 for (
auto ellipsoid : ellipsoids)
256 collisionObjectsOfSource.push_back(
257 simox::control::environment::createCollisionObject(
258 simox::control::utils::primitive::Ellipsoid{.lengthX = ellipsoid.lengthX, .lengthY = ellipsoid.lengthY, .lengthZ = ellipsoid.lengthZ},
259 matrixToIsometry(ellipsoid.transformation)
271 const Ice::Current& iceCurrent)
273 if (not collReady.load())
277 return coll->userCfg.toAronDTO();
282 const ::armarx::aron::data::dto::DictPtr& dto,
283 const Ice::Current& iceCurrent)
286 userCfgWithColl = CollisionCtrlCfg::FromAron(dto);
288 coll->setUserCfg(userCfgWithColl.coll);
297 return userCfgWithColl.toAronDTO();
310 datafields[
"trackingError"] =
new Variant(rtStatus.trackingError);
316 datafields,
"projectedImpedanceTorque", rtStatus.projImpedanceJointTorque);
322 Eigen::VectorXf selfCollNullspace = rtStatus.selfCollNullSpace.diagonal();
323 Eigen::VectorXf jointLimNullspace = rtStatus.jointLimNullSpace.diagonal();
358 for (
int i = 0; i < rtStatus.activeCollPairsNum; ++i) {
363 .fromTo(rtStatus.collDataVec[i].point1 * 1000.0,
364 rtStatus.collDataVec[i].point1 * 1000.0 +
365 rtStatus.collDataVec[i].direction * 50.0 *
366 rtStatus.collDataVec[i].repulsiveForce)
367 .
color(simox::Color::blue()));
371 datafields[std::to_string(i) +
"_minDistance"] =
372 new Variant(rtStatus.collDataVec[i].minDistance);
373 datafields[std::to_string(i) +
"_repForce"] =
374 new Variant(rtStatus.collDataVec[i].repulsiveForce);
375 datafields[std::to_string(i) +
"_dampingForce"] =
376 new Variant(-1.0f * rtStatus.collDataVec[i].damping *
377 rtStatus.collDataVec[i].distanceVelocity);
378 datafields[std::to_string(i) +
"_n_des(d)"] =
379 new Variant(rtStatus.collDataVec[i].desiredNSColl);
381 datafields, std::to_string(i) +
"_point", rtStatus.collDataVec[i].point1);
383 datafields, std::to_string(i) +
"_dir", rtStatus.collDataVec[i].direction);
633 .fromTo(rtStatus.globalPose.block<3, 1>(0, 3),
634 rtStatus.globalPose.block<3, 1>(0, 3) +
635 rtStatus.projForceImpedance.head(3) * 1000.0)
636 .
color(simox::Color::red()));
661 debugObs->setDebugChannel(
"CollAvoid_ImpCtrl_" + arm.
nodeSetName, datafields);
666 const std::vector<hpp::fcl::CollisionObject>&
objects,
668 const std::string& layerSuffix)
672 for (
size_t i = 0; i <
objects.size(); ++i)
675 auto position =
object.getTranslation().cast<
float>() * 1000;
676 auto rotation =
object.getRotation().cast<
float>();
678 switch (
object.getNodeType())
680 case hpp::fcl::NODE_TYPE::GEOM_BOX:
682 const hpp::fcl::Box* box = std::static_pointer_cast<hpp::fcl::Box>(
object.collisionGeometry()).get();
684 .
size(box->halfSide.cast<
float>() * 1000 * 2)
687 .
color(255, 0, 0, 128);
688 objectLayer.
add(vizObject);
691 case hpp::fcl::NODE_TYPE::GEOM_SPHERE:
693 const hpp::fcl::Sphere* sphere = std::static_pointer_cast<hpp::fcl::Sphere>(
object.collisionGeometry()).get();
695 .
radius(
static_cast<float>(sphere->radius) * 1000)
698 .
color(0, 0, 255, 128);
699 objectLayer.
add(vizObject);
702 case hpp::fcl::NODE_TYPE::GEOM_CYLINDER:
705 const auto _rotation = rotation * Eigen::AngleAxisf(-
M_PI / 2., Eigen::Vector3f::UnitX());
706 const hpp::fcl::Cylinder* cylinder = std::static_pointer_cast<hpp::fcl::Cylinder>(
object.collisionGeometry()).get();
708 .
height(
static_cast<float>(cylinder->halfLength) * 1000 * 2)
709 .
radius(
static_cast<float>(cylinder->radius) * 1000)
712 .
color(0, 255, 0, 128);
713 objectLayer.
add(vizObject);
716 case hpp::fcl::NODE_TYPE::GEOM_CAPSULE: {
717 const hpp::fcl::Capsule* capsule = std::static_pointer_cast<hpp::fcl::Capsule>(
object.collisionGeometry()).get();
718 Eigen::Vector3f offset;
719 offset << 0, 0, static_cast<float>(capsule->halfLength) * 1000;
720 offset = rotation * offset;
722 .
radius(
static_cast<float>(capsule->radius) * 1000)
725 .
color(255, 200, 0, 128);
727 .
radius(
static_cast<float>(capsule->radius) * 1000)
730 .
color(255, 200, 0, 128);
731 const auto _rotation = rotation * Eigen::AngleAxisf(-
M_PI / 2., Eigen::Vector3f::UnitX());
733 .
height(
static_cast<float>(capsule->halfLength) * 1000 * 2)
734 .
radius(
static_cast<float>(capsule->radius) * 1000)
735 .
color(255, 200, 0, 128)
738 objectLayer.
add(vizObject);
739 objectLayer.
add(cap1);
740 objectLayer.
add(cap2);
743 case hpp::fcl::NODE_TYPE::GEOM_ELLIPSOID:
745 const hpp::fcl::Ellipsoid* ellipsoid = std::static_pointer_cast<hpp::fcl::Ellipsoid>(
object.collisionGeometry()).get();
748 .
axisLengths(ellipsoid->radii.cast<
float>() * 1000)
751 .
color(255, 0, 200, 128);
752 objectLayer.
add(vizObject);
758 arviz.commit(objectLayer);
770 for (
auto& pair :
coll->collLimb)
776 const auto& robotObjects =
coll->collisionRobot->getCollisionManager()->getObjects();
777 std::vector<hpp::fcl::CollisionObject> robotObjectsByValue;
778 for (
const auto* ptr : robotObjects) {
779 robotObjectsByValue.push_back(*ptr);
789 "rt Preactivate controller NJointTaskspaceObjectCollisionAvoidanceImpedanceController");
792 if (collReady.load())
795 coll->rtPreActivate();
803 if (collReady.load())
806 coll->rtPostDeactivate();
809 "post deactivate: NJointTaskspaceObjectCollisionAvoidanceImpedanceController");
815 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
816 const std::map<std::string, ConstSensorDevicePtr>&)
822 ::armarx::WidgetDescription::WidgetSeq widgets;
825 LabelPtr label =
new Label;
826 label->text =
"select a controller config";
828 StringComboBoxPtr cfgBox =
new StringComboBox;
829 cfgBox->name =
"config_box";
830 cfgBox->defaultIndex = 0;
831 cfgBox->multiSelect =
false;
833 cfgBox->options = std::vector<std::string>{
834 "default",
"default_a7_right",
"default_a7_right_zero_torque"};
837 layout->children.emplace_back(label);
838 layout->children.emplace_back(cfgBox);
841 layout->children.insert(layout->children.end(), widgets.begin(), widgets.end());
850 auto cfgName = values.at(
"config_box")->getString();
853 "controller_config/NJointTaskspaceObjectCollisionAvoidanceImpedanceController/" + cfgName +
861 return new ConfigurableNJointControllerConfig{cfgDTO.toAronDTO()};
#define ARMARX_RT_LOGF_WARN(...)
#define ARMARX_RT_LOGF_INFO(...)
armarx::viz::Client arviz
std::string getName() const
Retrieve name of object.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
const T & getUpToDateReadBuffer() const
The Variant class is described here: Variants.
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
::armarx::aron::data::dto::DictPtr getConfig(const Ice::Current &iceCurrent=Ice::emptyCurrent) override
std::map< std::string, ArmPtr > limb
void limbRTSetTarget(ArmPtr &arm, const Eigen::VectorXf &targetTorque)
NJointTaskspaceImpedanceController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
core::HandControlPtr hands
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
std::unique_ptr< ArmData > ArmPtr
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface.
void rtPreActivateController() override
This function is called before the controller is activated.
void limbRTUpdateStatus(ArmPtr &arm, const double deltaT)
-----------------------------— Real time cotnrol --------------------------------------—
std::string getClassName(const Ice::Current &=Ice::emptyCurrent) const override
void collObjectPublish(const std::vector< hpp::fcl::CollisionObject > &objects, const DebugObserverInterfacePrx &debugObs, const std::string &layerSuffix)
static WidgetDescription::WidgetPtr GenerateConfigDescription(const VirtualRobot::RobotPtr &, const std::map< std::string, ConstControlDevicePtr > &, const std::map< std::string, ConstSensorDevicePtr > &)
ConfigurableNJointControllerConfigPtr ConfigPtrT
void limbRT(ArmPtr &arm, const double deltaT)
core::ObjectCollisionAvoidanceBasePtr coll
void sendCollisionObjects()
static ConfigPtrT GenerateConfigFromVariants(const StringVariantBaseMap &values)
std::map< std::string, std::vector< hpp::fcl::CollisionObject > > collisionObjects
NJointTaskspaceObjectCollisionAvoidanceImpedanceController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &robot)
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void updateCollisionAvoidanceConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface for collision avoidance.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void updateCollisionObjects(const std::string &primitiveSourceName, const ::armarx::aron::data::dto::DictPtr &scene, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
void onPublish(const SensorAndControl &sc, const DebugDrawerInterfacePrx &drawer, const DebugObserverInterfacePrx &) override
::armarx::aron::data::dto::DictPtr getConfig(const Ice::Current &iceCurrent) override
void collLimbPublish(core::ObjectCollisionAvoidanceBase::NodeSetData &arm, const DebugObserverInterfacePrx &debugObs)
void rtPreActivateController() override
NJointControllerBase interface.
void updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent) override
DerivedT & color(Color color)
DerivedT & position(float x, float y, float z)
DerivedT & orientation(Eigen::Quaternionf const &ori)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
armarx::aron::data::dto::Dict getCollisionAvoidanceConfig()
std::shared_ptr< class Robot > RobotPtr
::IceInternal::Handle< Dict > DictPtr
void debugEigenVec(StringVariantBaseMap &datafields, const std::string &name, Eigen::VectorXf vec)
NJointControllerRegistration< NJointTaskspaceObjectCollisionAvoidanceImpedanceController > registrationControllerNJointTaskspaceObjectCollisionAvoidanceImpedanceController("NJointTaskspaceObjectCollisionAvoidanceImpedanceController")
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
AronDTO readFromJson(const std::filesystem::path &filename)
auto transform(const Container< InputT, Alloc > &in, OutputT(*func)(InputT const &)) -> Container< OutputT, typename std::allocator_traits< Alloc >::template rebind_alloc< OutputT > >
Convenience function (with less typing) to transform a container of type InputT into the same contain...
IceUtil::Handle< class RobotUnit > RobotUnitPtr
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl
armarx::TripleBuffer< RtStatus > bufferRTtoPublish
Box & size(Eigen::Vector3f const &s)
Cylinder & height(float h)
Cylinder & radius(float r)
Ellipsoid & axisLengths(const Eigen::Vector3f &axisLengths)
void add(ElementT const &element)