Segment.cpp
Go to the documentation of this file.
1 #include "Segment.h"
2 
3 #include <filesystem>
4 
5 #include <SimoxUtility/algorithm/string/string_tools.h>
6 #include <VirtualRobot/XML/RobotIO.h>
7 
14 
22 #include <RobotAPI/libraries/armem_robot_state/aron/Proprioception.aron.generated.h>
23 #include <RobotAPI/libraries/armem_robot_state/aron/Robot.aron.generated.h>
24 #include <RobotAPI/libraries/armem_robot_state/aron/RobotDescription.aron.generated.h>
30 
32 {
33 
35  Base(memoryToIceAdapter,
36  armem::robot_state::descriptionSegmentID.coreSegmentName,
37  arondto::RobotDescription::ToAronType())
38  {
39  }
40 
41  Segment::~Segment() = default;
42 
43  void
45  {
46  robotUnit = robotUnitPrx;
47 
48  // store the robot description linked to the robot unit in this segment
49  updateRobotDescription();
50  }
51 
52  void
53  Segment::commitRobotDescription(
55  {
56  const Time now = Time::Now();
57 
58  const MemoryID providerID = segmentPtr->id().withProviderSegmentName(robotDescription.name);
60  {
62  arondto::RobotDescription::ToAronType());
63  }
64 
65 
67  update.entityID = providerID.withEntityName("description");
68  update.arrivedTime = update.referencedTime = update.sentTime = now;
69 
70  arondto::RobotDescription dto;
71  toAron(dto, robotDescription);
72  update.instancesData = {dto.toAron()};
73 
74  Commit commit;
75  commit.updates.push_back(update);
76  iceMemory.commitLocking(commit);
77  }
78 
79  // Helper function to handle exceptions
80  // template <typename T>
81  // std::optional<T> tryGet(const std::function<T()>& func) {
82  // try {
83  // return func();
84  // } catch (const std::exception& ex) {
85  // // Handle exception or log error
86  // std::cerr << "Error: " << ex.what() << std::endl;
87  // return std::nullopt; // Return an empty optional if an exception occurs
88  // }
89  // }
90 
91  std::string
92  tryGet(const std::function<std::string()>& func)
93  {
94  try
95  {
96  return func();
97  }
98  catch (const std::exception& ex)
99  {
100  return ""; // Return an empty string if an exception occurs
101  }
102  }
103 
104  void
105  Segment::updateRobotDescription()
106  {
107  ARMARX_CHECK_NOT_NULL(robotUnit);
108  KinematicUnitInterfacePrx kinematicUnit = robotUnit->getKinematicUnit();
109  if (kinematicUnit)
110  {
111  const std::string robotName = kinematicUnit->getRobotName();
112  const std::string robotFilename = kinematicUnit->getRobotFilename();
113 
114  const std::vector<std::string> packages =
116  // const std::string package = armarx::ArmarXDataPath::getProject(packages, robotFilename);
117  const std::string package = simox::alg::split(robotFilename, "/").front();
118 
119  ARMARX_CHECK_NOT_EMPTY(package);
120 
121  ARMARX_INFO << VAROUT(package);
122  ARMARX_INFO << VAROUT(robotFilename);
123 
124  // make sure that the relative path is without the 'package/' prefix
125  const auto fixPath = [](armarx::PackagePath& pp)
126  {
127  auto spp = pp.serialize();
128  if (simox::alg::starts_with(spp.path, spp.package))
129  {
130  // remove "package" + "/"
131  const std::string fixedPath = spp.path.substr(spp.package.size() + 1, -1);
132 
133  spp.path = fixedPath;
134 
135  pp = armarx::PackagePath{spp};
136  }
137  };
138 
139  armarx::PackagePath robotPath{package, robotFilename};
140  fixPath(robotPath);
141 
142  const auto fixPathDto = [](armarx::arondto::PackagePath& pp)
143  {
144  if (simox::alg::starts_with(pp.path, pp.package))
145  {
146  // remove "package" + "/"
147  const std::string fixedPath = pp.path.substr(pp.package.size() + 1, -1);
148 
149  pp.path = fixedPath;
150  }
151  };
152 
153  ARMARX_INFO << "Robot description '" << robotPath << "'";
154 
155  auto robotNameHelper = RobotNameHelper::Create(robotPath.toSystemPath());
156 
157  arondto::RobotInfo info;
158  {
159  for (const auto& side :
161  {
162  const auto arm = robotNameHelper->getArm(side);
163 
164  arondto::RobotInfoElement e;
165  e.end_effector = tryGet([&]() { return arm.getEndEffector(); });
166  e.force_torque_sensor = tryGet([&]() { return arm.getForceTorqueSensor(); });
167  e.force_torque_sensor_frame =
168  tryGet([&]() { return arm.getForceTorqueSensorFrame(); });
169 
170  e.full_hand_collision_model.package =
171  tryGet([&]() { return arm.getHandModelPackage(); });
172  e.full_hand_collision_model.path =
173  tryGet([&]() { return arm.getFullHandCollisionModel(); });
174  fixPathDto(e.full_hand_collision_model);
175 
176 
177  e.hand_controller_name = tryGet([&]() { return arm.getHandControllerName(); });
178 
179  e.hand_model.package = tryGet([&]() { return arm.getHandModelPackage(); });
180  e.hand_model.path = tryGet([&]() { return arm.getHandModelPath(); });
181  fixPathDto(e.hand_model);
182 
183  e.hand_root_node = tryGet([&]() { return arm.getHandRootNode(); });
184  e.kinematic_chain = tryGet([&]() { return arm.getKinematicChain(); });
185 
186  e.palm_collision_model = tryGet([&]() { return arm.getPalmCollisionModel(); });
187 
188  e.tcp = tryGet([&]() { return arm.getTCP(); });
189  e.torso_kinematic_chain =
190  tryGet([&]() { return arm.getTorsoKinematicChain(); });
191 
192  e.hand_unit =
193  tryGet([&]() { return arm.getHandUnitName(); });
194 
195 
196  info.parts.emplace(side + "Arm", e);
197  }
198  }
199 
200  arondto::RobotDescriptionVisualization visualization;
201  {
202  for (const auto& side :
204  {
205  const auto arm = robotNameHelper->getArm(side);
206 
207  armarx::armem::arondto::BodyPartDescription bpd;
208  bpd.root_node_name = tryGet([&]() { return arm.getHandRootNode(); });
209  bpd.xml.package = tryGet([&]() { return arm.getHandModelPackage(); });
210  bpd.xml.path = tryGet([&]() { return arm.getHandModelPath(); });
211  fixPathDto(bpd.xml);
212 
213  visualization.body_parts.emplace(side + "Hand", bpd);
214  }
215  }
216 
217  std::optional<
218  std::map<std::string, std::vector<armarx::armem::arondto::ManipulationCapability>>>
219  allManipulationCapabilities;
220  {
221  const auto robot = VirtualRobot::RobotIO::loadRobot(robotPath.toSystemPath());
222  ARMARX_CHECK_NOT_NULL(robot) << robotPath.toSystemPath();
223 
224  for (const auto& eef : robot->getEndEffectors())
225  {
226  const auto& capabilities = eef->getManipulationCapabilities();
227  if (capabilities.has_value())
228  {
229  std::vector<armarx::armem::arondto::ManipulationCapability>
230  manipulationCapabilities;
231 
232  for (const auto& vrCap : capabilities->capabilities)
233  {
234  arondto::ManipulationCapability dto;
235 
236  dto.affordance = vrCap.affordance;
237  dto.tcp = vrCap.tcp;
238  dto.shape = vrCap.shape;
239  dto.type = vrCap.type;
240 
241  manipulationCapabilities.push_back(dto);
242  }
243 
244  // initialize on demand
245  if (not allManipulationCapabilities)
246  {
247  allManipulationCapabilities.emplace();
248  }
249 
250  allManipulationCapabilities->emplace(eef->getName(),
251  manipulationCapabilities);
252  }
253  }
254  }
255 
256  const armem::robot_state::description::RobotDescription robotDescription{
257  .name = kinematicUnit->getRobotName(),
258  .xml = {robotPath.serialize().package, robotPath.serialize().path},
259  .visualization = visualization,
260  .info = info,
261  .manipulationCapabilities = allManipulationCapabilities};
262 
263  // make sure that the package path is valid
264  ARMARX_CHECK(std::filesystem::exists(robotDescription.xml.toSystemPath()));
265 
266  commitRobotDescription(robotDescription);
267  }
268  else
269  {
270  ARMARX_WARNING << "Robot unit '" << robotUnit->ice_getIdentity().name
271  << "' does not have a kinematic unit."
272  << "\n Cannot commit robot description.";
273  }
274  }
275 
278  {
279  return doLocked([this, &timestamp]() { return getRobotDescriptions(timestamp); });
280  }
281 
284  {
286  (void)timestamp; // Unused
287 
288  RobotDescriptionMap robotDescriptions;
290  [this, &robotDescriptions](const wm::Entity& entity)
291  {
292  const wm::EntityInstance& entityInstance =
293  entity.getLatestSnapshot().getInstance(0);
294  const auto description =
296  if (description)
297  {
298  ARMARX_DEBUG << "Key is " << armem::MemoryID(entity.id());
299  robotDescriptions.emplace(description->name, *description);
300  }
301  else
302  {
303  ARMARX_WARNING << "Could not convert entity instance to 'RobotDescription'";
304  }
305  });
306 
308  << "Number of known robot descriptions: " << robotDescriptions.size();
309  return robotDescriptions;
310  }
311 
312 } // namespace armarx::armem::server::robot_state::description
armarx::RobotNameHelper::LocationLeft
static const std::string LocationLeft
Definition: RobotNameHelper.h:171
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::armem::robot_state::description::RobotDescription
Definition: types.h:44
Writer.h
armarx::armem::MemoryID::providerSegmentName
std::string providerSegmentName
Definition: MemoryID.h:52
armarx::armem::Commit
A bundle of updates to be sent to the memory.
Definition: Commit.h:89
armarx::armem::wm::EntityInstance
Client-side working entity instance.
Definition: memory_definitions.h:32
armarx::armem::server::MemoryToIceAdapter
Helps connecting a Memory server to the Ice interface.
Definition: MemoryToIceAdapter.h:19
armarx::armem::base::CoreSegmentBase::hasProviderSegment
bool hasProviderSegment(const std::string &name) const
Definition: CoreSegmentBase.h:116
armarx::armem::base::detail::GetLatestSnapshotMixin::getLatestSnapshot
auto & getLatestSnapshot(int snapshotIndex=0)
Retrieve the latest entity snapshot.
Definition: lookup_mixins.h:199
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:55
armarx::CMakePackageFinder::FindAllArmarXSourcePackages
static std::vector< std::string > FindAllArmarXSourcePackages()
Definition: CMakePackageFinder.cpp:438
MemoryID.h
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
armarx::armem::server::robot_state::description::Segment::onConnect
void onConnect(const RobotUnitInterfacePrx &robotUnitPrx)
Definition: Segment.cpp:44
armarx::armem::toAron
void toAron(arondto::MemoryID &dto, const MemoryID &bo)
Definition: aron_conversions.cpp:19
armarx::armem
Definition: LegacyRobotStateMemoryAdapter.cpp:31
query_fns.h
armarx::armem::robot_state::description::RobotDescription::xml
PackagePath xml
Definition: types.h:49
ARMARX_CHECK_NOT_EMPTY
#define ARMARX_CHECK_NOT_EMPTY(c)
Definition: ExpressionException.h:224
armarx::RobotNameHelper::LocationRight
static const std::string LocationRight
Definition: RobotNameHelper.h:172
armarx::starts_with
bool starts_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:43
armarx::armem::server::wm::Entity
Definition: memory_definitions.h:30
armarx::armem::base::detail::ForEachEntityMixin::forEachEntity
bool forEachEntity(FunctionT &&func)
Definition: iteration_mixins.h:258
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::armem::server::robot_state::description::tryGet
std::string tryGet(const std::function< std::string()> &func)
Definition: Segment.cpp:92
armarx::armem::Commit::updates
std::vector< EntityUpdate > updates
The entity updates.
Definition: Commit.h:97
armarx::armem::articulated_object::convertRobotDescription
std::optional< robot_state::description::RobotDescription > convertRobotDescription(const armem::wm::EntityInstance &instance)
Definition: utils.cpp:11
armarx::armem::server::segment::detail::SegmentBase< server::wm::CoreSegment >::segmentPtr
server::wm::CoreSegment * segmentPtr
Definition: SpecializedSegment.h:54
armarx::armem::MemoryID::withProviderSegmentName
MemoryID withProviderSegmentName(const std::string &name) const
Definition: MemoryID.cpp:412
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::armem::server::robot_state::description
Definition: Segment.cpp:31
armarx::PackagePath::toSystemPath
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
Definition: PackagePath.cpp:54
armarx::armem::server::robot_state::description::Segment::~Segment
virtual ~Segment() override
armarx::armem::server::segment::detail::SegmentBase< server::wm::CoreSegment >
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::armem::server::segment::SpecializedCoreSegment::doLocked
auto doLocked(FunctionT &&function) const
Definition: SpecializedCoreSegment.h:39
armarx::armem::EntityUpdate
An update of an entity for a specific point in time.
Definition: Commit.h:27
aron_conversions.h
armarx::armem::server::robot_state::description::Segment::getRobotDescriptions
RobotDescriptionMap getRobotDescriptions(const armem::Time &timestamp) const
Definition: Segment.cpp:283
types.h
PluginAll.h
armarx::armem::base::detail::MemoryItem::id
MemoryID & id()
Definition: MemoryItem.h:27
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:67
aron_conversions.h
MemoryToIceAdapter.h
aron_conversions.h
ExpressionException.h
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
CMakePackageFinder.h
armarx::armem::MemoryID::withEntityName
MemoryID withEntityName(const std::string &name) const
Definition: MemoryID.cpp:420
armarx::armem::robot_state::description::RobotDescription::name
std::string name
Definition: types.h:48
armarx::armem::server::segment::detail::SegmentBase< server::wm::CoreSegment >::iceMemory
MemoryToIceAdapter & iceMemory
Definition: SpecializedSegment.h:60
TimeUtil.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::armem::server::robot_state::description::Segment::Segment
Segment(server::MemoryToIceAdapter &iceMemory)
Definition: Segment.cpp:34
Segment.h
armarx::armem::server::robot_state::description::RobotDescriptionMap
std::unordered_map< std::string, armarx::armem::robot_state::description::RobotDescription > RobotDescriptionMap
Definition: forward_declarations.h:67
armarx::armem::server::robot_state::description::Segment::getRobotDescriptionsLocking
RobotDescriptionMap getRobotDescriptionsLocking(const armem::Time &timestamp) const
Definition: Segment.cpp:277
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface >
Builder.h
armarx::RobotNameHelper::Create
static RobotNameHelperPtr Create(const RobotInfoNodePtr &robotInfo, const StatechartProfilePtr &profile)
Definition: RobotNameHelper.cpp:96
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:92
armarx::armem::robot_state::descriptionSegmentID
const MemoryID descriptionSegmentID
Definition: memory_ids.cpp:30
robot_conversions.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::armem::server::wm::CoreSegment::addProviderSegment
ProviderSegment & addProviderSegment(const std::string &name, Args... args)
Definition: memory_definitions.h:101
ArmarXDataPath.h
armarx::PackagePath
Definition: PackagePath.h:55
armarx::armem::server::MemoryToIceAdapter::commitLocking
data::CommitResult commitLocking(const data::Commit &commitIce, Time timeArrived)
Definition: MemoryToIceAdapter.cpp:166
RobotNameHelper.h
memory_ids.h
PackagePath.h
armarx::human::MemoryID
const armem::MemoryID MemoryID
Definition: memory_ids.cpp:29