NJointCartesianVelocityControllerWithRamp.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarX
19 * @author Sonja Marahrens( sonja.marahrens at kit dot edu)
20 * @date 2018
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
25
26#include <VirtualRobot/IK/DifferentialIK.h>
27#include <VirtualRobot/Robot.h>
28#include <VirtualRobot/RobotNodeSet.h>
29
31
32#include "../RobotUnit.h"
33
34#define DEFAULT_TCP_STRING "default TCP"
35
36namespace armarx
37{
38
39 NJointControllerRegistration<NJointCartesianVelocityControllerWithRamp>
41 "NJointCartesianVelocityControllerWithRamp");
42
43 std::string
45 {
46 return "NJointCartesianVelocityControllerWithRamp";
47 }
48
50 RobotUnit* robotUnit,
51 const NJointCartesianVelocityControllerWithRampConfigPtr& config,
53 {
54 ARMARX_CHECK_EXPRESSION(robotUnit);
55 ARMARX_CHECK_EXPRESSION(!config->nodeSetName.empty());
57 VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(config->nodeSetName);
58 ARMARX_CHECK_EXPRESSION(rns) << config->nodeSetName;
59 for (size_t i = 0; i < rns->getSize(); ++i)
60 {
61 std::string jointName = rns->getNode(i)->getName();
62 ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
63 const SensorValueBase* sv = useSensorValue(jointName);
64 targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
65
66 const SensorValue1DoFActuatorFilteredVelocity* filteredVelocitySensor =
67 sv->asA<SensorValue1DoFActuatorFilteredVelocity>();
68 const SensorValue1DoFActuatorVelocity* velocitySensor =
69 sv->asA<SensorValue1DoFActuatorVelocity>();
70 ARMARX_CHECK_EXPRESSION(filteredVelocitySensor || velocitySensor);
71 if (filteredVelocitySensor)
72 {
73 ARMARX_IMPORTANT << "Using filtered velocity for joint " << jointName;
74 velocitySensors.push_back(&filteredVelocitySensor->filteredvelocity);
75 }
76 else if (velocitySensor)
77 {
78 ARMARX_IMPORTANT << "Using raw velocity for joint " << jointName;
79 velocitySensors.push_back(&velocitySensor->velocity);
80 }
81 };
82
83 VirtualRobot::RobotNodePtr tcp =
84 (config->tcpName.empty() || config->tcpName == DEFAULT_TCP_STRING)
85 ? rns->getTCP()
86 : rtGetRobot()->getRobotNode(config->tcpName);
87 ARMARX_CHECK_EXPRESSION(tcp) << config->tcpName;
88
89 nodeSetName = config->nodeSetName;
90 jointLimitAvoidanceScale = config->jointLimitAvoidanceScale;
91 KpJointLimitAvoidance = config->KpJointLimitAvoidance;
92 mode = ModeFromIce(config->mode);
93
94 controller.reset(
96 Eigen::VectorXf::Zero(rns->getSize()),
97 mode,
98 config->maxPositionAcceleration,
99 config->maxOrientationAcceleration,
100 config->maxNullspaceAcceleration));
101 }
102
103 void
105 {
106#pragma GCC diagnostic push
107#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
108 Eigen::VectorXf currentJointVelocities(velocitySensors.size());
109 for (size_t i = 0; i < velocitySensors.size(); i++)
110 {
111 currentJointVelocities(i) = *velocitySensors.at(i);
112 }
113 controller->setCurrentJointVelocity(currentJointVelocities);
114#pragma GCC diagnostic pop
115 ARMARX_IMPORTANT << "initial joint velocities: " << currentJointVelocities.transpose();
116 }
117
118 void
119 NJointCartesianVelocityControllerWithRamp::rtRun(const IceUtil::Time& sensorValuesTimestamp,
120 const IceUtil::Time& timeSinceLastIteration)
121 {
122 Eigen::VectorXf x;
123 if (mode == VirtualRobot::IKSolver::All)
124 {
125 x.resize(6);
129 }
130 else if (mode == VirtualRobot::IKSolver::Position)
131 {
132 x.resize(3);
134 }
135 else if (mode == VirtualRobot::IKSolver::Orientation)
136 {
137 x.resize(3);
140 }
141 else
142 {
143 // No mode has been set
144 return;
145 }
146
147 Eigen::VectorXf jnv =
148 KpJointLimitAvoidance * controller->controller.calculateJointLimitAvoidance();
149 jnv += controller->controller.calculateNullspaceVelocity(x, jointLimitAvoidanceScale, mode);
150 Eigen::VectorXf jointTargetVelocities =
151 controller->calculate(x, jnv, timeSinceLastIteration.toSecondsDouble());
152 for (size_t i = 0; i < targets.size(); ++i)
153 {
154 targets.at(i)->velocity = jointTargetVelocities(i);
155 }
156 }
157
158 void
160 float maxOrientationAcceleration,
161 float maxNullspaceAcceleration,
162 const Ice::Current&)
163 {
164 controller->setMaxAccelerations(
165 maxPositionAcceleration, maxOrientationAcceleration, maxNullspaceAcceleration);
166 }
167
168 void
170 float vy,
171 float vz,
172 float vrx,
173 float vry,
174 float vrz,
175 const Ice::Current&)
176 {
185 }
186
187 void
189 float jointLimitAvoidanceScale,
190 const Ice::Current&)
191 {
192 this->jointLimitAvoidanceScale = jointLimitAvoidanceScale;
193 }
194
195 void
197 const Ice::Current&)
198 {
199 this->KpJointLimitAvoidance = KpJointLimitAvoidance;
200 }
201
202 void
204 {
206#pragma GCC diagnostic push
207#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
208 controller->setCurrentJointVelocity(Eigen::VectorXf::Zero(velocitySensors.size()));
209#pragma GCC diagnostic pop
217 }
218
219 void
223
224 const std::string&
226 {
227 return nodeSetName;
228 }
229
232 {
233 return {{"ControllerTarget", createTargetLayout()},
234 {"ControllerParameters", createParameterLayout()}};
235 }
236
237 void
239 const std::string& name,
240 const StringVariantBaseMap& valueMap,
241 const Ice::Current&)
242 {
243 if (name == "ControllerTarget")
244 {
246 getWriterControlStruct().xVel = valueMap.at("x")->getFloat();
247 getWriterControlStruct().yVel = valueMap.at("y")->getFloat();
248 getWriterControlStruct().zVel = valueMap.at("z")->getFloat();
249 getWriterControlStruct().rollVel = valueMap.at("roll")->getFloat();
250 getWriterControlStruct().pitchVel = valueMap.at("pitch")->getFloat();
251 getWriterControlStruct().yawVel = valueMap.at("yaw")->getFloat();
252 KpJointLimitAvoidance = valueMap.at("KpJointLimitAvoidance")->getFloat();
253 jointLimitAvoidanceScale = valueMap.at("jointLimitAvoidanceScale")->getFloat();
255 }
256 else if (name == "ControllerParameters")
257 {
259 setMaxAccelerations(valueMap.at("maxPositionAcceleration")->getFloat(),
260 valueMap.at("maxOrientationAcceleration")->getFloat(),
261 valueMap.at("maxNullspaceAcceleration")->getFloat());
262 }
263 else
264 {
265 ARMARX_WARNING << "Unknown function name called: " << name;
266 }
267 }
268
269 WidgetDescription::VBoxLayoutPtr
271 {
272 LayoutBuilder layout;
273 layout.addSlider("x", -100, 100, 0);
274 layout.addSlider("y", -100, 100, 0);
275 layout.addSlider("z", -100, 100, 0);
276 layout.addSlider("roll", -0.5, 0.5, 0);
277 layout.addSlider("pitch", -0.5, 0.5, 0);
278 layout.addSlider("yaw", -0.5, 0.5, 0);
279 layout.newLine();
280 layout.addSlider("KpJointLimitAvoidance", -10, 10, KpJointLimitAvoidance);
281 layout.addSlider("jointLimitAvoidanceScale", -10, 10, jointLimitAvoidanceScale);
282 return layout.getLayout();
283 }
284
285 WidgetDescription::VBoxLayoutPtr
287 {
288 LayoutBuilder layout;
289 layout.addSlider(
290 "maxPositionAcceleration", 0, 1000, controller->getMaxPositionAcceleration());
291 layout.addSlider(
292 "maxOrientationAcceleration", 0, 100, controller->getMaxOrientationAcceleration());
293 layout.addSlider(
294 "maxNullspaceAcceleration", 0, 100, controller->getMaxNullspaceAcceleration());
295 return layout.getLayout();
296 }
297
300 const VirtualRobot::RobotPtr& robot,
301 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
302 const std::map<std::string, ConstSensorDevicePtr>&)
303 {
304 using namespace armarx::WidgetDescription;
305 HBoxLayoutPtr layout = new HBoxLayout;
306
307 LabelPtr label = new Label;
308 label->text = "nodeset name";
309 layout->children.emplace_back(label);
310 StringComboBoxPtr box = new StringComboBox;
311 box->defaultIndex = 0;
312
313 box->options = robot->getRobotNodeSetNames();
314 box->name = "nodeSetName";
315 layout->children.emplace_back(box);
316
317 LabelPtr labelTCP = new Label;
318 labelTCP->text = "tcp name";
319 layout->children.emplace_back(labelTCP);
320 StringComboBoxPtr boxTCP = new StringComboBox;
321 boxTCP->defaultIndex = 0;
322
323 boxTCP->options = robot->getRobotNodeNames();
324 boxTCP->options.insert(boxTCP->options.begin(), DEFAULT_TCP_STRING);
325 boxTCP->name = "tcpName";
326 layout->children.emplace_back(boxTCP);
327
328 LabelPtr labelMode = new Label;
329 labelMode->text = "mode";
330 layout->children.emplace_back(labelMode);
331 StringComboBoxPtr boxMode = new StringComboBox;
332
333 boxMode->options = {"Position", "Orientation", "Both"};
334 boxMode->name = "mode";
335 layout->children.emplace_back(boxMode);
336 layout->children.emplace_back(new HSpacer);
337 boxMode->defaultIndex = 2;
338
339
340 auto addSlider = [&](const std::string& label, float max, float defaultValue)
341 {
342 layout->children.emplace_back(new Label(false, label));
343 FloatSliderPtr floatSlider = new FloatSlider;
344 floatSlider->name = label;
345 floatSlider->min = 0;
346 floatSlider->defaultValue = defaultValue;
347 floatSlider->max = max;
348 layout->children.emplace_back(floatSlider);
349 };
350 addSlider("maxPositionAcceleration", 1000, 100);
351 addSlider("maxOrientationAcceleration", 10, 1);
352 addSlider("maxNullspaceAcceleration", 10, 2);
353 addSlider("KpJointLimitAvoidance", 10, 2);
354 addSlider("jointLimitAvoidanceScale", 10, 2);
355
356 return layout;
357 }
358
359 NJointCartesianVelocityControllerWithRampConfigPtr
361 const StringVariantBaseMap& values)
362 {
363 return new NJointCartesianVelocityControllerWithRampConfig(
364 values.at("nodeSetName")->getString(),
365 values.at("tcpName")->getString(),
366 IceModeFromString(values.at("mode")->getString()),
367 values.at("maxPositionAcceleration")->getFloat(),
368 values.at("maxOrientationAcceleration")->getFloat(),
369 values.at("maxNullspaceAcceleration")->getFloat(),
370 values.at("KpJointLimitAvoidance")->getFloat(),
371 values.at("jointLimitAvoidanceScale")->getFloat());
372 }
373
374 VirtualRobot::IKSolver::CartesianSelection
376 {
377 //ARMARX_IMPORTANT_S << "the mode is " << mode;
378 if (mode == "Position")
379 {
380 return VirtualRobot::IKSolver::CartesianSelection::Position;
381 }
382 if (mode == "Orientation")
383 {
384 return VirtualRobot::IKSolver::CartesianSelection::Orientation;
385 }
386 if (mode == "Both")
387 {
388 return VirtualRobot::IKSolver::CartesianSelection::All;
389 }
390 ARMARX_ERROR_S << "invalid mode " << mode;
391 return (VirtualRobot::IKSolver::CartesianSelection)0;
392 }
393
394 CartesianSelectionMode::CartesianSelection
396 {
397 if (mode == "Position")
398 {
399 return CartesianSelectionMode::CartesianSelection::ePosition;
400 }
401 if (mode == "Orientation")
402 {
403 return CartesianSelectionMode::CartesianSelection::eOrientation;
404 }
405 if (mode == "Both")
406 {
407 return CartesianSelectionMode::CartesianSelection::eAll;
408 }
409 ARMARX_ERROR_S << "invalid mode " << mode;
410 return (CartesianSelectionMode::CartesianSelection)0;
411 }
412
413 VirtualRobot::IKSolver::CartesianSelection
415 const CartesianSelectionMode::CartesianSelection mode)
416 {
417 if (mode == CartesianSelectionMode::CartesianSelection::ePosition)
418 {
419 return VirtualRobot::IKSolver::CartesianSelection::Position;
420 }
421 if (mode == CartesianSelectionMode::CartesianSelection::eOrientation)
422 {
423 return VirtualRobot::IKSolver::CartesianSelection::Orientation;
424 }
425 if (mode == CartesianSelectionMode::CartesianSelection::eAll)
426 {
427 return VirtualRobot::IKSolver::CartesianSelection::All;
428 }
429 ARMARX_ERROR_S << "invalid mode " << mode;
430 return (VirtualRobot::IKSolver::CartesianSelection)0;
431 }
432
433
434} // namespace armarx
int Label(int n[], int size, int *curLabel, MiscLib::Vector< std::pair< int, size_t > > *labels)
Definition Bitmap.cpp:801
Brief description of class JointControlTargetBase.
WidgetDescription::VBoxLayoutPtr getLayout() const
void addSlider(const std::string &label, float min, float max, float value)
NJointCartesianVelocityControllerWithRamp(RobotUnit *robotUnit, const NJointCartesianVelocityControllerWithRampConfigPtr &config, const VirtualRobot::RobotPtr &)
void setMaxAccelerations(float maxPositionAcceleration, float maxOrientationAcceleration, float maxNullspaceAcceleration, const Ice::Current &=Ice::emptyCurrent) override
static WidgetDescription::WidgetPtr GenerateConfigDescription(const VirtualRobot::RobotPtr &, const std::map< std::string, ConstControlDevicePtr > &, const std::map< std::string, ConstSensorDevicePtr > &)
WidgetDescription::StringWidgetDictionary getFunctionDescriptions(const Ice::Current &) const override
static NJointCartesianVelocityControllerWithRampConfigPtr GenerateConfigFromVariants(const StringVariantBaseMap &values)
static VirtualRobot::IKSolver::CartesianSelection ModeFromString(const std::string mode)
static VirtualRobot::IKSolver::CartesianSelection ModeFromIce(const CartesianSelectionMode::CartesianSelection mode)
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
void setJointLimitAvoidanceScale(float jointLimitAvoidanceScale, const Ice::Current &) override
void setKpJointLimitAvoidance(float KpJointLimitAvoidance, const Ice::Current &) override
void setTargetVelocity(float vx, float vy, float vz, float vrx, float vry, float vrz, const Ice::Current &) override
static CartesianSelectionMode::CartesianSelection IceModeFromString(const std::string mode)
void callDescribedFunction(const std::string &name, const StringVariantBaseMap &valueMap, const Ice::Current &) override
void rtPreActivateController() override
This function is called before the controller is activated.
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
The RobotUnit class manages a robot and its controllers.
Definition RobotUnit.h:192
The SensorValueBase class.
const T * asA() const
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:216
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
::IceInternal::Handle<::armarx::WidgetDescription::Widget > WidgetPtr
::std::map<::std::string, ::armarx::WidgetDescription::WidgetPtr > StringWidgetDictionary
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::map< std::string, VariantBasePtr > StringVariantBaseMap
NJointControllerRegistration< NJointCartesianVelocityControllerWithRamp > registrationControllerNJointCartesianVelocityControllerWithRamp("NJointCartesianVelocityControllerWithRamp")
std::vector< T > max(const std::vector< T > &v1, const std::vector< T > &v2)