servo_node.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2014, Osnabrueck University
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  * * Redistributions of source code must retain the above copyright notice,
00009  *   this list of conditions and the following disclaimer.
00010  * * Redistributions in binary form must reproduce the above copyright notice,
00011  *   this list of conditions and the following disclaimer in the documentation
00012  *   and/or other materials provided with the distribution.
00013  * * Neither the name of the Osnabrueck University nor the names of its
00014  *   contributors may be used to endorse or promote products derived from this
00015  *   software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
00028  */
00029 
00030 #include <ros/ros.h>
00031 #include "kurt3d/ServoCommand.h"
00032 #include <sensor_msgs/JointState.h>
00033 #include <sstream>
00034 #include "USBInterface.h"
00035 #include <iostream>
00036 #include <boost/thread.hpp>
00037 #define _USE_MATH_DEFINES
00038 
00039 #define RAD(GRAD) ((GRAD * (float)M_PI) / (float)180)
00040 
00041 #define SERVO_RANGE 1000
00042 #define SERVO_MIN 1000
00043 
00044 static ros::Publisher state_pub;
00045 
00046 static sensor_msgs::JointState currentState;
00047 
00048 static double min_pos[5] =
00049 {
00050     RAD(-50.0),//fertig
00051     RAD(-65.0),//fertig
00052     RAD(-65.0),//fertig
00053     RAD(-50.0),//fertig
00054     RAD(-65.0) //fertig
00055 };
00056 static double max_pos[5] =
00057 {
00058     RAD(60.0),
00059     RAD(45.0),
00060     RAD(45.0),
00061     RAD(60.0),
00062     RAD(45.0)
00063 };
00064 
00065 static std::string jointNames[5] =
00066 { "drehobjekt_1_to_balken_1",
00067   "servo_1_a_to_wing_1_a",
00068   "servo_1_b_to_wing_1_b",
00069   "servo_2_a_to_wing_2_a",
00070   "servo_2_b_to_wing_2_b"};
00071 
00072 
00073 boost::mutex& mut()
00074 {
00075     static boost::mutex m;
00076     return m;
00077 }
00078 
00079 void setJointState(int channel, double angle)
00080 {
00081     currentState.header.stamp = ros::Time::now();
00082 
00083     currentState.position[channel] = angle;
00084 }
00085 
00086 void moveServo(const sensor_msgs::JointState& req, bool secure)
00087 {
00088     boost::lock_guard<boost::mutex> _(mut());
00089 
00090     USBPololuInterface usb;
00091 
00092     uscSettings settings;
00093     usb.setUscSettings(settings);
00094 
00095     for(size_t i = 0; i < req.name.size(); i++)
00096     {
00097       ROS_INFO("Channel: [%s] Target: [%f] Speed: [%f]",req.name[i].c_str(),req.position[i],req.velocity[i]);
00098       int channel;
00099       for(channel = 0; channel < 5; channel++)
00100         if(req.name[i] == jointNames[channel])
00101           break;
00102 
00103       if(channel == 5)
00104         continue;
00105 
00106       double angle = req.position[i];
00107 
00108       if(angle < min_pos[channel])
00109       {
00110           ROS_INFO("Required Angle out of range!");
00111           angle = min_pos[channel];
00112       }
00113 
00114       else if(angle > max_pos[channel])
00115       {
00116           ROS_INFO("Required Angle out of range!");
00117           angle = max_pos[channel];
00118       }
00119 
00120       // speed not calibrated
00121       ushort speed = req.velocity[i] * 10;
00122       usb.setSpeed(channel, speed);
00123 
00124       double target = angle;
00125 
00126       // Flip rotation of servo
00127       if(channel == 2 || channel == 4|| channel == 0) target *= -1.0;
00128 
00129       target -= min_pos[channel];
00130 
00131       target /=  (max_pos[channel] - min_pos[channel]);
00132 
00133       target *= SERVO_RANGE;
00134 
00135       target += SERVO_MIN;
00136 
00137       if(secure)
00138       {
00139           usb.moveToTarget(channel, target);
00140       }
00141       else
00142       {
00143           usb.setTarget(channel, target);
00144       }
00145       // As the board position information seems biased we just assume the requested angle was reached.
00146       setJointState(channel, angle);
00147     }
00148 
00149     state_pub.publish(currentState);
00150 
00151     std::cout << "Reported servo status: " << std::endl;
00152 }
00153 
00154 
00155 void servoCallback(const sensor_msgs::JointState::ConstPtr& req)
00156 {
00157   ROS_INFO("A servo movement was requested by topic");
00158   moveServo(*req, false);
00159 }
00160 
00161 
00162 bool nod(kurt3d::ServoCommand::Request  &req,
00163          kurt3d::ServoCommand::Response &res)
00164 {
00165   ROS_INFO("A servo movement was requested by service");
00166   moveServo(req.joint_goal, true);
00167 
00168   res.finished = true;
00169   return true;
00170 }
00171 
00172 int main(int argc, char **argv)
00173 {
00174   ros::init(argc, argv, "servo_node");
00175 
00176   ros::NodeHandle n;
00177 
00178   // inits the service
00179   ros::ServiceServer service = n.advertiseService("servo_node", nod);
00180 
00181   // inits the publisher
00182   state_pub = n.advertise<sensor_msgs::JointState>("joint_states", 1);
00183 
00184   // inits the subscriber
00185   ros::Subscriber sub = n.subscribe("servo_control", 5, servoCallback);
00186 
00187 
00188   // init the current State
00189   currentState = sensor_msgs::JointState();
00190   currentState.name.resize(5);
00191   currentState.position.resize(5);
00192 
00193   // populate the current State with the values of the servos
00194   for (int i = 0; i < 5; i++)
00195   {
00196       setJointState(i, 0.0);
00197       currentState.name[i] = jointNames[i];
00198   }
00199 
00200 
00201   ROS_INFO("Ready to control servos.");
00202 
00203   while(ros::ok())
00204   {
00205       {
00206           boost::lock_guard<boost::mutex> _(mut());
00207 
00208           currentState.header.stamp = ros::Time::now();
00209           state_pub.publish(currentState);
00210       }
00211 
00212       ros::spinOnce();
00213   }
00214 
00215   return 0;
00216 }


kurt3d
Author(s): Thomas Wiemann, Benjamin Kisliuk, Alexander Mock
autogenerated on Wed Sep 16 2015 10:24:29