teleop_arm_dish.cpp
Go to the documentation of this file.
00001 /*
00002  * teleop_arm_dish.h
00003  * Copyright 2013 University of Massachusetts Lowell
00004  * Author: Jonathan Hasenzahl
00005  */
00006 
00007 #include "arm/teleop_arm_dish.h"
00008 #include "arm/cartesian_move.h"
00009 #include "arm/cartesian_moves.h"
00010 #include "arm/constant_move_time.h"
00011 #include "time_server/time_srv.h"
00012 #include "arm/movement_definitions.h"
00013 #include <cmath>
00014 
00015 #define MIDPOINT 4.5
00016 
00020 TeleopArmDish::TeleopArmDish()
00021 {
00022         init();
00023         run();
00024 }
00025 
00033 void TeleopArmDish::init()
00034 {
00035     // Get parameters
00036     getParams();
00037 
00038     // Initialize client and publisher
00039     //     Cartesian commands or constant move commands: for now you can use one
00040     //     or the other. Keep one commented out.
00041     //cmd_pub_ = n_.advertise<arm::cartesian_moves>("cartesian_moves", 1000);
00042     cmd_pub_ = n_.advertise<arm::constant_move_time>("constant_move_times", 1);
00043     time_client_ = n_.serviceClient<time_server::time_srv>("time_service");
00044 
00045     // Wait for subscriber
00046     ROS_INFO("Waiting for subscriber...");
00047     while (cmd_pub_.getNumSubscribers() < 1 && ros::ok());
00048 
00049     // Initialize subscriber
00050     cat_sub_ = n_.subscribe("cats", 1000, &TeleopArmDish::callback, this);
00051 }
00052 
00056 void TeleopArmDish::getParams()
00057 {
00058     // Get ARM speed parameter
00059     if (!n_.getParam("arm_speed", speed_))
00060     {
00061         ROS_WARN("Could not load arm_speed parameter, default is 2");
00062         speed_ = 2;
00063     }
00064 
00065     // Get ARM safe range parameter
00066     if (!n_.getParam("arm_safe_range", arm_safe_range_))
00067     {
00068         ROS_WARN("Could not load arm_safe_range parameter, default is 20000.0");
00069         arm_safe_range_ = 20000.0;
00070     }
00071 
00072     // Get max range from midpoint parameter
00073     if (!n_.getParam("max_range_from_midpoint", max_range_from_midpoint_))
00074     {
00075         ROS_WARN("Could not load max_range_from_midpoint parameter, default is 1.0");
00076         max_range_from_midpoint_ = 1.0;
00077     }
00078 }
00079 
00086 void TeleopArmDish::run()
00087 {
00088     while(ros::ok())
00089     {
00090         ros::spinOnce();
00091         if (!queue_.empty())
00092         {
00093             // Use one or the other, keep only one uncommented
00094             //publishCartesianMove();
00095             publishConstantMove();
00096         }
00097     }
00098 }
00099 
00108 void TeleopArmDish::callback(const burst_calc::cat::ConstPtr& c)
00109 {
00110     queue_.push(*c);
00111 }
00112 
00120 void TeleopArmDish::publishCartesianMove()
00121 {
00122     burst_calc::cat cat = queue_.front();
00123     queue_.pop();
00124     time_server::time_srv cat_start;
00125     cat_start.request.target = cat.header.stamp;
00126 
00127     if (time_client_.call(cat_start))
00128     {
00129         printf("CAT start time : %f\n", cat.header.stamp.toSec());
00130         printf("Server time    : %f\n", cat_start.response.actual.toSec());
00131         printf("Delta          : %f\n", cat_start.response.delta.toSec());
00132 
00133         // The delta shouldn't be negative (server time is <= CAT time)
00134         if (cat_start.response.delta >= ros::Duration(0))
00135         {
00136             ROS_INFO("Sleeping for %.3fs", cat_start.response.delta.toSec());
00137             (cat_start.response.delta - ros::Duration(0.1)).sleep();
00138 
00139             //
00140             arm::cartesian_moves cmd;
00141             cmd.header.stamp = cat.header.stamp;
00142             cmd.end = cat.end;
00143             int size = cat.cas.size();
00144             for (int i = 0; i < size; i++)
00145             {
00146                 arm::cartesian_move move;
00147                 move.header.stamp = cat.header.stamp;
00148 
00149                 // Currently all axes have the same speed
00150                 move.speeds.fill(static_cast<int8_t>(speed_));
00151 
00152                 // Right now only X/Y movement is implemented
00153                 move.positions[X] = getArmCoord(cat.cas[i].x);
00154                 move.positions[Y] = getArmCoord(cat.cas[i].y);
00155                 move.positions[Z] = ORIGIN_POSITION[Z];
00156                 move.positions[YAW] = ORIGIN_POSITION[YAW];
00157                 move.positions[PITCH] = ORIGIN_POSITION[PITCH];
00158                 move.positions[ROLL] = ORIGIN_POSITION[ROLL];
00159                 move.positions[GRIP] = ORIGIN_POSITION[GRIP];
00160 
00161                 //printf("CA  : x[%10.3f] y[%10.3f]\n", x, y);
00162                 //printf("ARM : x[%10.3f] y[%10.3f]\n", cmd.position[ARM_X], cmd.position[ARM_Y]);
00163 
00164                 // Some error checking so we don't exceed the bounds of the ARM
00165                 if (fabs(move.positions[X] > 20000))
00166                 {
00167                     ROS_ERROR("X-axis position (%f) out of bounds", move.positions[X]);
00168                     move.positions[X] = 0;
00169                 }
00170                 if (fabs(move.positions[Y] > 20000))
00171                 {
00172                     ROS_ERROR("Y-axis position (%f) out of bounds", move.positions[Y]);
00173                     move.positions[Y] = 0;
00174                 }
00175 
00176                 cmd.moves.push_back(move);
00177             }
00178 
00179             // Publish the move and wait for the duration of the burst
00180             cmd_pub_.publish(cmd);
00181             ROS_INFO("Command published, sleeping for %.3fs",
00182                      (cat.end - cat.header.stamp).toSec());
00183             (cat.end - cat.header.stamp).sleep();
00184 
00185             time_server::time_srv cat_end;
00186             cat_end.request.target = cat.end;
00187             time_client_.call(cat_end);
00188             printf("CAT end time : %f\n", cat.end.toSec());
00189             printf("Server time  : %f\n", cat_end.response.actual.toSec());
00190             printf("Delta        : %f\n", cat_end.response.delta.toSec());
00191         }
00192         else
00193             ROS_ERROR("CAT start time is behind server time, no command will be issued");
00194     }
00195     else
00196         ROS_ERROR("Time server is not responding, no command will be issued");
00197 }
00198 
00206 void TeleopArmDish::publishConstantMove()
00207 {
00208     burst_calc::cat cat = queue_.front();
00209     queue_.pop();
00210     time_server::time_srv cat_start;
00211     cat_start.request.target = cat.header.stamp;
00212 
00213     if (time_client_.call(cat_start))
00214     {
00215         /*printf("CAT start time : %f\n", cat.header.stamp.toSec());
00216         printf("Server time    : %f\n", cat_start.response.actual.toSec());
00217         printf("Delta          : %f\n", cat_start.response.delta.toSec());*/
00218 
00219         // The delta shouldn't be negative (server time is <= CAT time)
00220         if (cat_start.response.delta >= ros::Duration(0))
00221         {
00222             ROS_INFO("SLeeping for %.3fs before publishing command",
00223                      cat_start.response.delta.toSec());
00224             cat_start.response.delta.sleep();
00225 
00226             arm::constant_move_time cmd;
00227             cmd.header.stamp = cat.header.stamp;
00228             cmd.end = cat.end;
00229             int size = cat.cas.size();
00230             double x = 0.0;
00231             double y = 0.0;
00232 
00233             // Add all of the CA coordinates
00234             for (int i = 0; i < size; i++)
00235             {
00236                 x += cat.cas[i].x;
00237                 y += cat.cas[i].y;
00238             }
00239 
00240             // Get the average coordinates of the CAT
00241             x /= size;
00242             y /= size;
00243             printf("X: %.3f Y: %.3f\n", x, y);
00244 
00245             // Set the applicable movement states.
00246             // If coordinate < midpoint, movement is forward/left
00247             // If coordinate > midpoint is negative, movement is backward/right
00248             if (y - MIDPOINT < 0)
00249             {
00250                 ROS_INFO("Y is ABOVE the midpoint, moving FORWARD");
00251                 cmd.move.states[X] = ARM_FORWARD;
00252             }
00253             else
00254             {
00255                 ROS_INFO("Y is BELOW the midpoint, moving BACKWARD");
00256                 cmd.move.states[X] = ARM_BACKWARD;
00257             }
00258 
00259             if (x - MIDPOINT < 0)
00260             {
00261                 ROS_INFO("X is to the LEFT of the midpoint, moving LEFT");
00262                 cmd.move.states[Y] = ARM_LEFT;
00263             }
00264             else
00265             {
00266                 ROS_INFO("X is to the RIGHT of the midpoint, moving RIGHT");
00267                 cmd.move.states[Y] = ARM_RIGHT;
00268             }
00269 
00270 
00271             // Currently all axes have the same speed
00272             cmd.move.speeds.fill(static_cast<int8_t>(speed_));
00273 
00274             // Everything else is 0 (doesn't move)
00275             cmd.move.states[Z] = 0;
00276             cmd.move.states[YAW] = 0;
00277             cmd.move.states[PITCH] = 0;
00278             cmd.move.states[ROLL] = 0;
00279             cmd.move.states[GRIP] = 0;
00280             cmd.move.states[LIFT] = 0;
00281 
00282             printf("[%d] [%d] [%d] [%d] [%d] [%d] [%d] [%d]\n",
00283                    cmd.move.states[X], cmd.move.states[Y],
00284                    cmd.move.states[Z], cmd.move.states[YAW],
00285                    cmd.move.states[PITCH], cmd.move.states[ROLL],
00286                    cmd.move.states[GRIP], cmd.move.states[LIFT]);
00287             printf("[%d] [%d] [%d] [%d] [%d] [%d] [%d]\n",
00288                    cmd.move.speeds[X], cmd.move.speeds[Y],
00289                    cmd.move.speeds[Z], cmd.move.speeds[YAW],
00290                    cmd.move.speeds[PITCH], cmd.move.speeds[ROLL],
00291                    cmd.move.speeds[GRIP]);
00292 
00293             // Publish the move and wait for the duration of the burst
00294             cmd_pub_.publish(cmd);
00295             ROS_INFO("Sleeping for duration of command (%.3fs)",
00296                      (cat.end - cat.header.stamp).toSec());
00297             (cat.end - cat.header.stamp).sleep();
00298 
00299             /*time_server::time_srv cat_end;
00300             cat_end.request.target = cat.end;
00301             time_client_.call(cat_end);
00302             printf("CAT end time : %f\n", cat.end.toSec());
00303             printf("Server time  : %f\n", cat_end.response.actual.toSec());
00304             printf("Delta        : %f\n", cat_end.response.delta.toSec());*/
00305         }
00306         else
00307         {
00308             ROS_ERROR("CAT start time (%.3f) is behind server time (%.3f): no command will be issued",
00309                       cat_start.request.target.toSec(), cat_start.response.actual.toSec());
00310         }
00311     }
00312     else
00313         ROS_ERROR("Time server is not responding: no command will be issued");
00314 }
00315 
00325 double TeleopArmDish::getArmCoord(double coord)
00326 {
00327     // arm_safe_range_:
00328     //     The safe range, in ARM units (AU), for the ARM to move in an X/Y
00329     //     square is -20000:20000 AU on each axis (40001 AU total). The actual
00330     //     safe range for each individual axis is -28000:28000, but that will
00331     //     shrink depending on the value of the other axis.
00332     //
00333     // max_range_from_midpoint_:
00334     //     Each axis of the CAT grid ranges from 1:8, with 1 in the upper left
00335     //     corner. The midpoint of each axis is 4.5 ([1+8]/2) CAT units (CU).
00336     //     The max is range is the farthest that the CAT strays from the
00337     //     midpoint in either direction on either axis.
00338     //
00339     // The returned value will always be within the ARM safe range as long as
00340     // each CA is within the max range we specified.
00341     return (coord - MIDPOINT) * -(arm_safe_range_ / max_range_from_midpoint_);
00342 }
00343 
00347 int main(int argc, char** argv)
00348 {
00349     ros::init(argc, argv, "teleop_arm_dish");
00350     TeleopArmDish teleop_arm_dish;
00351     return 0;
00352 }


arm
Author(s): Jonathan Hasenzahl
autogenerated on Sun Jan 5 2014 11:12:32