TransformReader.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @author Fabian Reister ( fabian dot reister at kit dot edu )
17 * @date 2021
18 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19 * GNU General Public License
20 */
21
22#include "TransformReader.h"
23
24#include <algorithm>
25#include <iterator>
26#include <numeric>
27
28// Ice
29#include <IceUtil/Time.h>
30
31// Eigen
32#include <Eigen/Geometry>
33
34// Simox
35#include <SimoxUtility/algorithm/get_map_keys_values.h>
36#include <SimoxUtility/algorithm/string/string_tools.h>
37#include <SimoxUtility/color/cmaps.h>
38#include <SimoxUtility/math/pose/interpolate.h>
39
40// ArmarX
44
45// this package
53#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
59
61{
63 memoryReader(t.memoryReader), properties(t.properties), propertyPrefix(t.propertyPrefix)
64 {
65 }
66
68
69 void
71 {
72 ARMARX_DEBUG << "TransformReader: registerPropertyDefinitions";
73
74 const std::string prefix = propertyPrefix;
75
76 def->optional(properties.localizationSegment,
77 prefix + "localizationSegment",
78 "Name of the localization memory core segment to use.");
79
80 def->optional(properties.memoryName, prefix + "Memory");
81 }
82
83 void
85 {
86 // Wait for the memory to become available and add it as dependency.
87 ARMARX_INFO << "TransformReader: Waiting for memory '" << properties.memoryName << "' ...";
88 try
89 {
90 memoryReader = memoryNameSystem.useReader(properties.memoryName);
91 ARMARX_INFO << "TransformReader: Connected to memory '" << properties.memoryName;
92 }
94 {
95 ARMARX_ERROR << e.what();
96 return;
97 }
98 }
99
101 TransformReader::getGlobalPose(const std::string& agentName,
102 const std::string& robotRootFrame,
103 const armem::Time& timestamp) const
104 {
105 const TransformQuery query{.header = {.parentFrame = GlobalFrame,
106 .frame = robotRootFrame,
107 .agent = agentName,
108 .timestamp = timestamp}};
109
110 return lookupTransform(query);
111 }
112
113 // std::vector<std::string> buildTransformChainArbitrary(const
114 // std::map<std::string, armem::ProviderSegment>& providerSegments, const
115 // std::string& parentFrame, const std::string& frame){
116
117 // std::map<std::string, std::string> tf;
118
119 // // build string representation of transforms
120 // for(const auto& [name, segment]: providerSegments){
121 // const auto frames = simox::alg::split(name, ",");
122 // if (frames.size() != 2){
123 // ARMARX_WARNING << "Segment name " << name << " not understood";
124 // continue;
125 // }
126
127 // tf.insert(frame[0], frame[1]);
128 // }
129
130 // // find
131
132 // }
133
134
137 {
138 const auto& timestamp = query.header.timestamp;
139 ARMARX_DEBUG << "Looking up transform at timestamp " << timestamp;
140
141 const IceUtil::Time durationEpsilon = IceUtil::Time::milliSeconds(-1);
142 (void)durationEpsilon;
143
144 // Query all entities from provider.
146
147 // clang-format off
148 qb
149 .coreSegments().withName(properties.localizationSegment)
150 .providerSegments().withName(query.header.agent) // agent
151 .entities().all() // parentFrame,frame
152 .snapshots().beforeOrAtTime(query.header.timestamp);
153 // clang-format on
154
155 try
156 {
157 std::scoped_lock l(memoryReaderMutex);
158 const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
159 ARMARX_DEBUG << "Lookup result in reader: " << qResult;
160
161 if (not qResult.success)
162 {
163 return {.transform =
164 {
165 .header = query.header,
166 },
167 .status = TransformResult::Status::ErrorFrameNotAvailable,
168 .errorMessage = "Error in tf lookup '" + query.header.parentFrame + " -> " +
169 query.header.frame + "' : " + qResult.errorMessage};
170 }
171
172 const auto& localizationCoreSegment =
173 qResult.memory.getCoreSegment(properties.localizationSegment);
174
176 return TransformHelper::lookupTransform(localizationCoreSegment, query);
177 }
178 catch (...)
179 {
180 ARMARX_VERBOSE << "Lookup Transform failure" << GetHandledExceptionString();
181 return TransformResult{.transform =
182 {
183 .header = query.header,
184 },
185 .status = TransformResult::Status::Error,
186 .errorMessage = "Error in tf lookup '" +
187 query.header.parentFrame + " -> " +
188 query.header.frame + "' : Memory exception."};
189 }
190 }
191
192} // namespace armarx::armem::robot_state::client::localization
std::string timestamp()
CoreSegmentT & getCoreSegment(const std::string &name)
Definition MemoryBase.h:134
The memory name system (MNS) client.
Reader useReader(const MemoryID &memoryID)
Use a memory server and get a reader for it.
The query::Builder class provides a fluent-style specification of hierarchical queries.
Definition Builder.h:22
CoreSegmentSelector & coreSegments()
Start specifying core segments.
Definition Builder.cpp:42
CoreSegmentSelector & withName(const std::string &name) override
ProviderSegmentSelector & providerSegments()
Start specifying provider segments.
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition selectors.cpp:92
ProviderSegmentSelector & withName(const std::string &name) override
EntitySelector & entities()
Start specifying entities.
SnapshotSelector & beforeOrAtTime(Time timestamp)
Definition selectors.cpp:73
Indicates that a query to the Memory Name System failed.
Definition mns.h:25
void registerPropertyDefinitions(::armarx::PropertyDefinitionsPtr &def) override
TransformResult getGlobalPose(const std::string &agentName, const std::string &robotRootFrame, const armem::Time &timestamp) const override
TransformResult lookupTransform(const TransformQuery &query) const override
void connect(armem::client::MemoryNameSystem &memoryNameSystem) override
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
armarx::core::time::DateTime Time
std::string GetHandledExceptionString()
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Result of a QueryInput.
Definition Query.h:51
wm::Memory memory
The slice of the memory that matched the query.
Definition Query.h:58