SegmentAdapter.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 * @package RobotAPI::armem_objects::SegmentAdapter
17 * @author Fabian Reister ( fabian dot reister at kit dot edu )
18 * @date 2024
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "SegmentAdapter.h"
24
25#include <iterator>
26#include <memory>
27#include <optional>
28
29#include <SimoxUtility/algorithm/get_map_keys_values.h>
30#include <VirtualRobot/Robot.h>
31
43
49#include <RobotAPI/libraries/armem_objects/aron/FamiliarObjectInstance.aron.generated.h>
50#include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
54
56{
57
58 SegmentAdapter::SegmentAdapter(MemoryToIceAdapter& iceMemory) : segment(iceMemory)
59 {
60 }
61
62 std::string
64 {
65 return Logging::tag.tagName;
66 }
67
68 void
70 {
71 segment.defineProperties(defs, prefix);
72 visu.defineProperties(defs, prefix + "visu.");
73 }
74
75 void
77 {
78 segment.setTag(getName());
79 segment.decay.setTag(getName());
80 // segment.setPredictionEngines(predictionEngines);
81 visu.setTag(getName());
82
83 segment.init();
84 }
85
86 void
89 viz::Client arviz,
90 DebugObserverInterfacePrx debugObserver)
91 {
92 this->debugObserver = debugObserver;
93 this->arviz = arviz;
94
95 ARMARX_CHECK_NOT_NULL(virtualRobotReader);
96 segment.robots.reader = virtualRobotReader;
97
98 visu.arviz = arviz;
99
100 if (!visu.updateTask)
101 {
102 ARMARX_IMPORTANT << "Enabled visu";
103 visu.updateTask = new SimpleRunningTask<>([this]() { this->visualizeRun(); });
104 visu.updateTask->start();
105 }
106
107 segment.connect(arviz);
108 }
109
110 void
112 const std::string& providerName,
113 const ::armarx::objpose::ProvidedFamiliarObjectPoseSeq& data,
114 const Ice::Current&)
115 {
116
117 if (data.empty())
118 {
119 return;
120 }
121
122 // Note, that in general, timestamps in `data` can differ. Therefore, we maintain the sync timestamp
123 // and check whether we have to update the robot. Otherwise, we can avoid these Ice calls.
124 std::optional<armarx::DateTime> syncTimestamp;
125
126
127 const auto convertAndFillFamiliarObjectInstances =
128 [this, providerName, &syncTimestamp](const ::armarx::aron::data::dto::DictPtr& data)
129 -> armarx::armem::arondto::FamiliarObjectInstance
130 {
131 auto famObjInstance = armarx::armem::arondto::FamiliarObjectInstance::FromAron(data);
132
133 // fill global pose info if not set yet
134 if (not famObjInstance.poseGlobal.has_value())
135 {
136 armarx::FramedPose framedPose(famObjInstance.poseSensFrame.pose,
137 famObjInstance.poseSensFrame.header.frame,
138 famObjInstance.poseSensFrame.header.agent);
139
140 ARMARX_CHECK_NOT_EMPTY(famObjInstance.poseSensFrame.header.agent);
141 ARMARX_CHECK_NOT_EMPTY(famObjInstance.poseSensFrame.header.frame);
142
144 segment.robots.get(famObjInstance.poseSensFrame.header.agent, providerName);
145 ARMARX_CHECK_NOT_NULL(robot) << famObjInstance.poseSensFrame.header.agent;
146
147
148 if (not syncTimestamp.has_value()
149 or syncTimestamp.value() != famObjInstance.timestamp)
150 {
152 segment.robots.reader->synchronizeRobot(*robot, famObjInstance.timestamp));
153 syncTimestamp = famObjInstance.timestamp;
154 }
155
156
157 famObjInstance.poseGlobal.emplace();
158 famObjInstance.poseGlobal->pose = framedPose.toGlobalEigen(robot);
159 famObjInstance.poseGlobal->header.agent = famObjInstance.poseSensFrame.header.agent;
160 famObjInstance.poseGlobal->header.frame = armarx::GlobalFrame;
161 }
162 else
163 {
164 ARMARX_CHECK_EQUAL(famObjInstance.poseGlobal->header.frame, armarx::GlobalFrame);
165 }
166
167
168 return famObjInstance;
169 };
170
171 std::vector<armarx::armem::arondto::FamiliarObjectInstance> familiarObjectInstances;
172 familiarObjectInstances.reserve(data.size());
173
174 std::transform(std::begin(data),
175 std::end(data),
176 std::back_inserter(familiarObjectInstances),
177 convertAndFillFamiliarObjectInstances);
178
179 segment.commit(familiarObjectInstances, providerName);
180 }
181
182 void
183 SegmentAdapter::handleProviderUpdate(const std::string& providerName)
184 {
185 // Initialized to 0 on first access.
186 if (segment.providers.count(providerName) == 0)
187 {
188 segment.providers[providerName] = objpose::ProviderInfo();
189 }
190 }
191
192 void
193 SegmentAdapter::visualizeRun()
194 {
195 if (not visu.enabled)
196 {
197 ARMARX_INFO << "Visu disabled";
198 return;
199 }
200
202
203 while (visu.updateTask && !visu.updateTask->isStopped())
204 {
205 {
206 std::scoped_lock lock(visuMutex);
207
208 const std::map<std::string,
209 std::vector<armarx::armem::arondto::FamiliarObjectInstance>>
210 familiarObjectsByProvider = segment.doLocked(
211 [this]()
212 { return segment.getFamiliarObjectsByProvider(armarx::Clock::Now()); });
213
214 ARMARX_VERBOSE << "Visualizing " << familiarObjectsByProvider.size()
215 << " providers.";
216 visu.visualizeFamiliarObjectsByProvider(familiarObjectsByProvider);
217 }
218
219 metronome.waitForNextTick();
220 }
221 }
222
223
224} // namespace armarx::armem::server::obj::familiar_object_instance
#define ARMARX_CHECK_NOT_EMPTY(c)
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
The FramedPose class.
Definition FramedPose.h:281
Eigen::Matrix4f toGlobalEigen(const SharedRobotInterfacePrx &referenceRobot) const
static Frequency HertzDouble(double hertz)
Definition Frequency.cpp:30
bool isStopped()
Retrieve whether stop() has been called.
Helps connecting a Memory server to the Ice interface.
void reportFamiliarObjectPoses(const std::string &providerName, const ::armarx::objpose::ProvidedFamiliarObjectPoseSeq &data, ICE_CURRENT_ARG) override
void connect(std::experimental::observer_ptr< robot_state::VirtualRobotReader > virtualRobotReader, viz::Client arviz, DebugObserverInterfacePrx debugObserver)
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="")
std::map< std::string, std::vector< armarx::armem::arondto::FamiliarObjectInstance > > getFamiliarObjectsByProvider(const DateTime &now)
Definition Segment.cpp:179
void visualizeFamiliarObjectsByProvider(const std::map< std::string, std::vector< armarx::armem::arondto::FamiliarObjectInstance > > &familiarObjectsByProvider)
Definition Visu.cpp:78
SimpleRunningTask ::pointer_type updateTask
Definition Visu.h:66
auto doLocked(FunctionT &&function) const
Execute function under shared (read) lock.
Simple rate limiter for use in loops to maintain a certain frequency given a clock.
Definition Metronome.h:57
#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_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#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
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
SimpleRunningTask(Ts...) -> SimpleRunningTask< std::function< void(void)> >