00001 /**************************************************************** 00002 * 00003 * Copyright (c) 2011 00004 * All rights reserved. 00005 * 00006 * Hochschule Bonn-Rhein-Sieg 00007 * University of Applied Sciences 00008 * Computer Science Department 00009 * 00010 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00011 * 00012 * Author: 00013 * Jan Paulus, Nico Hochgeschwender, Michael Reckhaus, Azamat Shakhimardanov 00014 * Supervised by: 00015 * Gerhard K. Kraetzschmar 00016 * 00017 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00018 * 00019 * This sofware is published under a dual-license: GNU Lesser General Public 00020 * License LGPL 2.1 and BSD license. The dual-license implies that users of this 00021 * code may choose which terms they prefer. 00022 * 00023 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 00024 * 00025 * Redistribution and use in source and binary forms, with or without 00026 * modification, are permitted provided that the following conditions are met: 00027 * 00028 * * Redistributions of source code must retain the above copyright 00029 * notice, this list of conditions and the following disclaimer. 00030 * * Redistributions in binary form must reproduce the above copyright 00031 * notice, this list of conditions and the following disclaimer in the 00032 * documentation and/or other materials provided with the distribution. 00033 * * Neither the name of the Hochschule Bonn-Rhein-Sieg nor the names of its 00034 * contributors may be used to endorse or promote products derived from 00035 * this software without specific prior written permission. 00036 * 00037 * This program is free software: you can redistribute it and/or modify 00038 * it under the terms of the GNU Lesser General Public License LGPL as 00039 * published by the Free Software Foundation, either version 2.1 of the 00040 * License, or (at your option) any later version or the BSD license. 00041 * 00042 * This program is distributed in the hope that it will be useful, 00043 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00044 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00045 * GNU Lesser General Public License LGPL and the BSD license for more details. 00046 * 00047 * You should have received a copy of the GNU Lesser General Public 00048 * License LGPL and BSD license along with this program. 00049 * 00050 ****************************************************************/ 00051 #include <youbot_driver/youbot/JointLimitMonitor.hpp> 00052 namespace youbot 00053 { 00054 00055 JointLimitMonitor::JointLimitMonitor(const YouBotJointStorage& jointParameters, 00056 const quantity<angular_acceleration>& jointAcceleration) 00057 { 00058 // Bouml preserved body begin 000FAB71 00059 this->storage = jointParameters; 00060 this->acceleration = jointAcceleration.value(); // rad/s^2 00061 brakingDistance = 0; 00062 isbraking = false; 00063 velocityWhenReachedLimit = 0; 00064 00065 // Bouml preserved body end 000FAB71 00066 } 00067 00068 JointLimitMonitor::~JointLimitMonitor() 00069 { 00070 // Bouml preserved body begin 000FABF1 00071 // Bouml preserved body end 000FABF1 00072 } 00073 00074 JointLimitMonitor::JointLimitMonitor(const JointLimitMonitor & source) 00075 { 00076 // Bouml preserved body begin 000FAC71 00077 this->storage = source.storage; 00078 // Bouml preserved body end 000FAC71 00079 } 00080 00081 JointLimitMonitor & JointLimitMonitor::operator=(const JointLimitMonitor & source) 00082 { 00083 // Bouml preserved body begin 000FACF1 00084 this->storage = source.storage; 00085 return *this; 00086 // Bouml preserved body end 000FACF1 00087 } 00088 00089 void JointLimitMonitor::checkLimitsPositionControl(const quantity<plane_angle>& setpoint) 00090 { 00091 // Bouml preserved body begin 000FAD71 00092 if (storage.gearRatio == 0) 00093 { 00094 throw std::out_of_range("A Gear Ratio of zero is not allowed"); 00095 } 00096 00097 if (storage.encoderTicksPerRound == 0) 00098 { 00099 throw std::out_of_range("Zero Encoder Ticks per Round are not allowed"); 00100 } 00101 if (storage.areLimitsActive) 00102 { 00103 00104 quantity<plane_angle> lowLimit = ((double)this->storage.lowerLimit / storage.encoderTicksPerRound) 00105 * storage.gearRatio * (2.0 * M_PI) * radian; 00106 quantity<plane_angle> upLimit = ((double)this->storage.upperLimit / storage.encoderTicksPerRound) 00107 * storage.gearRatio * (2.0 * M_PI) * radian; 00108 00109 if (storage.inverseMovementDirection) 00110 { 00111 upLimit = ((double)-(this->storage.lowerLimit) / storage.encoderTicksPerRound) * storage.gearRatio * (2.0 * M_PI) 00112 * radian; 00113 lowLimit = ((double)-(this->storage.upperLimit) / storage.encoderTicksPerRound) * storage.gearRatio * (2.0 * M_PI) 00114 * radian; 00115 } 00116 00117 if (!((setpoint < upLimit) && (setpoint > lowLimit))) 00118 { 00119 std::stringstream errorMessageStream; 00120 errorMessageStream << "The setpoint angle for joint " << this->storage.jointName 00121 << " is out of range. The valid range is between " << lowLimit << " and " << upLimit << " and it is: " 00122 << setpoint; 00123 throw std::out_of_range(errorMessageStream.str()); 00124 } 00125 } 00126 // Bouml preserved body end 000FAD71 00127 } 00128 00129 void JointLimitMonitor::checkLimitsEncoderPosition(const signed int& setpoint) 00130 { 00131 // Bouml preserved body begin 000FAF71 00132 if (storage.areLimitsActive) 00133 { 00134 if (!((setpoint < this->storage.upperLimit) && (setpoint > this->storage.lowerLimit))) 00135 { 00136 std::stringstream errorMessageStream; 00137 errorMessageStream << "The setpoint angle for joint " << this->storage.jointName 00138 << " is out of range. The valid range is between " << this->storage.lowerLimit << " and " 00139 << this->storage.upperLimit << " and it is: " << setpoint; 00140 throw std::out_of_range(errorMessageStream.str()); 00141 } 00142 } 00143 // Bouml preserved body end 000FAF71 00144 } 00145 00146 void JointLimitMonitor::checkLimitsProcessData(const SlaveMessageInput& messageInput, SlaveMessageOutput& messageOutput) 00147 { 00148 // Bouml preserved body begin 000FCAF1 00149 switch (messageOutput.controllerMode) 00150 { 00151 case POSITION_CONTROL: 00152 break; 00153 case VELOCITY_CONTROL: 00154 if (isbraking == false) 00155 { 00156 calculateBrakingDistance(messageInput); 00157 } 00158 00159 if ((messageInput.actualPosition < bevorLowerLimit && !(messageOutput.value > 0)) 00160 || (messageInput.actualPosition > bevorUpperLimit && !(messageOutput.value < 0))) 00161 { 00162 // messageOutput.value = velocityWhenReachedLimit * this->calculateDamping(messageInput.actualPosition); 00163 messageOutput.value = this->calculateBrakingVelocity(messageInput.actualPosition); 00164 isbraking = true; 00165 } 00166 else 00167 { 00168 isbraking = false; 00169 } 00170 00171 break; 00172 case CURRENT_MODE: 00173 break; //disable limit checker for current mode 00174 /* 00175 if(isbraking == false){ 00176 calculateBrakingDistance(messageInput); 00177 } 00178 00179 if( (messageInput.actualPosition < bevorLowerLimit && !(messageOutput.value > 0)) || (messageInput.actualPosition > bevorUpperLimit && !(messageOutput.value < 0))) { 00180 messageOutput.value = this->calculateBrakingVelocity(messageInput.actualPosition); 00181 messageOutput.controllerMode = VELOCITY_CONTROL; 00182 isbraking = true; 00183 }else{ 00184 isbraking = false; 00185 } 00186 00187 break; 00188 */ 00189 default: 00190 00191 break; 00192 00193 } 00194 00195 // Bouml preserved body end 000FCAF1 00196 } 00197 00198 double JointLimitMonitor::calculateDamping(const int actualPosition) 00199 { 00200 // Bouml preserved body begin 000FAFF1 00201 if (actualPosition <= storage.lowerLimit) 00202 { 00203 return 0.0; 00204 } 00205 if (actualPosition >= storage.upperLimit) 00206 { 00207 return 0.0; 00208 } 00209 if (actualPosition < bevorLowerLimit) 00210 { 00211 return abs(((double)(actualPosition - storage.lowerLimit)) / (bevorLowerLimit - storage.lowerLimit)); 00212 } 00213 if (actualPosition > bevorUpperLimit) 00214 { 00215 return abs(((double)(storage.upperLimit - actualPosition)) / (storage.upperLimit - bevorUpperLimit)); 00216 } 00217 return 0.0; 00218 00219 // Bouml preserved body end 000FAFF1 00220 } 00221 00222 void JointLimitMonitor::calculateBrakingDistance(const SlaveMessageInput& messageInput) 00223 { 00224 // Bouml preserved body begin 000FE471 00225 actualVelocityRPS = (((double)messageInput.actualVelocity / 60.0) * storage.gearRatio * 2.0 * M_PI); // radian_per_second; 00226 00227 brakingDistance = abs( 00228 (((actualVelocityRPS * actualVelocityRPS) / (2.0 * acceleration)) 00229 * ((double)storage.encoderTicksPerRound / (2.0 * M_PI))) / storage.gearRatio); 00230 00231 bevorLowerLimit = storage.lowerLimit + brakingDistance; 00232 bevorUpperLimit = storage.upperLimit - brakingDistance; 00233 velocityWhenReachedLimit = messageInput.actualVelocity; 00234 // Bouml preserved body end 000FE471 00235 } 00236 00237 int JointLimitMonitor::calculateBrakingVelocity(const int actualPosition) 00238 { 00239 // Bouml preserved body begin 000FE4F1 00240 if (actualPosition <= storage.lowerLimit) 00241 { 00242 return 0; 00243 } 00244 if (actualPosition >= storage.upperLimit) 00245 { 00246 return 0; 00247 } 00248 if (actualPosition < bevorLowerLimit) 00249 { 00250 distanceToLimit = ((double)(actualPosition - storage.lowerLimit) / storage.encoderTicksPerRound) * storage.gearRatio 00251 * (2.0 * M_PI); 00252 newVelocity = -sqrt(2.0 * acceleration * distanceToLimit); 00253 return round((newVelocity / (storage.gearRatio * 2.0 * M_PI)) * 60.0); 00254 } 00255 if (actualPosition > bevorUpperLimit) 00256 { 00257 distanceToLimit = ((double)(storage.upperLimit - actualPosition) / storage.encoderTicksPerRound) * storage.gearRatio 00258 * (2.0 * M_PI); 00259 newVelocity = sqrt(2.0 * acceleration * distanceToLimit); 00260 return round((newVelocity / (storage.gearRatio * 2.0 * M_PI)) * 60.0); 00261 } 00262 return 0; 00263 00264 // Bouml preserved body end 000FE4F1 00265 } 00266 00267 } // namespace youbot