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
102  update.localization)
103  {
104  localizationSegment.doLocked(
105  [&localizationSegment, &transform]()
106  { localizationSegment.commitTransform(transform); });
107  }
108  endLocalization = std::chrono::high_resolution_clock::now();
109 
110  if (not resultProprioception.allSuccess())
111  {
112  ARMARX_WARNING << "Could not commit data to proprioception segment in memory. "
113  "Error message: "
114  << resultProprioception.allErrorMessages();
115  }
116 
117  if (not resultExteroception.allSuccess())
118  {
119  ARMARX_WARNING << "Could not commit data to exteroception segment in memory. "
120  "Error message: "
121  << resultExteroception.allErrorMessages();
122  }
123 
124  if (debugObserver)
125  {
126  auto end = std::chrono::high_resolution_clock::now();
127 
128  debugObserver->setDebugObserverDatafield("RobotStateWriter | t Commit (ms)",
129  toDurationMs(start, end));
130  debugObserver->setDebugObserverDatafield(
131  "RobotStateWriter | t Commit 1. Build Update (ms)",
132  toDurationMs(start, endBuildUpdate));
133  debugObserver->setDebugObserverDatafield(
134  "RobotStateWriter | t Commit 2. Proprioception (ms)",
135  toDurationMs(endBuildUpdate, endProprioception));
136  debugObserver->setDebugObserverDatafield(
137  "RobotStateWriter | t Commit 3. Localization (ms)",
138  toDurationMs(endProprioception, endLocalization));
139  }
140  }
141  else
142  {
143  ARMARX_WARNING << "Queue pull was not successful. "
144  << static_cast<std::underlying_type<boost::queue_op_status>::type>(
145  status);
146  }
147 
148  if (debugObserver)
149  {
150  debugObserver->sendDebugObserverBatch();
151  }
152  }
153  }
154 
155  bool
156  RobotStateWriter::isRunning()
157  {
158  return task and not task->isStopped();
159  }
160 
161  RobotStateWriter::Update
163  {
164  // Send batch to memory
165  Update update;
166 
167  if (data.proprioception)
168  {
169  armem::EntityUpdate& up = update.proprioception.add();
174  up.referencedTime = data.timestamp;
175  up.arrivedTime = data.timestampArrived;
176  up.instancesData = {data.proprioception};
177  }
178 
179  // Exteroception
180  if (data.exteroception)
181  {
182  armem::EntityUpdate& up = update.exteroception.add();
187  up.referencedTime = data.timestamp;
188  up.instancesData = {data.exteroception};
189  }
190 
191  // Extract odometry data.
192  ARMARX_CHECK_NOT_NULL(data.proprioception);
193  const std::string platformKey = "platform";
194  if (data.proprioception->hasElement(platformKey))
195  {
196  ARMARX_DEBUG << "Found odometry data.";
197  auto platformData =
198  aron::data::Dict::DynamicCastAndCheck(data.proprioception->getElement(platformKey));
199  update.localization.emplace_back(getTransform(platformData, data.timestamp));
200  }
201  else
202  {
203  ARMARX_INFO << "No odometry data! "
204  << "(No element '" << platformKey << "' in proprioception data.)"
205  << "\nIf you are using a mobile platform this should not have happened."
206  << "\nThis error is only logged once."
207  << "\nThese keys exist: " << data.proprioception->getAllKeys();
208  noOdometryDataLogged = true;
209  }
210 
211  return update;
212  }
213 
215  RobotStateWriter::getTransform(const aron::data::DictPtr& platformData,
216  const Time& timestamp) const
217  {
218  prop::arondto::Platform platform;
219  platform.fromAron(platformData);
220 
221  const Eigen::Vector3f& relPose = platform.relativePosition;
222 
223  Eigen::Isometry3f odometryPose = Eigen::Isometry3f::Identity();
224  odometryPose.translation() << relPose.x(), relPose.y(), 0; // TODO set height
225  odometryPose.linear() = simox::math::rpy_to_mat3f(0.f, 0.f, relPose.z());
226 
228  transform.header.parentFrame = armarx::OdometryFrame;
231  transform.header.timestamp = timestamp;
232  transform.transform = odometryPose;
233 
234  return transform;
235  }
236 
237 } // 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:61
armarx::armem::server::robot_state::proprioception::RobotStateWriter::buildUpdate
Update buildUpdate(const RobotUnitData &dataQueue)
Definition: RobotStateWriter.cpp:162
armarx::armem::server::robot_state::proprioception::RobotStateWriter::Properties::robotUnitProviderID
armem::MemoryID robotUnitProviderID
Definition: RobotStateWriter.h:88
RobotStateWriter.h
armarx::armem::CommitResult::allErrorMessages
std::vector< std::string > allErrorMessages() const
Definition: Commit.cpp:73
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:31
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:42
armarx::armem::server::robot_state::proprioception
Definition: forward_declarations.h:78
constants.h
armarx::armem::robot_state::constants::proprioceptionCoreSegment
const std::string proprioceptionCoreSegment
Definition: constants.h:30
armarx::armem::robot_state::localization::Transform
Definition: types.h:154
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:134
armarx::memory
Brief description of class memory.
Definition: memory.h:38
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:60
armarx::armem::server::robot_state::proprioception::RobotStateWriter::debugObserver
std::optional< DebugObserverHelper > debugObserver
Definition: RobotStateWriter.h:93
armarx::status
status
Definition: FiniteStateMachine.h:244
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
armarx::DebugObserverHelper::getDebugObserver
const DebugObserverInterfacePrx & getDebugObserver() const
Definition: DebugObserverHelper.cpp:187
armarx::armem::server::robot_state::proprioception::RobotStateWriter::properties
Properties properties
Definition: RobotStateWriter.h:91
FramedPose.h
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::armem::server::segment::SpecializedCoreSegment::doLocked
auto doLocked(FunctionT &&function) const
Definition: SpecializedCoreSegment.h:38
Segment.h
armarx::armem::EntityUpdate
An update of an entity for a specific point in time.
Definition: Commit.h:25
DebugObserverComponentPlugin.h
armarx::armem::CommitResult
Result of a Commit.
Definition: Commit.h:105
All.h
armarx::armem::server::robot_state::proprioception::RobotUnitData
Definition: RobotUnitData.h:13
armarx::OdometryFrame
const std::string OdometryFrame
Definition: FramedPose.h:66
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:301
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:68
MemoryToIceAdapter.h
armarx::armem::server::robot_state::localization::Segment::commitTransform
bool commitTransform(const armem::robot_state::localization::Transform &transform)
Definition: Segment.cpp:145
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:351
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:37
armarx::armem::MemoryID::withEntityName
MemoryID withEntityName(const std::string &name) const
Definition: MemoryID.cpp:425
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::Logging::tag
LogTag tag
Definition: Logging.h:278
armarx::armem::server::robot_state::proprioception::RobotStateWriter::task
armarx::SimpleRunningTask ::pointer_type task
Definition: RobotStateWriter.h: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:99
armarx::armem::server::robot_state::proprioception::RobotStateWriter::Update
Definition: RobotStateWriter.h:70
Logging.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::plugins::DebugObserverComponentPlugin
Brief description of class DebugObserverComponentPlugin.
Definition: DebugObserverComponentPlugin.h:46
armarx::armem::EntityUpdate::entityID
MemoryID entityID
The entity's ID.
Definition: Commit.h:28
armarx::armem::robot_state::constants::exteroceptionCoreSegment
const std::string exteroceptionCoreSegment
Definition: constants.h:31
armarx::DebugObserverHelper
Brief description of class DebugObserverHelper.
Definition: DebugObserverHelper.h:51
armarx::armem::CommitResult::allSuccess
bool allSuccess() const
Definition: Commit.cpp:64