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
66 EntityUpdate update;
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);
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 :
160 {RobotNameHelper::LocationLeft, RobotNameHelper::LocationRight})
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 = tryGet([&]() { return arm.getHandUnitName(); });
193
194
195 info.parts.emplace(side + "Arm", e);
196 }
197 }
198
199 arondto::RobotDescriptionVisualization visualization;
200 {
201 for (const auto& side :
202 {RobotNameHelper::LocationLeft, RobotNameHelper::LocationRight})
203 {
204 const auto arm = robotNameHelper->getArm(side);
205
206 armarx::armem::arondto::BodyPartDescription bpd;
207 bpd.root_node_name = tryGet([&]() { return arm.getHandRootNode(); });
208 bpd.xml.package = tryGet([&]() { return arm.getHandModelPackage(); });
209 bpd.xml.path = tryGet([&]() { return arm.getHandModelPath(); });
210 fixPathDto(bpd.xml);
211
212 visualization.body_parts.emplace(side + "Hand", bpd);
213 }
214 }
215
216 std::optional<
217 std::map<std::string, std::vector<armarx::armem::arondto::ManipulationCapability>>>
218 allManipulationCapabilities;
219 {
220 const auto robot = VirtualRobot::RobotIO::loadRobot(robotPath.toSystemPath());
221 ARMARX_CHECK_NOT_NULL(robot) << robotPath.toSystemPath();
222
223 for (const auto& eef : robot->getEndEffectors())
224 {
225 const auto& capabilities = eef->getManipulationCapabilities();
226 if (capabilities.has_value())
227 {
228 std::vector<armarx::armem::arondto::ManipulationCapability>
229 manipulationCapabilities;
230
231 for (const auto& vrCap : capabilities->capabilities)
232 {
233 arondto::ManipulationCapability dto;
234
235 dto.affordance = vrCap.affordance;
236 dto.tcp = vrCap.tcp;
237 dto.shape = vrCap.shape;
238 dto.type = vrCap.type;
239
240 manipulationCapabilities.push_back(dto);
241 }
242
243 // initialize on demand
244 if (not allManipulationCapabilities)
245 {
246 allManipulationCapabilities.emplace();
247 }
248
249 allManipulationCapabilities->emplace(eef->getName(),
250 manipulationCapabilities);
251 }
252 }
253 }
254
255 const armem::robot_state::description::RobotDescription robotDescription{
256 .name = kinematicUnit->getRobotName(),
257 .xml = {robotPath.serialize().package, robotPath.serialize().path},
258 .visualization = visualization,
259 .info = info,
260 .manipulationCapabilities = allManipulationCapabilities};
261
262 // make sure that the package path is valid
263 ARMARX_CHECK(std::filesystem::exists(robotDescription.xml.toSystemPath()));
264
265 commitRobotDescription(robotDescription);
266 }
267 else
268 {
269 ARMARX_WARNING << "Robot unit '" << robotUnit->ice_getIdentity().name
270 << "' does not have a kinematic unit."
271 << "\n Cannot commit robot description.";
272 }
273 }
274
277 {
278 return doLocked([this, &timestamp]() { return getRobotDescriptions(timestamp); });
279 }
280
283 {
285 (void)timestamp; // Unused
286
287 RobotDescriptionMap robotDescriptions;
288 segmentPtr->forEachEntity(
289 [this, &robotDescriptions](const wm::Entity& entity)
290 {
291 const wm::EntityInstance& entityInstance =
292 entity.getLatestSnapshot().getInstance(0);
293 const auto description =
295 if (description)
296 {
297 ARMARX_DEBUG << "Key is " << armem::MemoryID(entity.id());
298 robotDescriptions.emplace(description->name, *description);
299 }
300 else
301 {
302 ARMARX_WARNING << "Could not convert entity instance to 'RobotDescription'";
303 }
304 });
305
307 << "Number of known robot descriptions: " << robotDescriptions.size();
308 return robotDescriptions;
309 }
310
311} // namespace armarx::armem::server::robot_state::description
std::string timestamp()
#define ARMARX_CHECK_NOT_EMPTY(c)
#define VAROUT(x)
static std::vector< std::string > FindAllArmarXSourcePackages()
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:99
static std::filesystem::path toSystemPath(const data::PackagePath &pp)
MemoryID withProviderSegmentName(const std::string &name) const
Definition MemoryID.cpp:417
MemoryID withEntityName(const std::string &name) const
Definition MemoryID.cpp:425
std::string providerSegmentName
Definition MemoryID.h:52
bool hasProviderSegment(const std::string &name) const
Helps connecting a Memory server to the Ice interface.
data::CommitResult commitLocking(const data::Commit &commitIce, Time timeArrived)
void onConnect(const RobotUnitInterfacePrx &robotUnitPrx)
Definition Segment.cpp:44
RobotDescriptionMap getRobotDescriptionsLocking(const armem::Time &timestamp) const
Definition Segment.cpp:276
RobotDescriptionMap getRobotDescriptions(const armem::Time &timestamp) const
Definition Segment.cpp:282
Segment(server::MemoryToIceAdapter &iceMemory)
Definition Segment.cpp:34
auto doLocked(FunctionT &&function) const
Execute function under shared (read) lock.
ProviderSegment & addProviderSegment(const std::string &name, Args... args)
static DateTime Now()
Definition DateTime.cpp:51
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::optional< description::RobotDescription > convertRobotDescription(const armem::wm::EntityInstance &instance)
std::string tryGet(const std::function< std::string()> &func)
Definition Segment.cpp:92
std::unordered_map< std::string, armarx::armem::robot_state::description::RobotDescription > RobotDescriptionMap
armem::wm::EntityInstance EntityInstance
armarx::core::time::DateTime Time
void toAron(arondto::MemoryID &dto, const MemoryID &bo)
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface > RobotUnitInterfacePrx
A bundle of updates to be sent to the memory.
Definition Commit.h:90
std::vector< EntityUpdate > updates
The entity updates.
Definition Commit.h:97
An update of an entity for a specific point in time.
Definition Commit.h:26
auto & getLatestSnapshot(int snapshotIndex=0)
Retrieve the latest entity snapshot.