RobotStateWriter.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::ArmarXObjects::RobotSensorMemory
17  * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu )
18  * @date 2020
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 #include "RobotStateWriter.h"
24 
25 // STL
26 #include <chrono>
27 
28 // Simox
29 #include <SimoxUtility/math/convert/rpy_to_mat3f.h>
30 
31 // ArmarX
35 
38 #include <RobotAPI/libraries/armem_robot_state/aron/Proprioception.aron.generated.h>
42 
44 {
45 
46  void
48  {
49  // Thread-local copy of debug observer helper.
50  this->debugObserver =
51  DebugObserverHelper(Logging::tag.tagName, debugObserverPlugin.getDebugObserver(), true);
52  }
53 
54  static float
55  toDurationMs(std::chrono::high_resolution_clock::time_point start,
56  std::chrono::high_resolution_clock::time_point end)
57  {
58  auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
59  return duration.count() / 1000.f;
60  }
61 
62  void
63  RobotStateWriter::run(float pollFrequency,
64  Queue& dataBuffer,
66  localization::Segment& localizationSegment)
67  {
68  while (isRunning())
69  {
70  if (debugObserver)
71  {
72  // This locks the queue, but I did not find an interface to lock the queue,
73  // get the size and wait_pull().
74  size_t dataBufferSize = dataBuffer.size();
75  debugObserver->setDebugObserverDatafield("RobotStateWriter | Queue Size",
76  static_cast<long>(dataBufferSize));
77  }
78 
79  RobotUnitData robotUnitData;
80  if (const auto status = dataBuffer.wait_pull(robotUnitData);
81  status == boost::queue_op_status::success)
82  {
83  auto start = std::chrono::high_resolution_clock::now();
84  auto endBuildUpdate = start, endProprioception = start, endLocalization = start;
85 
86  Update update = buildUpdate(robotUnitData);
87  endBuildUpdate = std::chrono::high_resolution_clock::now();
88 
89  // Commits lock the core segments.
90 
91  // Proprioception + Exteroception
92  armem::CommitResult resultProprioception =
93  memory.commitLocking(update.proprioception);
94 
95  ARMARX_DEBUG << deactivateSpam(1) << VAROUT(update.exteroception.updates.size());
96  armem::CommitResult resultExteroception =
97  memory.commitLocking(update.exteroception);
98  endProprioception = std::chrono::high_resolution_clock::now();
99 
100  // Localization
101  for (const armem::robot_state::Transform& transform : update.localization)
102  {
103  localizationSegment.doLocked(
104  [&localizationSegment, &transform]()
105  { localizationSegment.commitTransform(transform); });
106  }
107  endLocalization = std::chrono::high_resolution_clock::now();
108 
109  if (not resultProprioception.allSuccess())
110  {
111  ARMARX_WARNING << "Could not commit data to proprioception segment in memory. "
112  "Error message: "
113  << resultProprioception.allErrorMessages();
114  }
115 
116  if (not resultExteroception.allSuccess())
117  {
118  ARMARX_WARNING << "Could not commit data to exteroception segment in memory. "
119  "Error message: "
120  << resultExteroception.allErrorMessages();
121  }
122 
123  if (debugObserver)
124  {
125  auto end = std::chrono::high_resolution_clock::now();
126 
127  debugObserver->setDebugObserverDatafield("RobotStateWriter | t Commit (ms)",
128  toDurationMs(start, end));
129  debugObserver->setDebugObserverDatafield(
130  "RobotStateWriter | t Commit 1. Build Update (ms)",
131  toDurationMs(start, endBuildUpdate));
132  debugObserver->setDebugObserverDatafield(
133  "RobotStateWriter | t Commit 2. Proprioception (ms)",
134  toDurationMs(endBuildUpdate, endProprioception));
135  debugObserver->setDebugObserverDatafield(
136  "RobotStateWriter | t Commit 3. Localization (ms)",
137  toDurationMs(endProprioception, endLocalization));
138  }
139  }
140  else
141  {
142  ARMARX_WARNING << "Queue pull was not successful. "
143  << static_cast<std::underlying_type<boost::queue_op_status>::type>(
144  status);
145  }
146 
147  if (debugObserver)
148  {
149  debugObserver->sendDebugObserverBatch();
150  }
151  }
152  }
153 
154  bool
155  RobotStateWriter::isRunning()
156  {
157  return task and not task->isStopped();
158  }
159 
160  RobotStateWriter::Update
162  {
163  // Send batch to memory
164  Update update;
165 
166  if (data.proprioception)
167  {
168  armem::EntityUpdate& up = update.proprioception.add();
173  up.referencedTime = data.timestamp;
174  up.arrivedTime = data.timestampArrived;
175  up.instancesData = {data.proprioception};
176  }
177 
178  // Exteroception
179  if (data.exteroception)
180  {
181  armem::EntityUpdate& up = update.exteroception.add();
186  up.referencedTime = data.timestamp;
187  up.instancesData = {data.exteroception};
188  }
189 
190  // Extract odometry data.
191  ARMARX_CHECK_NOT_NULL(data.proprioception);
192  const std::string platformKey = "platform";
193  if (data.proprioception->hasElement(platformKey))
194  {
195  ARMARX_DEBUG << "Found odometry data.";
196  auto platformData =
197  aron::data::Dict::DynamicCastAndCheck(data.proprioception->getElement(platformKey));
198  update.localization.emplace_back(getTransform(platformData, data.timestamp));
199  }
200  else
201  {
202  ARMARX_INFO << "No odometry data! "
203  << "(No element '" << platformKey << "' in proprioception data.)"
204  << "\nIf you are using a mobile platform this should not have happened."
205  << "\nThis error is only logged once."
206  << "\nThese keys exist: " << data.proprioception->getAllKeys();
207  noOdometryDataLogged = true;
208  }
209 
210  return update;
211  }
212 
214  RobotStateWriter::getTransform(const aron::data::DictPtr& platformData,
215  const Time& timestamp) const
216  {
217  prop::arondto::Platform platform;
218  platform.fromAron(platformData);
219 
220  const Eigen::Vector3f& relPose = platform.relativePosition;
221 
222  Eigen::Affine3f odometryPose = Eigen::Affine3f::Identity();
223  odometryPose.translation() << relPose.x(), relPose.y(), 0; // TODO set height
224  odometryPose.linear() = simox::math::rpy_to_mat3f(0.f, 0.f, relPose.z());
225 
227  transform.header.parentFrame = armarx::OdometryFrame;
230  transform.header.timestamp = timestamp;
231  transform.transform = odometryPose;
232 
233  return transform;
234  }
235 
236 } // namespace armarx::armem::server::robot_state::proprioception
armarx::armem::server::robot_state::proprioception::RobotStateWriter::Queue
armarx::armem::server::robot_state::proprioception::Queue Queue
Definition: RobotStateWriter.h:60
armarx::armem::server::robot_state::proprioception::RobotStateWriter::buildUpdate
Update buildUpdate(const RobotUnitData &dataQueue)
Definition: RobotStateWriter.cpp:161
armarx::armem::server::robot_state::proprioception::RobotStateWriter::Properties::robotUnitProviderID
armem::MemoryID robotUnitProviderID
Definition: RobotStateWriter.h:92
RobotStateWriter.h
armarx::armem::CommitResult::allErrorMessages
std::vector< std::string > allErrorMessages() const
Definition: Commit.cpp:72
armarx::armem::MemoryID::providerSegmentName
std::string providerSegmentName
Definition: MemoryID.h:52
armarx::armem::EntityUpdate::instancesData
std::vector< aron::data::DictPtr > instancesData
The entity data.
Definition: Commit.h:33
armarx::armem::server::MemoryToIceAdapter
Helps connecting a Memory server to the Ice interface.
Definition: MemoryToIceAdapter.h:19
armarx::armem::server::robot_state::proprioception::RobotStateWriter::connect
void connect(armarx::plugins::DebugObserverComponentPlugin &debugObserverPlugin)
Definition: RobotStateWriter.cpp:47
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::localization::Segment
Definition: Segment.h:43
armarx::armem::server::robot_state::proprioception
Definition: forward_declarations.h:75
constants.h
armarx::armem::robot_state::constants::proprioceptionCoreSegment
const std::string proprioceptionCoreSegment
Definition: constants.h:30
armarx::armem::robot_state::constants::robotRootNodeName
const std::string robotRootNodeName
Definition: constants.h:36
armarx::aron::data::detail::SpecializedVariantBase< data::dto::Dict, Dict >::DynamicCastAndCheck
static PointerType DynamicCastAndCheck(const VariantPtr &n)
Definition: SpecializedVariant.h:135
armarx::memory
Brief description of class memory.
Definition: memory.h:39
armarx::armem::MemoryID::coreSegmentName
std::string coreSegmentName
Definition: MemoryID.h:51
armarx::armem::EntityUpdate::arrivedTime
Time arrivedTime
Time when this update arrived at the memory server.
Definition: Commit.h:62
armarx::armem::server::robot_state::proprioception::RobotStateWriter::debugObserver
std::optional< DebugObserverHelper > debugObserver
Definition: RobotStateWriter.h:96
armarx::status
status
Definition: FiniteStateMachine.h:259
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:523
armarx::DebugObserverHelper::getDebugObserver
const DebugObserverInterfacePrx & getDebugObserver() const
Definition: DebugObserverHelper.cpp:149
armarx::armem::server::robot_state::proprioception::RobotStateWriter::properties
Properties properties
Definition: RobotStateWriter.h:94
FramedPose.h
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::armem::server::segment::SpecializedCoreSegment::doLocked
auto doLocked(FunctionT &&function) const
Definition: SpecializedCoreSegment.h:39
Segment.h
armarx::armem::robot_state::Transform
Definition: types.h:41
armarx::armem::EntityUpdate
An update of an entity for a specific point in time.
Definition: Commit.h:27
DebugObserverComponentPlugin.h
armarx::armem::CommitResult
Result of a Commit.
Definition: Commit.h:110
All.h
armarx::armem::server::robot_state::proprioception::RobotUnitData
Definition: RobotUnitData.h:13
armarx::OdometryFrame
const std::string OdometryFrame
Definition: FramedPose.h:63
Metronome.h
armarx::armem::server::robot_state::proprioception::RobotStateWriter::run
void run(float pollFrequency, Queue &dataBuffer, MemoryToIceAdapter &memory, localization::Segment &localizationSegment)
Reads data from dataQueue and commits to the memory.
Definition: RobotStateWriter.cpp:63
armarx::control::hardware_config::tagName
std::string tagName(ConfigTag tag)
Definition: Config.cpp:302
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
MemoryToIceAdapter.h
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::armem::EntityUpdate::referencedTime
Time referencedTime
Time when this entity update was created (e.g.
Definition: Commit.h:39
armarx::armem::MemoryID::withEntityName
MemoryID withEntityName(const std::string &name) const
Definition: MemoryID.cpp:420
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::armem::server::robot_state::localization::Segment::commitTransform
bool commitTransform(const armem::robot_state::Transform &transform)
Definition: Segment.cpp:163
armarx::transform
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...
Definition: algorithm.h:315
armarx::Logging::tag
LogTag tag
Definition: Logging.h:271
armarx::armem::server::robot_state::proprioception::RobotStateWriter::task
armarx::SimpleRunningTask ::pointer_type task
Definition: RobotStateWriter.h:99
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::server::robot_state::proprioception::RobotStateWriter::Update
Definition: RobotStateWriter.h:71
Logging.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::plugins::DebugObserverComponentPlugin
Brief description of class DebugObserverComponentPlugin.
Definition: DebugObserverComponentPlugin.h:48
armarx::armem::EntityUpdate::entityID
MemoryID entityID
The entity's ID.
Definition: Commit.h:30
armarx::armem::robot_state::constants::exteroceptionCoreSegment
const std::string exteroceptionCoreSegment
Definition: constants.h:31
armarx::DebugObserverHelper
Brief description of class DebugObserverHelper.
Definition: DebugObserverHelper.h:50
armarx::armem::CommitResult::allSuccess
bool allSuccess() const
Definition: Commit.cpp:64