Newer
Older
/*
* This file is part of ArmarX.
*
* ArmarX is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* ArmarX is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package RobotAPI::ArmarXObjects::NJointHolonomicPlatformUnitVelocityPassThroughController
* @author Raphael Grimm ( raphael dot grimm at kit dot edu )
* @date 2017
* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
* GNU General Public License
*/
#include "NJointHolonomicPlatformVelocityControllerWithRamp.h"
#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
#include <RobotAPI/components/units/RobotUnit/NJointControllers/NJointControllerRegistry.h>
namespace armarx
{
NJointHolonomicPlatformVelocityControllerWithRamp::
NJointHolonomicPlatformVelocityControllerWithRamp(RobotUnit* prov,
ConfigPtrT cfg,
const VirtualRobot::RobotPtr&) :
ramp(cfg->maxPositionAcceleration, cfg->maxOrientationAcceleration)
{
target = useControlTarget(cfg->platformName, ControlModes::HolonomicPlatformVelocity)
->asA<ControlTargetHolonomicPlatformVelocity>();
ARMARX_CHECK_EXPRESSION(target)
<< "The actuator " << cfg->platformName << " has no control mode "
<< ControlModes::HolonomicPlatformVelocity;
const auto sensor = useSensorValue(cfg->platformName);
ARMARX_CHECK_EXPRESSION(sensor) << "No sensor value for " << cfg->platformName;
velocitySensor = sensor->asA<SensorValueHolonomicPlatformVelocity>();
ARMARX_CHECK_EXPRESSION(velocitySensor)
<< "Sensor value for " << cfg->platformName << " has invalid type";
}
void
NJointHolonomicPlatformVelocityControllerWithRamp::rtPreActivateController()
{
activationVelocity(0) = velocitySensor->velocityX;
activationVelocity(1) = velocitySensor->velocityY;
activationVelocity(2) = velocitySensor->velocityRotation;
activationTime = IceUtil::Time::now();
ramp.init(activationVelocity);
}
void
NJointHolonomicPlatformVelocityControllerWithRamp::rtRun(
const IceUtil::Time& sensorValuesTimestamp,
{
auto commandAge = sensorValuesTimestamp - rtGetControlStruct().commandTimestamp;
if (commandAge > maxCommandDelay && // command must be recent
(rtGetControlStruct().velocityX != 0.0f || rtGetControlStruct().velocityY != 0.0f ||
rtGetControlStruct().velocityRotation !=
0.0f)) // only throw error if any command is not zero
{
throw LocalException(
"Platform target velocity was not set for a too long time: delay: ")
<< commandAge.toSecondsDouble()
<< " s, max allowed delay: " << maxCommandDelay.toSecondsDouble() << " s";
}
else
{
Eigen::Vector3f result;
if (activationTime > rtGetControlStruct().commandTimestamp)
{
// No valid command has been specified. Sane default: come to rest.
const Eigen::Vector3f targetVelocity = Eigen::Vector3f::Zero();
result = ramp.update(targetVelocity, timeSinceLastIteration.toSecondsDouble());
}
else
{
Eigen::Vector3f x(rtGetControlStruct().velocityX,
rtGetControlStruct().velocityY,
rtGetControlStruct().velocityRotation);
result = ramp.update(x, timeSinceLastIteration.toSecondsDouble());
}
target->velocityX = result(0);
target->velocityY = result(1);
target->velocityRotation = result(2);
}
}
void
NJointHolonomicPlatformVelocityControllerWithRamp::setMaxAccelerations(
float maxPositionAcceleration,
float maxOrientationAcceleration)
{
ramp.setMaxPositionAcceleration(maxPositionAcceleration);
ramp.setMaxOrientationAcceleration(maxOrientationAcceleration);
}
NJointControllerRegistration<NJointHolonomicPlatformVelocityControllerWithRamp>
registrationNJointHolonomicPlatformVelocityControllerWithRamp(
"NJointHolonomicPlatformVelocityControllerWithRamp");
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
Cartesian2DimVelocityRamp ::Cartesian2DimVelocityRamp(float maxPositionAcceleration,
float maxOrientationAcceleration) :
maxPositionAcceleration(maxPositionAcceleration),
maxOrientationAcceleration(maxOrientationAcceleration)
{
}
void
Cartesian2DimVelocityRamp::init(const Eigen::Vector3f& state)
{
this->state = state;
}
Eigen::Vector3f
Cartesian2DimVelocityRamp::update(const Eigen::Vector3f& target, float dt)
{
if (dt <= 0)
{
return state;
}
Eigen::Vector3f delta = target - state;
float factor = 1;
Eigen::Vector2f posDelta = delta.block<2, 1>(0, 0);
float posFactor = posDelta.norm() / maxPositionAcceleration / dt;
factor = std::max(factor, posFactor);
float oriFactor = std::abs(delta(2)) / maxOrientationAcceleration / dt;
factor = std::max(factor, oriFactor);
state += delta / factor;
return state;
}
void
Cartesian2DimVelocityRamp::setMaxPositionAcceleration(float maxPositionAcceleration)
{
this->maxPositionAcceleration = maxPositionAcceleration;
}
void
Cartesian2DimVelocityRamp::setMaxOrientationAcceleration(float maxOrientationAcceleration)
{
this->maxOrientationAcceleration = maxOrientationAcceleration;
}
} // namespace armarx