RobotStateMemory.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 "RobotStateMemory.h"
24 
25 #include <SimoxUtility/algorithm/contains.h>
26 #include <SimoxUtility/algorithm/get_map_keys_values.h>
27 #include <SimoxUtility/algorithm/string.h>
28 
33 
34 #include <RobotAPI/interface/core/PoseBase.h>
39 
41 {
42 
44  descriptionSegment(iceAdapter()),
45  proprioceptionSegment(iceAdapter()),
46  exteroceptionSegment(iceAdapter()),
47  localizationSegment(iceAdapter()),
48  commonVisu(descriptionSegment, proprioceptionSegment, localizationSegment)
49  {
50  addPlugin(debugObserver);
51  ARMARX_CHECK_NOT_NULL(debugObserver);
52 
53  addPlugin(robotUnit.plugin);
54  ARMARX_CHECK_NOT_NULL(robotUnit.plugin);
55  robotUnit.plugin->setRobotUnitAsOptionalDependency(true);
56  robotUnit.dataBuffer = std::make_unique<RobotUnit::Queue>();
57  }
58 
60 
63  {
66 
67  const std::string robotUnitPrefix = RobotUnit::sensorValuePrefix;
68 
69 
70  defs->optional(robotUnit.waitForRobotUnit,
71  "WaitForRobotUnit",
72  "Add the robot unit as dependency to the component. This memory requires a "
73  "running RobotUnit, therefore we should add it as explicit dependency.");
74 
75  defs->optional(robotUnit.reader.properties.sensorPrefix,
76  robotUnitPrefix + "SensorValuePrefix",
77  "Prefix of all sensor values.");
78  defs->optional(robotUnit.pollFrequency,
79  robotUnitPrefix + "UpdateFrequency",
80  "The frequency to store values in Hz. All other values get discarded. "
81  "Minimum is 1, max is " +
82  std::to_string(RobotUnit::ROBOT_UNIT_MAXIMUM_FREQUENCY) + ".")
83  .setMin(1)
84  .setMax(RobotUnit::ROBOT_UNIT_MAXIMUM_FREQUENCY);
85 
86 
87  const std::string prefix = "mem.";
88 
90 
91  descriptionSegment.defineProperties(defs, prefix + "desc.");
92  exteroceptionSegment.defineProperties(defs, prefix + "ext.");
93  proprioceptionSegment.defineProperties(defs, prefix + "prop.");
94  localizationSegment.defineProperties(defs, prefix + "loc.");
95  commonVisu.defineProperties(defs, prefix + "visu.");
96 
97  return defs;
98  }
99 
100  std::string
102  {
103  return "RobotStateMemory";
104  }
105 
106  void
108  {
109  descriptionSegment.init();
110  proprioceptionSegment.init();
111  exteroceptionSegment.init();
112  localizationSegment.init();
113  commonVisu.init();
114 
115  robotUnit.pollFrequency =
116  std::clamp(robotUnit.pollFrequency, 0.F, RobotUnit::ROBOT_UNIT_MAXIMUM_FREQUENCY);
117 
118  std::vector<std::string> includePaths;
119  std::vector<std::string> packages = armarx::Application::GetProjectDependencies();
120  packages.push_back(Application::GetProjectName());
121 
122  for (const std::string& projectName : packages)
123  {
124  if (projectName.empty())
125  {
126  continue;
127  }
128 
129  const CMakePackageFinder project(projectName);
130  const std::string pathsString = project.getIncludePaths();
131  std::vector<std::string> projectIncludePaths = simox::alg::split(pathsString, ";,");
132  includePaths.insert(
133  includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
134  }
135 
136  if (robotUnit.waitForRobotUnit)
137  {
138  usingProxy(robotUnit.plugin->getRobotUnitName());
139  }
140  }
141 
142  void
144  {
145  {
146  ARMARX_CHECK(not robotUnit.reader.task or not robotUnit.reader.task->isRunning());
147  ARMARX_CHECK(not robotUnit.writer.task or not robotUnit.writer.task->isRunning());
148  robotUnit.dataBuffer = std::make_unique<RobotUnit::Queue>();
149  }
150  ARMARX_CHECK_NOT_NULL(debugObserver->getDebugObserver());
151 
152  // 1. General setup
153  localizationSegment.onConnect();
154  commonVisu.connect(getArvizClient(), debugObserver->getDebugObserver());
155 
156  // 2. Check for RobotUnit. If RobotUnit is enabled. Otherwise, we do not wait for a streaming service and do not set up the segments
157  if (robotUnit.plugin->hasRobotUnitName())
158  {
159  robotUnit.plugin->waitUntilRobotUnitIsRunning();
160  const RobotUnitInterfacePrx robotUnitPrx = robotUnit.plugin->getRobotUnit();
161 
162  robotUnit.reader.setTag(getName());
163  robotUnit.writer.setTag(getName());
164 
165  descriptionSegment.onConnect(robotUnitPrx);
166  proprioceptionSegment.onConnect(robotUnitPrx);
167 
168  robotUnit.reader.connect(
169  *robotUnit.plugin,
170  *debugObserver,
171  proprioceptionSegment.getRobotUnitProviderID().providerSegmentName);
172  robotUnit.writer.connect(*debugObserver);
173  robotUnit.writer.properties.robotUnitProviderID =
174  proprioceptionSegment.getRobotUnitProviderID();
175 
176  robotUnit.reader.task = new SimpleRunningTask<>(
177  [this]() { robotUnit.reader.run(robotUnit.pollFrequency, *robotUnit.dataBuffer); },
178  "Robot Unit Reader");
179  robotUnit.writer.task = new SimpleRunningTask<>(
180  [this]()
181  {
182  robotUnit.writer.run(robotUnit.pollFrequency,
183  *robotUnit.dataBuffer,
184  iceAdapter(),
185  localizationSegment);
186  },
187  "Robot State Writer");
188 
189  startRobotUnitStream();
190  }
191 
192  }
193 
194  void
196  {
197  stopRobotUnitStream();
198  }
199 
200  void
202  {
203  stopRobotUnitStream();
204  }
205 
206  armarx::PoseBasePtr
208  const std::string& robotName,
209  const ::Ice::Current& /*unused*/)
210  {
211  const armem::Time timestamp{armem::Duration::MicroSeconds(timestampUs)};
212  ARMARX_DEBUG << "Getting robot pose of robot " << robotName << " at timestamp " << timestamp
213  << ".";
214 
215  auto poseMap = localizationSegment.getRobotGlobalPoses(timestamp);
216 
217  const bool robotNameFound = simox::alg::contains_key(poseMap, robotName);
218  ARMARX_CHECK(robotNameFound)
219  << "Robot with name " << robotName << " does not exist at or before timestamp "
220  << timestamp << ".\n"
221  << "Available robots are: " << simox::alg::get_keys(poseMap);
222 
223  return {new Pose(poseMap[robotName].matrix())};
224  }
225 
226  /*************************************************************/
227  // RobotUnit Streaming functions
228  /*************************************************************/
229 
230 
231  void
232  RobotStateMemory::startRobotUnitStream()
233  {
234  ARMARX_INFO << "Starting RobotUnit stream";
235  ARMARX_CHECK(robotUnit.plugin->robotUnitIsRunning());
236 
237  if (robotUnit.reader.task->isRunning() || robotUnit.writer.task->isRunning())
238  {
239  if (robotUnit.reader.task->isRunning() && robotUnit.writer.task->isRunning())
240  {
241  return;
242  }
243  ARMARX_WARNING << "Found inconsistency in running tasks. Restarting all!";
244  stopRobotUnitStream();
245  }
246  {
247  std::stringstream ss;
248  ss << "Getting sensor values for:" << std::endl;
249  for (const auto& [name, dataEntry] : robotUnit.reader.description.entries)
250  {
251  const std::string type =
252  RobotUnitDataStreaming::DataEntryNames.to_name(dataEntry.type);
253  ss << "\t" << name << " (type: '" << type << "')" << std::endl;
254  }
255  ARMARX_INFO << ss.str();
256  }
257 
258  robotUnit.reader.task->start();
259  robotUnit.writer.task->start();
260  }
261 
262  void
263  RobotStateMemory::stopRobotUnitStream()
264  {
265  ARMARX_INFO << "Stopping RobotUnit stream";
266  robotUnit.dataBuffer->close();
267  robotUnit.reader.task->stop();
268  ARMARX_VERBOSE << "RobotUnit reader stopped";
269  robotUnit.writer.task->stop();
270  ARMARX_VERBOSE << "RobotUnit writer stopped";
271  }
272 
273 } // namespace armarx::armem::server::robot_state
armarx::armem::robot_state::memoryID
const MemoryID memoryID
Definition: memory_ids.cpp:28
armarx::SimpleRunningTask
Usage:
Definition: TaskUtil.h:70
armarx::ArVizComponentPluginUser::getArvizClient
armarx::viz::Client & getArvizClient()
Definition: ArVizComponentPlugin.h:45
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::Application::GetProjectName
static const std::string & GetProjectName()
Definition: Application.cpp:863
armarx::armem::server::robot_state::RobotStateMemory::~RobotStateMemory
~RobotStateMemory() override
armarx::armem::server::robot_state::Visu::init
void init()
Definition: Visu.cpp:62
armarx::armem::MemoryID::providerSegmentName
std::string providerSegmentName
Definition: MemoryID.h:52
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
RobotStateMemory.h
Pose.h
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::description::Segment::onConnect
void onConnect(const RobotUnitInterfacePrx &robotUnitPrx)
Definition: Segment.cpp:44
armarx::armem::server::robot_state::RobotStateMemory::getDefaultName
std::string getDefaultName() const override
Retrieve default name of component.
Definition: RobotStateMemory.cpp:101
armarx::CMakePackageFinder
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Definition: CMakePackageFinder.h:53
armarx::armem::server::robot_state::proprioception::Segment::init
void init() override
Definition: Segment.cpp:46
armarx::armem::server::plugins::ReadWritePluginUser::setMemoryName
void setMemoryName(const std::string &memoryName)
Definition: ReadWritePluginUser.cpp:25
armarx::ManagedIceObject::addPlugin
PluginT * addPlugin(const std::string prefix="", ParamsT &&...params)
Definition: ManagedIceObject.h:182
armarx::armem::server::robot_state::RobotStateMemory::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: RobotStateMemory.cpp:195
armarx::armem::server::robot_state::RobotStateMemory::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: RobotStateMemory.cpp:107
project
std::string project
Definition: VisualizationRobot.cpp:82
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
clamp
double clamp(double x, double a, double b)
Definition: point.hpp:125
armarx::armem::server::robot_state
Definition: RobotStateMemory.cpp:40
armarx::armem::server::robot_state::localization::Segment::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="") override
Definition: Segment.cpp:46
armarx::armem::server::robot_state::Visu::connect
void connect(const viz::Client &arviz, DebugObserverInterfacePrx debugObserver=nullptr)
Definition: Visu.cpp:67
armarx::armem::server::robot_state::RobotStateMemory::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: RobotStateMemory.cpp:62
armarx::DebugObserverHelper::getDebugObserver
const DebugObserverInterfacePrx & getDebugObserver() const
Definition: DebugObserverHelper.cpp:149
armarx::armem::server::robot_state::RobotStateMemory::getGlobalRobotPose
armarx::PoseBasePtr getGlobalRobotPose(Ice::Long timestamp, const std::string &robotName, const ::Ice::Current &) override
Definition: RobotStateMemory.cpp:207
armarx::armem::server::robot_state::localization::Segment::onConnect
void onConnect()
Definition: Segment.cpp:65
armarx::armem::server::segment::SpecializedCoreSegment::init
virtual void init() override
Definition: SpecializedCoreSegment.cpp:49
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::armem::server::robot_state::localization::Segment::getRobotGlobalPoses
RobotPoseMap getRobotGlobalPoses(const armem::Time &timestamp) const
Definition: Segment.cpp:127
DebugObserverComponentPlugin.h
armarx::VariantType::Long
const VariantTypeId Long
Definition: Variant.h:917
armarx::armem::server::robot_state::proprioception::Segment::getRobotUnitProviderID
const armem::MemoryID & getRobotUnitProviderID() const
Definition: Segment.cpp:156
armarx::armem::server::plugins::ReadWritePluginUser::iceAdapter
MemoryToIceAdapter & iceAdapter()
Definition: ReadWritePluginUser.cpp:112
armarx::armem::server::robot_state::RobotStateMemory::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: RobotStateMemory.cpp:201
armarx::armem::server::robot_state::RobotStateMemory::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: RobotStateMemory.cpp:143
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
aron_conversions.h
ExpressionException.h
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:70
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::armem::server::robot_state::RobotStateMemory::RobotStateMemory
RobotStateMemory()
Definition: RobotStateMemory.cpp:43
armarx::armem::laser_scans::constants::memoryName
const std::string memoryName
Definition: constants.h:28
armarx::RobotUnitDataStreaming::DataEntryNames
const simox::meta::EnumNames< DataEntryType > DataEntryNames
Definition: aron_conversions.cpp:58
IceUtil::Handle< class PropertyDefinitionContainer >
IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface >
armarx::armem::server::robot_state::proprioception::Segment::onConnect
void onConnect(RobotUnitInterfacePrx robotUnitPrx)
Definition: Segment.cpp:55
ice_conversions_templates.h
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:107
armarx::armem::server::robot_state::localization::Segment::init
void init() override
Definition: Segment.cpp:56
Logging.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::core::time::Duration::MicroSeconds
static Duration MicroSeconds(std::int64_t microSeconds)
Constructs a duration in microseconds.
Definition: Duration.cpp:27
Visu.h
armarx::armem::server::robot_state::Visu::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="visu.")
Definition: Visu.cpp:42
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:151
armarx::armem::server::segment::SpecializedCoreSegment::defineProperties
virtual void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="") override
Definition: SpecializedCoreSegment.cpp:33
armarx::Application::GetProjectDependencies
static const Ice::StringSeq & GetProjectDependencies()
Definition: Application.cpp:870
memory_ids.h
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:36
armarx::armem::server::robot_state::proprioception::Segment::defineProperties
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="") override
Definition: Segment.cpp:36