PhidgetStepper.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009, CoroWare
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
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Stanford U. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this 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 OWNER 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 <stdio.h>
00032 #include <math.h>
00033 #include <stdint.h>
00034 
00035 #include "std_msgs/Float64.h"
00036 #include "corobot_msgs/MoveArm.h"
00037 #include "corobot_msgs/PosMsg.h"
00038 #include <phidget21.h>
00039 
00040 #include <corobot_diagnostics/diagnostics.h>
00041 #include <diagnostic_updater/diagnostic_updater.h>
00042 #include <diagnostic_updater/publisher.h>
00043 
00044 //Enumeration to identify the position of a stepper
00045 typedef enum
00046 {
00047   armBaseRotation,
00048   armShoulder,
00049         armElbow,
00050         armWrist,
00051         armGripper,
00052   leftWheel,
00053   rightWheel
00054 } stepper_type;
00055 
00056 
00057 // stepper type that save data about the connected stepper.
00058 typedef struct
00059 {
00060         stepper_type type;
00061         int serial; 
00062         CPhidgetStepperHandle handle;
00063 } stepper;
00064 
00065 // list of connected servos
00066 stepper* steppers = NULL; 
00067 
00068 // The number of connected stepper motors
00069 int number_stepper = 0; 
00070 
00071 // used for diagnostics purpose
00072 int stepperError = 0; 
00073 
00074 // Publish the position of the left and right wheel motors, if any is present
00075 ros::Publisher positionPublisher; 
00076 
00077 // Publish the position of stepper motors present in an arm
00078 ros::Publisher stepperPositionPublisher; 
00079 int64_t leftPosition = 0;
00080 int64_t rightPosition = 0;
00081 
00082 
00086 void setStepperPosition(const corobot_msgs::MoveArm &msg)
00087 {
00088         int err;
00089         for(int i; i<number_stepper; i++)
00090         {
00091 
00092                 //We received the indication on which stepper we want to move, so now we are finding the index corresponding to the servo.  
00093                 if(msg.index == steppers[i].type)
00094                 {
00095                     err = CPhidgetStepper_setTargetPosition(steppers[i].handle, 0, msg.position);       
00096                     if (err != 0)
00097                     {
00098                         stepperError = 2;
00099                     }
00100                     else
00101                     {
00102                         stepperError = 0;
00103                     }
00104                 }
00105         }
00106 }
00107 
00108 // publishes the "encoder" position
00109 void publishPosition()
00110 {
00111   corobot_msgs::PosMsg msg;
00112   msg.px = leftPosition;
00113   msg.py = rightPosition;
00114 
00115   positionPublisher.publish(msg);
00116 }
00117 
00118 // Callback called by the phidgets API. It gives us the latest position of the motor
00119 int positionCallback(CPhidgetStepperHandle phid, void *userPtr, int index, __int64 position)
00120 {
00121   stepper * stepperMoved = (stepper*) userPtr;
00122 
00123   // The information is treated differently whether it is concerning a wheel servo or an arm
00124   if (stepperMoved->type == leftWheel)
00125   {
00126     leftPosition = position;
00127     publishPosition();
00128   }
00129   else if (stepperMoved->type == rightWheel)
00130   {
00131     rightPosition = position;
00132     publishPosition();
00133   }
00134   else
00135   {
00136     corobot_msgs::MoveArm msg;
00137     msg.index = stepperMoved->type;
00138     msg.position = position;
00139 
00140     // Publishes the position of the stepper
00141     stepperPositionPublisher.publish(msg);
00142   } 
00143 }
00144 
00145 
00149 void init_servos_db(XmlRpc::XmlRpcValue stepper_list, ros::NodeHandle n)
00150 {
00151   // Search for all possible stepper position and find the serial number assigned to it.
00152   // A serial number of -1 means no stepper controller board is assigned at this position, else it is the serial number of the board assigned.
00153 
00154         if(stepper_list.hasMember("leftWheel") && (int)stepper_list["leftWheel"]["serial"] != -1)
00155         {
00156     // save the type of the stepper motor
00157                 steppers[number_stepper].type = leftWheel;
00158     // save the serial number of the stepper motor board
00159                 steppers[number_stepper].serial = (int) stepper_list["leftWheel"]["serial"];
00160     steppers[number_stepper].handle = 0;
00161         
00162                 number_stepper++;
00163         }
00164         if(stepper_list.hasMember("rightWheel") && (int)stepper_list["leftWheel"]["serial"] != -1)
00165         {
00166                 steppers[number_stepper].type = rightWheel;
00167                 steppers[number_stepper].serial = (int) stepper_list["rightWheel"]["serial"];
00168     steppers[number_stepper].handle = 0;
00169         
00170                 number_stepper++;
00171         }
00172         if(stepper_list.hasMember("armBaseRotation") && (int)stepper_list["leftWheel"]["serial"] != -1)
00173         {
00174                 steppers[number_stepper].type = armBaseRotation;
00175                 steppers[number_stepper].serial = (int) stepper_list["armBaseRotation"]["serial"];
00176     steppers[number_stepper].handle = 0;
00177         
00178                 number_stepper++;
00179         }
00180         if(stepper_list.hasMember("armShoulder") && (int)stepper_list["leftWheel"]["serial"] != -1)
00181         {
00182                 steppers[number_stepper].type = armShoulder;
00183                 steppers[number_stepper].serial = (int) stepper_list["armShoulder"]["serial"];
00184     steppers[number_stepper].handle = 0;
00185         
00186                 number_stepper++;
00187         }
00188         if(stepper_list.hasMember("armElbow") && (int)stepper_list["leftWheel"]["serial"] != -1)
00189         {
00190                 steppers[number_stepper].type = armElbow;
00191                 steppers[number_stepper].serial = (int) stepper_list["armElbow"]["serial"];
00192     steppers[number_stepper].handle = 0;
00193         
00194                 number_stepper++;
00195         }
00196         if(stepper_list.hasMember("armWrist") && (int)stepper_list["leftWheel"]["serial"] != -1)
00197         {
00198                 steppers[number_stepper].type = armWrist;
00199                 steppers[number_stepper].serial = (int) stepper_list["armWrist"]["serial"];
00200     steppers[number_stepper].handle = 0;
00201         
00202                 number_stepper++;
00203         }
00204         if(stepper_list.hasMember("armGripper") && (int)stepper_list["leftWheel"]["serial"] != -1)
00205         {
00206                 steppers[number_stepper].type = armGripper;
00207                 steppers[number_stepper].serial = (int) stepper_list["armGripper"]["serial"];
00208     steppers[number_stepper].handle = 0;
00209         
00210                 number_stepper++;
00211         }
00212 }
00213 
00214 // Intiailise all the stepper motor boards that have been registered in the yaml file and previously read.
00215 void init_stepper_boards()
00216 {
00217     int err;
00218     for(int i; i<number_stepper; i++)
00219           {
00220       // create the stepper motor object
00221             err = CPhidgetStepper_create (&(steppers[i].handle));
00222             if (err != 0)
00223             {
00224                     ROS_ERROR("error create the Phidget stepper controller device of serial number %d", steppers[i].serial);
00225                     stepperError = 1;
00226             }
00227             // Open the Phidgets board
00228             err = CPhidget_open((CPhidgetHandle)steppers[i].handle, steppers[i].serial);
00229             if (err != 0)
00230             {
00231                     ROS_ERROR("error opening the Phidget stepper controller device of serial number %d", steppers[i].serial);
00232                     stepperError = 1;
00233             }
00234       // Set the position callback
00235             CPhidgetStepper_set_OnPositionChange_Handler(steppers[i].handle, &positionCallback, (void*) &(steppers[i]));
00236       // Attach the board.
00237       if((err = CPhidget_waitForAttachment((CPhidgetHandle)steppers[i].handle, 10000)))
00238             {
00239                     ROS_ERROR("Problem waiting for attachment of Phidget stepper controller of serial number %d", steppers[i].serial);
00240                     stepperError = 1;
00241             }
00242       // Engage the stepper motor
00243             if(err = CPhidgetStepper_setEngaged(steppers[i].handle, 0, 1))
00244             {
00245                     ROS_ERROR("Problem engaging Phidget stepper controller of serial number %d", steppers[i].serial);
00246                     stepperError = 1;
00247             }
00248         }
00249 }
00250 
00251 // Diagnostic
00252 void stepper_diagnostic (diagnostic_updater::DiagnosticStatusWrapper &stat)
00253 {
00254   if (stepperError == 0)
00255   {
00256     stat.summaryf(diagnostic_msgs::DiagnosticStatus::OK, "initialized");
00257   }
00258   else if (stepperError == 1)
00259   {
00260     stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "Phidget Stepper cannot be initialized");
00261     stat.addf("Recommendation", PHIDGET_STEPPER_ERROR_CONNECTION);
00262   }
00263   else if (stepperError == 2)
00264   {
00265     stat.summaryf(diagnostic_msgs::DiagnosticStatus::ERROR, "The Phidget Stepper motor cannot be moved");
00266     stat.addf("Recommendation",ERROR_MOVING_ARM);
00267   }
00268 }
00269 
00270 
00271 int main(int argc, char **argv)
00272 {
00273         ros::init(argc, argv, "phidget_stepper");
00274         ros::NodeHandle n;
00275         ros::NodeHandle n_private("~");
00276   diagnostic_updater::Updater updater;
00277 
00278         //Read yalm file parameters.
00279         XmlRpc::XmlRpcValue stepper_list;
00280   n_private.param("stepper_list", stepper_list, stepper_list);
00281 
00282 
00283         //Read information about the servos
00284         steppers = (stepper*) malloc(stepper_list.size() * sizeof(stepper));
00285         init_servos_db(stepper_list, n_private);
00286 
00287   //Diagnostic
00288   updater.setHardwareIDf("Phidget");
00289   // Function executed with updater.update()
00290   updater.add("Stepper", stepper_diagnostic);
00291 
00292   // Initialize all the boards using the serial numbers we got.
00293   init_stepper_boards();
00294 
00295 
00296   //Subscribe to the topic
00297   ros::Subscriber stepperPos= n.subscribe("stepperPosition", 100, setStepperPosition);
00298     
00299   //Advertise topic
00300   positionPublisher= n.advertise<corobot_msgs::PosMsg>("position_data", 100);
00301   stepperPositionPublisher = n.advertise<corobot_msgs::MoveArm>("stepper_position",100);
00302   ros::Rate rate(50);
00303     
00304   while(ros::ok())
00305   {
00306       updater.update();
00307       ros::spinOnce();
00308       rate.sleep();
00309   }
00310         
00311         free(steppers);
00312         return 0;
00313 }


phidget_stepper
Author(s):
autogenerated on Wed Aug 26 2015 11:10:14