PainterMain.cpp
Go to the documentation of this file.
00001 #include <vector>
00002 
00003 #include <ros/ros.h>
00004 #include <tf/tf.h>
00005 #include <tf/transform_listener.h>
00006 
00007 #include <ee_cart_imped_action/ee_cart_imped_arm.hh>
00008 
00009 #include <portrait_painter/SetCanvas.h>
00010 #include <portrait_painter/PainterUtils.h>
00011 #include <portrait_painter/JobSubmission.h>
00012 #include <portrait_painter/Point2D.h>
00013 
00014 #define MAXSPEED 0.2
00015 
00016 // distance to the canvas the robot has to have while not drawing
00017 #define CANVAS_OFFSET 0.1
00018 
00019 using namespace portrait_painter;
00020 
00021 double SPEED;
00022 // The listener to read the gripper position
00023 
00024 // Method declaration
00025 bool validateJob();
00026 void runJob();
00027 
00028 // The Canvas position
00029 tf::Point leftUpper;
00030 tf::Point rightUpper;
00031 tf::Point leftLower;
00032 
00033 // True if the canvas was set
00034 bool canvasSet = false;
00035 
00036 // Job Data:
00037 // True if there is a job currently in process
00038 bool jobActive = false;
00039 
00040 // List of Points to draw
00041 std::vector<portrait_painter::Point2D> jobPoints;
00042 portrait_painter::Point2D jobStart;
00043 
00044 // The unit vector that points from leftUpper to rightUpper
00045 tf::Point cornerRight;
00046 // The unit vector that points from leftUpper to leftLower
00047 tf::Point cornerDown;
00048 
00049 // The arm Controller publisher
00050 ros::Publisher armController;
00051 
00052 // Sets the Canvas to a certain set of coordinates
00053 bool handleCanvasSetting(portrait_painter::SetCanvas::Request &req,
00054                 portrait_painter::SetCanvas::Response &res) {
00055 
00056         tf::pointMsgToTF(req.leftUpper, leftUpper);
00057         tf::pointMsgToTF(req.rightUpper, rightUpper);
00058         tf::pointMsgToTF(req.leftLower, leftLower);
00059 
00060         cornerRight = (rightUpper - leftUpper);
00061         //cornerRight.normalize();
00062 
00063         cornerDown = leftLower - leftUpper;
00064         //cornerDown.normalize();
00065 
00066         canvasSet = true;
00067 
00068         std::ostringstream stream;
00069         ros::NodeHandle n;
00070         ros::ServiceClient msg_client = getMessageClient(n);
00071 
00072         stream << setprecision(2) << "New Canvas Position: \n(" << leftUpper.x()
00073                         << ", " << leftUpper.y() << ", " << leftUpper.z() << ") \n("
00074                         << rightUpper.x() << ", " << rightUpper.y() << ", "
00075                         << rightUpper.z() << ") \n(" << leftLower.x() << ", "
00076                         << leftLower.y() << ", " << leftLower.z() << ") \n";
00077         sendStatus(stream.str(), msg_client);
00078 
00079         ROS_INFO(
00080                         "New Corner Right: (%f, %f, %f)", cornerRight.x(), cornerRight.y(), cornerRight.z());
00081         ROS_INFO(
00082                         "New Corner Down: (%f, %f, %f)", cornerDown.x(), cornerDown.y(), cornerDown.z());
00083         return true;
00084 }
00085 
00086 // Recieves and Handles a new Job submission
00087 bool handleJobSumission(portrait_painter::JobSubmission::Request &req,
00088                 portrait_painter::JobSubmission::Response &res) {
00089         // If the canvas was not set properly, the Painter will refuse to accept Jobs
00090         if (!canvasSet || jobActive) {
00091                 res.success = false;
00092                 return true;
00093         }
00094 
00095         int pointNumber = req.points.size();
00096         portrait_painter::Point2D start = req.start;
00097 
00098         ROS_INFO(
00099                         "Recieved Job! %d Points\n Startpoint: (%f,%f)", pointNumber, start.x, start.y);
00100 
00101         // Save the submitted list to the global list
00102         jobPoints = req.points;
00103         jobStart = req.start;
00104 
00105         if (!validateJob()) {
00106                 res.success = false;
00107                 return true;
00108         }
00109         res.success = true;
00110         jobActive = true;
00111 
00112         // Start Job
00113         runJob();
00114 
00115         // Job done
00116         printf("Job Done!\n");
00117         jobActive = false;
00118 
00119         return true;
00120 }
00121 
00122 // This method handles the whole painting process of a job
00123 void runJob() {
00124 
00125         ROS_INFO("Job Started");
00126 
00127         // Fit Image to canvas
00128         // Action Client
00129         EECartImpedArm arm("r_arm_cart_imped_controller");
00130 
00131         // Trajectory
00132         ee_cart_imped_msgs::EECartImpedGoal traj;
00133 
00134         portrait_painter::Point2D canvasPosition;
00135         canvasPosition.x = jobStart.x;
00136         canvasPosition.y = jobStart.y;
00137 
00138         // Move Gripper to start position
00139         double timestamp = 0.0;
00140         double speed = SPEED;
00141 
00142         tf::Point nextGripperPosition = leftUpper
00143                         + (cornerRight * canvasPosition.x);
00144         nextGripperPosition = nextGripperPosition + (cornerDown * canvasPosition.y);
00145         nextGripperPosition[2] += CANVAS_OFFSET;
00146         ROS_INFO(
00147                         "Job start: (%f, %f, %f)", nextGripperPosition.x(), nextGripperPosition.y(), nextGripperPosition.z());
00148 
00149         tf::Quaternion o = tf::createQuaternionFromRPY(0, 0, 0);
00150 
00151         int stiffness = 50;
00152 
00153         tf::Point previousPosition = getGripperPosition();
00154         double length = (nextGripperPosition - previousPosition).length();
00155         timestamp += length / speed;
00156 
00157         EECartImpedArm::addTrajectoryPoint(traj, nextGripperPosition.x(),
00158                         nextGripperPosition.y(), nextGripperPosition.z(), o.x(), o.y(),
00159                         o.z(), o.w(), 1000, 1000, 1000, 30, 30, 30, false, false, false,
00160                         false, false, false, timestamp, "/torso_lift_link");
00161         timestamp += CANVAS_OFFSET * 3 / speed;
00162 
00163         nextGripperPosition[2] -= 3 * CANVAS_OFFSET;
00164 
00165         ROS_INFO(
00166                         "2nd Point: (%f, %f, %f)", nextGripperPosition.x(), nextGripperPosition.y(), nextGripperPosition.z());
00167 
00168         EECartImpedArm::addTrajectoryPoint(traj, nextGripperPosition.x(),
00169                         nextGripperPosition.y(), nextGripperPosition.z(), o.x(), o.y(),
00170                         o.z(), o.w(), 1000, 1000, stiffness, 30, 30, 30, false, false,
00171                         false, false, false, false, timestamp, "/torso_lift_link");
00172 
00173         for (unsigned int i = 0; i < jobPoints.size(); i++) {
00174                 // Remember last Point for distance calculation
00175                 tf::Point lastGripperPosition = nextGripperPosition;
00176 
00177                 // Calculate the next point on the canvas (relative to absolute)
00178                 canvasPosition.x += jobPoints[i].x;
00179                 canvasPosition.y += jobPoints[i].y;
00180 
00181                 nextGripperPosition = leftUpper + (cornerRight * canvasPosition.x);
00182                 nextGripperPosition = nextGripperPosition
00183                                 + (cornerDown * canvasPosition.y);
00184                 nextGripperPosition[2] -= 2 * CANVAS_OFFSET;
00185 
00186                 ROS_INFO(
00187                                 "Next point: (%f, %f, %f)", nextGripperPosition.x(), nextGripperPosition.y(), nextGripperPosition.z());
00188 
00189                 double length = (nextGripperPosition - lastGripperPosition).length();
00190                 timestamp += length / speed;
00191 
00192                 // Add next point to the trajectory
00193                 EECartImpedArm::addTrajectoryPoint(traj, nextGripperPosition.x(),
00194                                 nextGripperPosition.y(), nextGripperPosition.z(), o.x(), o.y(),
00195                                 o.z(), o.w(), 1000, 1000, stiffness, 30, 30, 30, false, false,
00196                                 false, false, false, false, timestamp, "/torso_lift_link");
00197 
00198                 printf("timestamp: %f", timestamp);
00199 
00200         }
00201 
00202         arm.startTrajectory(traj);
00203 }
00204 
00205 // This method checks if a submitted job would cause the pen to leave the canvas
00206 // return: true if job is valid; false otherwise
00207 bool validateJob() {
00208         portrait_painter::Point2D currentPosition = jobStart;
00209 
00210         int pointNum = jobPoints.size();
00211 
00212         for (int i = 0; i < pointNum; i++) {
00213                 currentPosition.x += jobPoints[i].x;
00214                 currentPosition.y += jobPoints[i].y;
00215 
00216                 if (currentPosition.x > 1.01 || currentPosition.x < -0.01
00217                                 || currentPosition.y > 1.01 || currentPosition.y < -0.01) {
00218                         ROS_INFO(
00219                                         "Invalid Job! Leaves canvas in step %d (%f, %f)", i, currentPosition.x, currentPosition.y);
00220                         return false;
00221                 }
00222         }
00223         return true;
00224 }
00225 
00226 int main(int argc, char **argv) {
00227         // Initialize Canvas
00228 
00229         leftUpper.setZero();
00230         rightUpper.setZero();
00231         leftLower.setZero();
00232         cornerRight.setZero();
00233         cornerDown.setZero();
00234 
00235         ros::init(argc, argv, "Painter");
00236         ros::NodeHandle n;
00237 
00238         if (argc != 2) {
00239                 printf("Please specify desired speed in meters/second\n");
00240                 return (1);
00241         }
00242         SPEED = atof(argv[1]);
00243         if (SPEED > MAXSPEED) {
00244                 printf("Warning: Speed to high! Was set to %1.1f for safety reasons!\n",
00245                                 MAXSPEED);
00246                 SPEED = MAXSPEED;
00247         }
00248 
00249         // Initialize Canvas setting service
00250         ros::ServiceServer canvasSetting = n.advertiseService("canvas_setting",
00251                         handleCanvasSetting);
00252         // Initialize Job Submission service
00253         ros::ServiceServer jobSubmission = n.advertiseService("job_submission",
00254                         handleJobSumission);
00255 
00256         ROS_INFO("Painter Services up and running");
00257 
00258         ros::spin();
00259 
00260         return 0;
00261 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


portrait_painter
Author(s): Niklas Meinzer, Ina Baumgarten
autogenerated on Wed Dec 26 2012 16:00:43