Component.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 control::ArmarXObjects::example_component_plugin_user
17  * @author Fabian Reister ( fabian dot reister at kit dot edu )
18  * @date 2022
19  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20  * GNU General Public License
21  */
22 
23 
24 #include "Component.h"
25 #include <thread>
26 
28 
30 
31 // Include headers you only need in function definitions in the .cpp.
32 
33 // #include <Eigen/Core>
34 
35 // #include <SimoxUtility/color/Color.h>
36 
37 
39 {
40 
41  const std::string Component::defaultName = "example_component_plugin_user";
42 
43 
46  {
49 
50  // Publish to a topic (passing the TopicListenerPrx).
51  // def->topic(myTopicListener);
52 
53  // Subscribe to a topic (passing the topic name).
54  // def->topic<PlatformUnitListener>("MyTopic");
55 
56  // Use (and depend on) another component (passing the ComponentInterfacePrx).
57  // def->component(myComponentProxy)
58 
59 
60  // Add a required property. (The component won't start without a value being set.)
61  // def->required(properties.boxLayerName, "p.box.LayerName", "Name of the box layer in ArViz.");
62 
63  // Add an optionalproperty.
64  // def->optional(
65  // properties.boxLayerName, "p.box.LayerName", "Name of the box layer in ArViz.");
66  // def->optional(properties.numBoxes, "p.box.Number", "Number of boxes to draw in ArViz.");
67 
68  return def;
69  }
70 
71 
72  void
74  {
75  // Topics and properties defined above are automagically registered.
76 
77  // Keep debug observer data until calling `sendDebugObserverBatch()`.
78  // (Requies the armarx::DebugObserverComponentPluginUser.)
79  // setDebugObserverBatchModeEnabled(true);
80  }
81 
82 
83  void
85  {
86 
87  // Load the controllers that we are using here.
89  robotUnit->loadLibFromPackage("armarx_control", "libarmarx_control_njoint_controller.so");
90  robotUnit->loadLibFromPackage("armarx_control", "libarmarx_control_njoint_qp_controller.so");
91 
92  //
93  // Example:
94  //
95  // use of controller builder with defaults
96  //
97  {
98  ARMARX_INFO << "Example 1";
99 
100  auto builder = controllerBuilder<common::ControllerType::TSImpedance>();
101 
102  auto controller = builder.withDefaultConfig()
103  .withNodeSet("RightArm")
104  .create("MyTaskSpaceImpedanceController1");
106 
107  std::this_thread::sleep_for(std::chrono::seconds(1));
108 
109 
110  controller->activate();
111  std::this_thread::sleep_for(std::chrono::seconds(2));
112 
113  }
114 
115 
116  //
117  // Example:
118  //
119  // use of controller builder with defaults (short version)
120  //
121  {
122  ARMARX_INFO << "Example 2";
123 
124  auto builder = controllerBuilder<common::ControllerType::TSImpedance>();
125 
126  auto controller =
127  builder.withNodeSet("RightArm")
128  .create("MyTaskSpaceImpedanceController2"); // implicit withDefaultConfig()
130 
131  controller->activate();
132 
133  std::this_thread::sleep_for(std::chrono::seconds(2));
134  }
135 
136 
137  //
138  // Example:
139  //
140  // use of controller builder with config from file
141  //
142  {
143  ARMARX_INFO << "Example 3";
144 
145  auto builder = controllerBuilder<common::ControllerType::TSImpedance>();
146 
147 
148  auto controller = builder.withDefaultConfig()
149  .withConfig("file provided by Jeff")
150  .withNodeSet("RightArm")
151  .create("MyTaskSpaceImpedanceController3");
153 
154  std::this_thread::sleep_for(std::chrono::seconds(2));
155 
156  controller->updateConfig();
157 
158  std::this_thread::sleep_for(std::chrono::seconds(2));
159 
160  }
161 
162 
163  //
164  // Example:
165  //
166  // use of controller builder with config from memory
167  //
168  // {
169  // ARMARX_INFO << "Example 4";
170 
171  // auto builder = controllerBuilder<common::ControllerType::TSImpedance>();
172 
173  // auto controller = builder.withNodeSet("RightArm")
174  // .withConfig(armarx::armem::MemoryID("memorylink", "to", "config"))
175  // .create("MyTaskSpaceImpedanceController4");
176  // ARMARX_CHECK_NOT_NULL(controller);
177  // }
178 
179 
180  //
181  // Example:
182  //
183  // use of controller builder with config update
184  //
185  {
186  ARMARX_INFO << "Example 5";
187 
188  auto builder = controllerBuilder<common::ControllerType::TSImpedance>();
189 
190  auto controller =
191  builder.withNodeSet("RightArm").create("MyTaskSpaceImpedanceController5");
193 
194  // update some parameters
195  controller->config.kdImpedance *= 2;
196 
197  // send new config to robot unit / the controller
198  controller->updateConfig();
199 
200  // again, update some parameters
201  controller->config.kdImpedance.setOnes();
202  controller->config.kdImpedance *= 42;
203 
204  controller->updateConfig();
205 
206 
207  std::this_thread::sleep_for(std::chrono::seconds(2));
208 
209  controller->activate();
210 
211  std::this_thread::sleep_for(std::chrono::seconds(2));
212 
213  // send new config to robot unit / the controller
214  controller->updateConfig();
215 
216  std::this_thread::sleep_for(std::chrono::seconds(2));
217 
218  controller->deactivate();
219  }
220 
221  //
222  // Example:
223  //
224  // use of controller builder with config access before creation
225  //
226  {
227  ARMARX_INFO << "Example 6";
228 
229  auto builder = controllerBuilder<common::ControllerType::TSImpedance>();
230 
231  // access config before creation
232  builder.config().kdImpedance *= 3;
233 
234  auto controller =
235  builder.withNodeSet("RightArm").create("MyTaskSpaceImpedanceController6");
237 
238  std::this_thread::sleep_for(std::chrono::seconds(2));
239 
240  controller->activate();
241 
242  std::this_thread::sleep_for(std::chrono::seconds(2));
243 
244  controller->deactivate();
245 
246  }
247 
248 
249 
250  //
251  // Example:
252  //
253  // use of controller builder with config access before creation
254  //
255  {
256  ARMARX_INFO << "Example 7";
257 
258  auto builder = controllerBuilder<common::ControllerType::TSImpedance>();
259 
260  // access config before creation
261  builder.config().kdImpedance *= 3;
262 
263  auto controller =
264  builder.withNodeSet("RightArm").create("MyTaskSpaceImpedanceController7");
266 
267  // controller->daemonize();
268 
269  std::this_thread::sleep_for(std::chrono::seconds(2));
270 
271  }
272 
273 
274  ARMARX_INFO << "done.";
275  }
276 
277 
278  void
280  {
281  }
282 
283 
284  void
286  {
287  }
288 
289 
290  std::string
292  {
293  return Component::defaultName;
294  }
295 
296 
297  std::string
299  {
300  return Component::defaultName;
301  }
302 
303 
304  /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
305  void
306  Component::createRemoteGuiTab()
307  {
308  using namespace armarx::RemoteGui::Client;
309 
310  // Setup the widgets.
311 
312  tab.boxLayerName.setValue(properties.boxLayerName);
313 
314  tab.numBoxes.setValue(properties.numBoxes);
315  tab.numBoxes.setRange(0, 100);
316 
317  tab.drawBoxes.setLabel("Draw Boxes");
318 
319  // Setup the layout.
320 
321  GridLayout grid;
322  int row = 0;
323  {
324  grid.add(Label("Box Layer"), {row, 0}).add(tab.boxLayerName, {row, 1});
325  ++row;
326 
327  grid.add(Label("Num Boxes"), {row, 0}).add(tab.numBoxes, {row, 1});
328  ++row;
329 
330  grid.add(tab.drawBoxes, {row, 0}, {2, 1});
331  ++row;
332  }
333 
334  VBoxLayout root = {grid, VSpacer()};
335  RemoteGui_createTab(getName(), root, &tab);
336  }
337 
338 
339  void
340  Component::RemoteGui_update()
341  {
342  if (tab.boxLayerName.hasValueChanged() || tab.numBoxes.hasValueChanged())
343  {
344  std::scoped_lock lock(propertiesMutex);
345  properties.boxLayerName = tab.boxLayerName.getValue();
346  properties.numBoxes = tab.numBoxes.getValue();
347 
348  {
349  setDebugObserverDatafield("numBoxes", properties.numBoxes);
350  setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
351  sendDebugObserverBatch();
352  }
353  }
354  if (tab.drawBoxes.wasClicked())
355  {
356  // Lock shared variables in methods running in seperate threads
357  // and pass them to functions. This way, the called functions do
358  // not need to think about locking.
359  std::scoped_lock lock(propertiesMutex, arvizMutex);
360  drawBoxes(properties, arviz);
361  }
362  }
363  */
364 
365 
366  /* (Requires the armarx::ArVizComponentPluginUser.)
367  void
368  Component::drawBoxes(const Component::Properties& p, viz::Client& arviz)
369  {
370  // Draw something in ArViz (requires the armarx::ArVizComponentPluginUser.
371  // See the ArVizExample in RobotAPI for more examples.
372 
373  viz::Layer layer = arviz.layer(p.boxLayerName);
374  for (int i = 0; i < p.numBoxes; ++i)
375  {
376  layer.add(viz::Box("box_" + std::to_string(i))
377  .position(Eigen::Vector3f(i * 100, 0, 0))
378  .size(20).color(simox::Color::blue()));
379  }
380  arviz.commit(layer);
381  }
382  */
383 
384 
386 
387 } // namespace armarx::control::components::example_component_plugin_user
armarx::control::components::example_component_plugin_user::Component::getDefaultName
std::string getDefaultName() const override
Definition: Component.cpp:291
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::control::components::example_component_plugin_user::Component::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: Component.cpp:45
armarx::control::components::example_component_plugin_user::Component::GetDefaultName
static std::string GetDefaultName()
Get the component's default name.
Definition: Component.cpp:298
controller
Definition: AddOperation.h:39
armarx::control::components::example_component_plugin_user::Component::onDisconnectComponent
void onDisconnectComponent() override
Definition: Component.cpp:279
armarx::control::components::example_component_plugin_user::ARMARX_REGISTER_COMPONENT_EXECUTABLE
ARMARX_REGISTER_COMPONENT_EXECUTABLE(Component, Component::GetDefaultName())
Component.h
armarx::control::components::example_component_plugin_user::Component::onExitComponent
void onExitComponent() override
Definition: Component.cpp:285
armarx::control::client::ComponentPlugin::getRobotUnitPlugin
armarx::plugins::RobotUnitComponentPlugin & getRobotUnitPlugin()
Definition: ComponentPlugin.h:106
armarx::control::components::example_component_plugin_user
Definition: Component.cpp:38
armarx::control::client::ComponentPluginUser::getControlComponentPlugin
ComponentPlugin & getControlComponentPlugin()
Definition: ComponentPlugin.cpp:70
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:74
Decoupled.h
armarx::control::components::example_component_plugin_user::Component::onConnectComponent
void onConnectComponent() override
Definition: Component.cpp:84
armarx::ComponentPropertyDefinitions
Default component property definition container.
Definition: Component.h:70
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::control::components::example_component_plugin_user::Component
Definition: Component.h:46
armarx::control::components::example_component_plugin_user::Component::onInitComponent
void onInitComponent() override
Definition: Component.cpp:73
armarx::plugins::RobotUnitComponentPlugin::getRobotUnit
RobotUnitInterfacePrx getRobotUnit() const
Definition: RobotUnitComponentPlugin.cpp:112
controller_descriptions.h