KeypointsImpedanceController.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 ...
17 * @author Jianfeng Gao ( jianfeng dot gao at kit dot edu )
18 * @date 2021
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
24
25#include <VirtualRobot/MathTools.h>
26#include <VirtualRobot/RobotNodeSet.h>
27
30
35
37#include <armarx/control/common/control_law/aron/KeypointControllerConfig.aron.generated.h>
39
41{
42 NJointControllerRegistration<NJointKeypointsImpedanceController>
44 "NJointKeypointsImpedanceController");
45
48 const NJointControllerConfigPtr& config,
50 {
51 ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
52
55 {
56 auto configData = ::armarx::fromAronDict<AronDTO, BO>(cfg->config);
57
58 kinematicChainName = configData.nodeSetName;
60 validateConfigData(configData);
61
62 bufferUserToAdditionalTask.reinitAllBuffers(configData);
63 bufferAdditionalTaskToUser.reinitAllBuffers(configData);
64 bufferUserToRt.reinitAllBuffers(configData);
65 }
66
68 VirtualRobot::RobotNodeSetPtr rtRns = rtGetRobot()->getRobotNodeSet(kinematicChainName);
69
70 nonRtRobot = robotUnit->cloneRobot();
71 VirtualRobot::RobotNodeSetPtr nonRtRns = nonRtRobot->getRobotNodeSet(kinematicChainName);
72 robotUnit->updateVirtualRobot(nonRtRobot);
73
76
77 controller.initialize(nonRtRns);
78
79 jointNames.clear();
80 for (size_t i = 0; i < rtRns->getSize(); ++i)
81 {
82 std::string jointName = rtRns->getNode(i)->getName();
83 jointNames.push_back(jointName);
84 ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Torque1DoF);
86 const SensorValueBase* sv = useSensorValue(jointName);
88 auto casted_ct = ct->asA<ControlTarget1DoFActuatorTorque>();
89 ARMARX_CHECK_EXPRESSION(casted_ct);
90 targets.push_back(casted_ct);
91
92 const SensorValue1DoFActuatorTorque* torqueSensor =
93 sv->asA<SensorValue1DoFActuatorTorque>();
94 const SensorValue1DoFActuatorVelocity* velocitySensor =
95 sv->asA<SensorValue1DoFActuatorVelocity>();
96 const SensorValue1DoFActuatorPosition* positionSensor =
97 sv->asA<SensorValue1DoFActuatorPosition>();
98 if (!torqueSensor)
99 {
100 ARMARX_WARNING << "No Torque sensor available for " << jointName;
101 }
102 if (!velocitySensor)
103 {
104 ARMARX_WARNING << "No velocity sensor available for " << jointName;
105 }
106 if (!positionSensor)
107 {
108 ARMARX_WARNING << "No position sensor available for " << jointName;
109 }
110
111 sensorDevices.torqueSensors.push_back(torqueSensor);
112 sensorDevices.velocitySensors.push_back(velocitySensor);
113 sensorDevices.positionSensors.push_back(positionSensor);
114 };
115
116 controlTargets.targets.resize(rtRns->getSize(), 0.);
117 }
118
119 std::string
121 {
122 return "NJointKeypointsImpedanceController";
123 }
124
125 //std::string NJointKeypointsImpedanceController::getKinematicChainName(const Ice::Current &)
126 //{
127 // return kinematicChainName;
128 //}
129
130 void
132 {
133 runTask("NJointTaskspaceAdmittanceAdditionalTask",
134 [&]
135 {
136 CycleUtil c(1);
137 getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
139 << "Create a new thread alone NJointKeypointsImpedanceController";
140 while (getState() == eManagedIceObjectStarted)
141 {
142 if (isControllerActive())
143 {
145 }
146 c.waitForCycleDuration();
147 }
148 });
149 }
150
151 void
153 {
154 robotUnit->updateVirtualRobot(nonRtRobot);
155
156 controller.updateControlStatus(bufferUserToAdditionalTask.getUpToDateReadBuffer(),
157 bufferRtToAdditionalTask.getUpToDateReadBuffer());
158 }
159
160 void
161 NJointKeypointsImpedanceController::rtRun(const IceUtil::Time& /*sensorValuesTimestamp*/,
162 const IceUtil::Time& timeSinceLastIteration)
163 {
164 double deltaT = timeSinceLastIteration.toSecondsDouble();
165 auto& userConfig = bufferUserToRt.getUpToDateReadBuffer();
166
167 if (rtFirstRun.load())
168 {
169 rtFirstRun.store(false);
170 rtReady.store(true);
171 controller.firstRun();
172 }
173
174 auto& s = bufferRtToAdditionalTask.getWriteBuffer();
175 size_t nDoF = sensorDevices.positionSensors.size();
176 for (size_t i = 0; i < nDoF; ++i)
177 {
178 s.jointPosition[i] = sensorDevices.positionSensors[i]->position;
179 s.jointVelocity[i] = sensorDevices.velocitySensors[i]->velocity;
180 s.jointTorque[i] = sensorDevices.torqueSensors[i]->torque;
181 }
182 s.deltaT = deltaT;
183 bufferRtToAdditionalTask.commitWrite();
184
185 controller.run(userConfig, controlTargets);
186
187 for (unsigned int i = 0; i < controlTargets.targets.size(); i++)
188 {
189 targets.at(i)->torque = controlTargets.targets.at(i);
190 if (!targets.at(i)->isValid())
191 {
192 targets.at(i)->torque = 0;
193 }
194 }
195 }
196
197 void
198 NJointKeypointsImpedanceController::updateConfig(const ::armarx::aron::data::dto::DictPtr& dto,
199 const Ice::Current& iceCurrent)
200 {
201 auto configData = ::armarx::fromAronDict<AronDTO, BO>(dto);
202
203 validateConfigData(configData);
204
205 bufferUserToAdditionalTask.getWriteBuffer() = configData;
206 bufferUserToAdditionalTask.commitWrite();
207
208 bufferUserToRt.getWriteBuffer() = configData;
209 bufferUserToRt.commitWrite();
210 }
211
213 NJointKeypointsImpedanceController::getConfig(const Ice::Current& iceCurrent)
214 {
215 auto configData = bufferAdditionalTaskToUser.getUpToDateReadBuffer();
216 return armarx::toAronDict<AronDTO, BO>(configData);
217 }
218
219 void
221 {
222 const auto nDoF = jointNames.size();
223
224 const auto checkSize = [nDoF](const auto& v)
225 { ARMARX_CHECK_EQUAL((unsigned)v.rows(), nDoF); };
226 const auto checkNonNegative = [](const auto& v) { ARMARX_CHECK((v.array() >= 0).all()); };
227
228 if (!configData.desiredNullspaceJointAngles.has_value() and !isControllerActive())
229 {
230 ARMARX_INFO << "No user defined nullspace target, reset to zero with " << VAROUT(nDoF);
231 configData.desiredNullspaceJointAngles = Eigen::VectorXf::Zero(nDoF);
232 reInitPreActivate.store(true);
233 }
234 checkSize(configData.desiredNullspaceJointAngles.value());
235 checkSize(configData.kdNullspaceTorque);
236 checkSize(configData.kpNullspaceTorque);
237
238 checkNonNegative(configData.kdNullspaceTorque);
239 checkNonNegative(configData.kpNullspaceTorque);
240 checkNonNegative(configData.kdImpedance);
241 checkNonNegative(configData.kpImpedance);
242
243 ARMARX_CHECK_GREATER_EQUAL(configData.numPoints, 0);
244 ARMARX_CHECK_GREATER_EQUAL(configData.qvelFilter, 0);
245 ARMARX_CHECK_GREATER_EQUAL(configData.numPoints, 0);
246 ARMARX_CHECK_GREATER_EQUAL(configData.keypointPositionFilter, 0);
247 ARMARX_CHECK_GREATER_EQUAL(configData.keypointVelocityFilter, 0);
248
249 ARMARX_CHECK_EQUAL(configData.keypointKp.size(), configData.numPoints * 3);
250 ARMARX_CHECK_EQUAL(configData.keypointKd.size(), configData.numPoints * 3);
251 ARMARX_CHECK_EQUAL(configData.fixedTranslation.size(), configData.numPoints * 3);
252 }
253
254 void
257 const DebugObserverInterfacePrx& debugObs)
258 {
259 StringVariantBaseMap datafields;
260
261 auto nonRtData = controller.bufferNonRtToOnPublish.getUpToDateReadBuffer();
262 auto rtData = controller.bufferRtToOnPublish.getUpToDateReadBuffer();
263 auto configData = bufferUserToAdditionalTask.getUpToDateReadBuffer();
264
265 common::debugEigenVec(datafields, "kpImpedance", configData.kpImpedance);
266 common::debugEigenVec(datafields, "kdImpedance", configData.kdImpedance);
267
268 common::debugEigenVec(datafields, "forceImpedance", rtData.forceImpedance);
269 common::debugEigenVec(datafields, "desiredJointTorques", rtData.desiredJointTorques);
270 common::debugEigenVec(datafields, "f_Impedance", rtData.forceImpedance);
271 common::debugEigenVec(datafields, "tau_d_joint", rtData.desiredJointTorques);
272
273 common::debugEigenPose(datafields, "current_pose", nonRtData.currentPose);
274 common::debugEigenPose(datafields, "desired_pose", nonRtData.desiredPose);
275 common::debugEigenVec(datafields, "v_d", nonRtData.desiredVel);
276 common::debugEigenVec(datafields, "a_d", nonRtData.desiredAcc);
277 common::debugEigenVec(datafields, "f_density", nonRtData.desiredDensityForce);
278 common::debugEigenVec(datafields, "pointTrackingForce", nonRtData.pointTrackingForce);
280 datafields, "desiredKeypointPosition", nonRtData.desiredKeypointPosition);
282 datafields, "currentKeypointPosition", nonRtData.currentKeypointPosition);
284 datafields, "currentKeypointVelocity", nonRtData.currentKeypointVelocity);
286 datafields, "filteredKeypointPosition", nonRtData.filteredKeypointPosition);
287
288 debugObs->setDebugChannel("NJointKeypointsImpedanceController", datafields);
289 }
290
291 void
293 {
294 VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(kinematicChainName);
295 Eigen::Matrix4f currentPose = rns->getTCP()->getPoseInRootFrame();
296 ARMARX_IMPORTANT << "rt preactivate controller with target pose\n\n" << currentPose;
297 controller.preactivateInit(rns, bufferUserToRt.getUpToDateReadBuffer());
298
299 if (reInitPreActivate.load())
300 {
301 auto& c = bufferUserToAdditionalTask.getWriteBuffer();
302 c.desiredNullspaceJointAngles.value() = rns->getJointValuesEigen();
303
304 bufferUserToAdditionalTask.reinitAllBuffers(c);
305 bufferUserToRt.reinitAllBuffers(c);
306
307 reInitPreActivate.store(false);
308 }
309
310 const auto nDoF = rns->getSize();
311
312 {
313 law::RobotStatus rtToNonRtStatus;
314 rtToNonRtStatus.jointPosition.resize(nDoF, 0.);
315 rtToNonRtStatus.jointVelocity.resize(nDoF, 0.);
316 rtToNonRtStatus.jointTorque.resize(nDoF, 0.);
317 for (size_t i = 0; i < nDoF; ++i)
318 {
319 rtToNonRtStatus.jointPosition[i] = sensorDevices.positionSensors[i]->position;
320 rtToNonRtStatus.jointVelocity[i] = sensorDevices.velocitySensors[i]->velocity;
321 rtToNonRtStatus.jointTorque[i] = sensorDevices.torqueSensors[i]->torque;
322 }
323 bufferRtToAdditionalTask.reinitAllBuffers(rtToNonRtStatus);
324 }
325 }
326
327 void
332} // namespace armarx::control::njoint_controller::task_space
#define VAROUT(x)
constexpr T c
Brief description of class JointControlTargetBase.
This util class helps with keeping a cycle time during a control cycle.
Definition CycleUtil.h:41
ArmarXObjectSchedulerPtr getObjectScheduler() const
int getState() const
Retrieve current state of the ManagedIceObject.
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
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 SensorValueBase class.
const T * asA() const
void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
::armarx::aron::data::dto::DictPtr getConfig(const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointKeypointsImpedanceController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
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 updateConfig(const ::armarx::aron::data::dto::DictPtr &dto, const Ice::Current &iceCurrent=Ice::emptyCurrent) override
NJointController interface.
void rtPreActivateController() override
This function is called before the controller is activated.
#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_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#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< Dict > DictPtr
void debugEigenVec(StringVariantBaseMap &datafields, const std::string &name, Eigen::VectorXf vec)
Definition utils.cpp:190
void debugEigenPose(StringVariantBaseMap &datafields, const std::string &name, Eigen::Matrix4f pose)
Definition utils.cpp:140
NJointControllerRegistration< NJointKeypointsImpedanceController > registrationControllerNJointKeypointsImpedanceController("NJointKeypointsImpedanceController")
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
std::map< std::string, VariantBasePtr > StringVariantBaseMap
::armarx::aron::data::dto::DictPtr toAronDict(const BOType &bo)
T fromAronDict(const ::armarx::aron::data::dto::DictPtr &dto)
IceUtil::Handle< class RobotUnit > RobotUnitPtr
Definition FTSensor.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface > DebugDrawerInterfacePrx
detail::ControlThreadOutputBufferEntry SensorAndControl