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
00017 #define CANVAS_OFFSET 0.1
00018
00019 using namespace portrait_painter;
00020
00021 double SPEED;
00022
00023
00024
00025 bool validateJob();
00026 void runJob();
00027
00028
00029 tf::Point leftUpper;
00030 tf::Point rightUpper;
00031 tf::Point leftLower;
00032
00033
00034 bool canvasSet = false;
00035
00036
00037
00038 bool jobActive = false;
00039
00040
00041 std::vector<portrait_painter::Point2D> jobPoints;
00042 portrait_painter::Point2D jobStart;
00043
00044
00045 tf::Point cornerRight;
00046
00047 tf::Point cornerDown;
00048
00049
00050 ros::Publisher armController;
00051
00052
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
00062
00063 cornerDown = leftLower - leftUpper;
00064
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
00087 bool handleJobSumission(portrait_painter::JobSubmission::Request &req,
00088 portrait_painter::JobSubmission::Response &res) {
00089
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
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
00113 runJob();
00114
00115
00116 printf("Job Done!\n");
00117 jobActive = false;
00118
00119 return true;
00120 }
00121
00122
00123 void runJob() {
00124
00125 ROS_INFO("Job Started");
00126
00127
00128
00129 EECartImpedArm arm("r_arm_cart_imped_controller");
00130
00131
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
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
00175 tf::Point lastGripperPosition = nextGripperPosition;
00176
00177
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
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
00206
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
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
00250 ros::ServiceServer canvasSetting = n.advertiseService("canvas_setting",
00251 handleCanvasSetting);
00252
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 }