corobot_arm.cpp
Go to the documentation of this file.
00001 /*
00002  * corobot_arm
00003  * Copyright (c) 2008, CoroWare.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  *     * Redistributions of source code must retain the above copyright
00010  *       notice, this list of conditions and the following disclaimer.
00011  *     * Redistributions in binary form must reproduce the above copyright
00012  *       notice, this list of conditions and the following disclaimer in the
00013  *       documentation and/or other materials provided with the distribution.
00014  *     * Neither the name of the <ORGANIZATION> nor the names of its
00015  *       contributors may be used to endorse or promote products derived from
00016  *       this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00019  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00022  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028  * POSSIBILITY OF SUCH DAMAGE.
00029  */
00030 
00031 #include "ros/ros.h"
00032 #include <stdio.h>
00033 #include <math.h>
00034 
00035 #include "std_msgs/Float64.h"
00036 #include "corobot_msgs/MoveArm.h"
00037 #include "corobot_msgs/ServoPosition.h"
00038 #include "corobot_msgs/ServoType.h"
00039 
00040 
00049 //Enumeration to identifies the position of a servo
00050 typedef enum
00051 {
00052         base_rotation,
00053         shoulder,
00054         elbow,
00055         wrist_flex,
00056         wrist_rotation,
00057         gripper
00058 } servo_type;
00059 
00060 //Enumeration to identify the servo controller used for the arm
00061 typedef enum
00062 {
00063         arbotix,
00064         ssc32,
00065         phidget
00066 } hardware_controller;
00067 
00068 // servo type that save data about the connected servos.
00069 typedef struct
00070 {
00071         servo_type type;
00072         int id;
00073         int min_angle;
00074         int max_angle; 
00075 } servo;
00076 
00077 // Publishing topics to control the servos
00078 ros::Publisher position_pub, type_pub; 
00079 
00080 //servo offset, in degrees
00081 double centerOffset = 0.0; 
00082 
00083 // list of connected servos
00084 servo * servos = NULL; 
00085 
00086 //number of connected servos
00087 int number_servo = 0; 
00088 
00089 //which servo controller id used?
00090 hardware_controller controller; 
00091 
00092 //table of publishers, as we need one publisher per servo for the arbotix controller.
00093 ros::Publisher * arbotix_publisher = NULL; 
00094 
00095 
00099 void setServoPosition(const corobot_msgs::MoveArm &msg)
00100 {
00101         corobot_msgs::ServoPosition msg_sending;
00102         
00103         for(int i=0; i<number_servo; i++)
00104         {
00105                 msg_sending.index = -1;
00106 
00107                 //We received the indication on which servo we want to move, so now we are finding the index corresponding to the servo.  
00108                 if(msg.index == msg.BASE_ROTATION && servos[i].type == base_rotation)
00109                         msg_sending.index = servos[i].id;
00110                 if(msg.index == msg.SHOULDER && servos[i].type == shoulder)
00111                         msg_sending.index = servos[i].id;
00112                 if(msg.index == msg.ELBOW && servos[i].type == elbow)
00113                         msg_sending.index = servos[i].id;
00114                 if(msg.index == msg.WRIST_FLEX && servos[i].type == wrist_flex)
00115                         msg_sending.index = servos[i].id;
00116                 if(msg.index == msg.WRIST_ROTATION && servos[i].type == wrist_rotation)
00117                         msg_sending.index = servos[i].id;
00118                 if(msg.index == msg.GRIPPER && servos[i].type == gripper)
00119                         msg_sending.index = servos[i].id;
00120 
00121                 //if we found the corresponding servo, we send it to the driver of the controller board
00122                 if(msg_sending.index != -1)
00123                 {
00124                         msg_sending.position = msg.position + centerOffset;
00125 
00126                         //make sure the position is in the range
00127                         if(msg_sending.position < servos[i].min_angle)
00128                                 msg_sending.position = servos[i].min_angle;
00129                         else if(msg_sending.position > servos[i].max_angle)
00130                                 msg_sending.position = servos[i].max_angle;
00131 
00132                 
00133                         if(controller == arbotix)
00134                         {
00135                                 std_msgs::Float64 msg_arbotix;
00136                                 // the arbotix controller code take angles in radian and not degrees
00137                                 msg_arbotix.data = (msg_sending.position / 180) * M_PI; 
00138                                 arbotix_publisher[i].publish(msg_arbotix);
00139                         }
00140                         else
00141                                 position_pub.publish(msg_sending);
00142                 }
00143         }
00144 }
00145 
00149 void init_servos_db(XmlRpc::XmlRpcValue dynamixels, ros::NodeHandle n)
00150 {
00151         if(dynamixels.hasMember("base"))
00152         {
00153                 servos[number_servo].type = base_rotation;
00154                 servos[number_servo].id = (int) dynamixels["base"]["id"];
00155                 servos[number_servo].min_angle = (int) dynamixels["base"]["min_angle"];
00156                 servos[number_servo].max_angle = (int) dynamixels["base"]["max_angle"];
00157 
00158     //the arbotix controller driver needs one topic per servo motor
00159                 if(controller == arbotix) 
00160                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/base/command", 100);
00161 
00162                 number_servo++;
00163         }
00164         if(dynamixels.hasMember("shoulder"))
00165         {
00166                 servos[number_servo].type = shoulder;
00167                 servos[number_servo].id = (int) dynamixels["shoulder"]["id"];
00168                 servos[number_servo].min_angle = (int) dynamixels["shoulder"]["min_angle"];
00169                 servos[number_servo].max_angle = (int) dynamixels["shoulder"]["max_angle"];
00170 
00171     //the arbotix controller driver needs one topic per servo motor
00172                 if(controller == arbotix)
00173                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/shoulder/command", 100);
00174 
00175                 number_servo++;
00176         }
00177         if(dynamixels.hasMember("shoulder2"))
00178         {
00179                 servos[number_servo].type = shoulder;
00180                 servos[number_servo].id = (int) dynamixels["shoulder2"]["id"];
00181                 servos[number_servo].min_angle = (int) dynamixels["shoulder2"]["min_angle"];
00182                 servos[number_servo].max_angle = (int) dynamixels["shoulder2"]["max_angle"];
00183 
00184     //the arbotix controller driver needs one topic per servo motor
00185                 if(controller == arbotix)
00186                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/shoulder2/command", 100);
00187 
00188                 number_servo++;
00189         }
00190         if(dynamixels.hasMember("elbow"))
00191         {
00192                 servos[number_servo].type = elbow;
00193                 servos[number_servo].id = (int) dynamixels["elbow"]["id"];
00194                 servos[number_servo].min_angle = (int) dynamixels["elbow"]["min_angle"];
00195                 servos[number_servo].max_angle = (int) dynamixels["elbow"]["max_angle"];
00196 
00197     //the arbotix controller driver needs one topic per servo motor
00198                 if(controller == arbotix)
00199                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/elbow/command", 100);
00200         
00201                 number_servo++;
00202         }
00203         if(dynamixels.hasMember("elbow2"))
00204         {
00205                 servos[number_servo].type = elbow;
00206                 servos[number_servo].id = (int) dynamixels["elbow2"]["id"];
00207                 servos[number_servo].min_angle = (int) dynamixels["elbow2"]["min_angle"];
00208                 servos[number_servo].max_angle = (int) dynamixels["elbow2"]["max_angle"];
00209 
00210     //the arbotix controller driver needs one topic per servo motor
00211                 if(controller == arbotix)
00212                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/elbow2/command", 100);
00213 
00214                 number_servo++;
00215         }
00216         if(dynamixels.hasMember("wrist_flex"))
00217         {
00218                 servos[number_servo].type = wrist_flex;
00219                 servos[number_servo].id = (int) dynamixels["wrist_flex"]["id"];
00220                 servos[number_servo].min_angle = (int) dynamixels["wrist_flex"]["min_angle"];
00221                 servos[number_servo].max_angle = (int) dynamixels["wrist_flex"]["max_angle"];
00222 
00223     //the arbotix controller driver needs one topic per servo motor
00224                 if(controller == arbotix)
00225                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/wrist_flex/command", 100);
00226 
00227                 number_servo++;
00228         }
00229         if(dynamixels.hasMember("wrist_rotation"))
00230         {
00231                 servos[number_servo].type = wrist_rotation;
00232                 servos[number_servo].id = (int) dynamixels["wrist_rotation"]["id"];
00233                 servos[number_servo].min_angle = (int) dynamixels["wrist_rotation"]["min_angle"];
00234                 servos[number_servo].max_angle = (int) dynamixels["wrist_rotation"]["max_angle"];
00235 
00236     //the arbotix controller driver needs one topic per servo motor
00237                 if(controller == arbotix)
00238                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/wrist_rotation/command", 100);
00239 
00240                 number_servo++;
00241         }
00242         if(dynamixels.hasMember("gripper"))
00243         {
00244                 servos[number_servo].type = gripper;
00245                 servos[number_servo].id = (int) dynamixels["gripper"]["id"];
00246                 servos[number_servo].min_angle = -180;
00247                 servos[number_servo].max_angle = 180;
00248 
00249     //the arbotix controller driver needs one topic per servo motor
00250                 if(controller == arbotix)
00251                         arbotix_publisher[number_servo] = n.advertise<std_msgs::Float64>("/gripper/command", 100);
00252 
00253                 number_servo++;
00254         }
00255 }
00256 
00257 int main(int argc, char **argv)
00258 {
00259         ros::init(argc, argv, "corobot_arm");
00260         ros::NodeHandle n;
00261         ros::NodeHandle n_private("~");
00262 
00263         //Command received by corobot_teleop or any other controlling node
00264         ros::Subscriber armPos= n.subscribe("armPosition", 100, setServoPosition); 
00265 
00266 
00267         //Set up an offset, in case the servo is not at its default position when it is supposed to  
00268         n_private.param("offset", centerOffset, 0.0);
00269 
00270 
00271         //Read yalm file parameters.
00272         XmlRpc::XmlRpcValue dynamixels;
00273         XmlRpc::XmlRpcValue controller_type;
00274         n_private.param("dynamixels", dynamixels, dynamixels);
00275         n_private.param("controller_type", controller_type, controller_type);
00276 
00277         //Read the type of arm we are controlling
00278         if (strcmp(static_cast<std::string>(controller_type).c_str(), "arbotix") == 0)
00279         {
00280                         controller = arbotix;
00281                         //set the size of the table
00282                         arbotix_publisher = new ros::Publisher[dynamixels.size()];
00283         }
00284         else if (strcmp(static_cast<std::string>(controller_type).c_str(), "ssc32") == 0)
00285         {
00286                         controller = ssc32;
00287         }
00288         else if (strcmp(static_cast<std::string>(controller_type).c_str(), "phidget") == 0)
00289         {
00290                         controller = phidget;
00291         }
00292         //Read information about the servos
00293         servos = (servo*) malloc(dynamixels.size() * sizeof(servo));
00294         init_servos_db(dynamixels, n_private);
00295 
00296 
00297         //Declare the necessary topics
00298         if(controller == phidget) 
00299         {
00300           //Set the position of the servo. Use for phidgetServo and corobot_ssc32
00301                 position_pub = n.advertise<corobot_msgs::ServoPosition>("setPositionServo", 100); 
00302                 
00303                 //Set the type of servos. PhidgetServo needs it.
00304                 type_pub = n.advertise<corobot_msgs::ServoType>("phidgetServo_setType", 100); 
00305 
00306                 corobot_msgs::ServoType typeMsg;
00307         }
00308         else if (controller == ssc32)
00309         {
00310           //Set the position of the servo. Use for phidgetServo and corobot_ssc32
00311                 position_pub = n.advertise<corobot_msgs::ServoPosition>("setPositionServo", 100); 
00312         }
00313 
00314 
00315         if(controller == phidget || controller == ssc32)
00316         { 
00317                 //Make sure that the arm is in the default initial position for non arbotix arms (wrist horizontal, gripper open and shoulder and elbow angle at 0)
00318                 corobot_msgs::ServoPosition msg;
00319 
00320                 ros::spinOnce();
00321                 //We wait 2s to make sure that the node PhidgetServo has already subscribed to the topic
00322                 ros::Rate loop_rate(0.5);  
00323                 loop_rate.sleep();
00324 
00325     //we initialize the servos
00326                 for (int i=0; i<number_servo; i++) 
00327                 {
00328                         msg.index = servos[i].id;
00329                         if(servos[i].type == base_rotation)
00330                                 msg.position = 90;
00331                         else if (servos[i].type == wrist_rotation)
00332                                 msg.position = 90;
00333                         else if (servos[i].type == wrist_flex)
00334                                 msg.position = 90;
00335                         else
00336                                 msg.position = 0;
00337                         position_pub.publish(msg);
00338                 }
00339         }
00340 
00341         ros::spin();
00342         
00343         free(servos);
00344         delete[] arbotix_publisher;
00345         return 0;
00346 }


corobot_arm
Author(s):
autogenerated on Sun Oct 5 2014 23:18:08