00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "ArmWidget.h"
00042
00043 #include <math.h>
00044 #include <QtGui>
00045 #include "corobot.h"
00046
00047 double inchesToMeters(const double inches)
00048
00049 {
00050 return inches * 2.54 / 100.0;
00051 }
00052
00053 double PixeltoMeter(const double pixel)
00054
00055 {
00056 return (pixel / PIXELS_PER_METER);
00057 }
00058
00059 double MetersToPixels(const double meters)
00060
00061 {
00062 return (meters * PIXELS_PER_METER);
00063 }
00064
00065
00066
00067 const double COROBOT_ARM_SHOULDER_SEGMENT_METERS = inchesToMeters(6.25);
00068 const double COROBOT_ARM_ELBOW_SEGMENT_METERS = inchesToMeters(8);
00069
00070
00071 const double PINCHER_ARM_SHOULDER_SEGMENT_METERS = inchesToMeters(6.25);
00072 const double PINCHER_ARM_ELBOW_SEGMENT_METERS = inchesToMeters(8);
00073
00074
00075 const double REACTOR_ARM_SHOULDER_SEGMENT_METERS = inchesToMeters(6.25);
00076 const double REACTOR_ARM_ELBOW_SEGMENT_METERS = inchesToMeters(8);
00077
00078
00079 const double AL5A_ARM_SHOULDER_SEGMENT_METERS = inchesToMeters(3.75);
00080 const double AL5A_ARM_ELBOW_SEGMENT_METERS = inchesToMeters(7.62);
00081
00082
00083 double armShoulderSegmentMeters=COROBOT_ARM_SHOULDER_SEGMENT_METERS;
00084 double armElbowSegmentMeters=COROBOT_ARM_ELBOW_SEGMENT_METERS;
00085
00086
00087 const int ARM_X = 120;
00088 const int ARM_Y = 120;
00089 const int ARM_CENTER_X = ARM_X / 2;
00090 const int ARM_BODY_TOP = ARM_X * 7 / 10;
00091 const int ARM_SHOULDER_X = ARM_CENTER_X - ARM_X / 7;
00092
00093 ArmWidget::ArmWidget(QWidget *parent)
00094 : QGraphicsView(parent), timerId(0)
00095 {
00096
00097 QGraphicsScene *scene = new QGraphicsScene(this);
00098 scene->setItemIndexMethod(QGraphicsScene::NoIndex);
00099 scene->setSceneRect(0, 00, 210, 110);
00100
00101 shoulder = true;
00102 elbow = true;
00103 setScene(scene);
00104 setCacheMode(CacheBackground);
00105 setViewportUpdateMode(BoundingRectViewportUpdate);
00106 setRenderHint(QPainter::Antialiasing);
00107 setTransformationAnchor(AnchorUnderMouse);
00108 scale(qreal(1), qreal(1));
00109 setMinimumSize(210, 110);
00110 setWindowTitle(tr("Elastic Nodes"));
00111
00112 joint *joint1 = new joint(this);
00113 joint *joint2 = new joint(this);
00114 joint *joint3 = new joint(this);
00115
00116
00117 scene->addItem(joint1);
00118 scene->addItem(joint2);
00119 scene->addItem(joint3);
00120
00121 joint3->setFlag(joint3->ItemIsMovable);
00122
00123 double x = armShoulderSegmentMeters;
00124 double y = armElbowSegmentMeters;
00125
00126 joint1->setPos(this->sceneRect().left()+ARM_SHOULDER_X+5, this->sceneRect().bottom()-ARM_Y+ARM_BODY_TOP+5);
00127 joint2->setPos(this->sceneRect().left()+ARM_SHOULDER_X+5, -MetersToPixels(y)-ARM_Y+ARM_BODY_TOP+5+this->sceneRect().bottom());
00128
00129
00130 joint3->setPos(MetersToPixels(x)+this->sceneRect().left()+ARM_SHOULDER_X+5,
00131 -MetersToPixels(y)-ARM_Y+ARM_BODY_TOP+5+this->sceneRect().bottom());
00132 end_effector = QPointF(0,0);
00133
00134 QGraphicsLineItem *line = new QGraphicsLineItem(joint1->pos().x()-5,joint1->pos().y()-5,joint2->pos().x()-5,joint2->pos().y()-5);
00135 scene->addItem(line);
00136 QGraphicsLineItem *line2 = new QGraphicsLineItem(joint2->pos().x()-5,joint2->pos().y()-5,joint3->pos().x()-5,joint3->pos().y()-5);
00137 scene->addItem(line2);
00138
00139 }
00147 bool doArmIK(const double x, const double y, double& theta1, double& theta2)
00148
00149 {
00150 const double LOWER_LINK_LEN = armShoulderSegmentMeters;
00151 const double UPPER_LINK_LEN = armElbowSegmentMeters;
00152 const double LOWER_SQUARED = armShoulderSegmentMeters * armShoulderSegmentMeters;
00153 const double UPPER_SQUARED = armElbowSegmentMeters * armElbowSegmentMeters;
00154
00155 double c2;
00156
00157 c2 = ((x * x) + (y * y) - LOWER_SQUARED - UPPER_SQUARED) /
00158 (2 * LOWER_LINK_LEN * UPPER_LINK_LEN);
00159 if ((c2 < -1.0) || (c2 > 1.0))
00160 {
00161 return false;
00162 }
00163
00164 double magS2;
00165
00166 magS2 = sqrt(1 - c2 * c2);
00167 double posS2 = magS2;
00168 double negS2 = -magS2;
00169 double posTheta2,
00170 negTheta2;
00171
00172 posTheta2 = atan2(posS2, c2);
00173 negTheta2 = atan2(negS2, c2);
00174
00175 double posS1;
00176
00177 posS1 =
00178 ((LOWER_LINK_LEN + UPPER_LINK_LEN * c2) * y -
00179 (UPPER_LINK_LEN * posS2 * x)) / (x * x + y * y);
00180 double posC1;
00181
00182 posC1 =
00183 ((LOWER_LINK_LEN + UPPER_LINK_LEN * c2) * x +
00184 (UPPER_LINK_LEN * posS2 * y)) / (x * x + y * y);
00185 double posTheta1;
00186
00187 posTheta1 = atan2(posS1, posC1);
00188
00189 double negS1;
00190
00191 negS1 =
00192 ((LOWER_LINK_LEN + UPPER_LINK_LEN * c2) * y -
00193 (UPPER_LINK_LEN * negS2 * x)) / (x * x + y * y);
00194 double negC1;
00195
00196 negC1 =
00197 ((LOWER_LINK_LEN + UPPER_LINK_LEN * c2) * x +
00198 (UPPER_LINK_LEN * negS2 * y)) / (x * x + y * y);
00199 double negTheta1;
00200
00201 negTheta1 = atan2(negS1, negC1);
00202
00203
00204 if ((posTheta1 <= M_PI * 0.75) && (posTheta1 >= 0.0) && (posTheta2 <= 0.0))
00205 {
00206 theta1 = posTheta1;
00207 theta2 = posTheta2;
00208 return true;
00209 }
00210
00211
00212 if ((negTheta1 <= M_PI * 0.75) && (negTheta1 >= 0.0) && (negTheta2 <= 0.0))
00213 {
00214 theta1 = negTheta1;
00215 theta2 = negTheta2;
00216 return true;
00217 }
00218 return false;
00219 }
00220
00221 void ArmWidget::Corobot(bool value)
00222
00223 {
00224 foreach (QGraphicsItem *item, scene()->items()) {
00225 if(value == true){
00226 item->show();
00227 }
00228 else{
00229 item->hide();
00230 }
00231 }
00232 }
00233
00234 void ArmWidget::setModel(bool arm_al5a,bool arm_pincher,bool arm_reactor,bool arm_old_corobot)
00235
00236 {
00237 if (arm_old_corobot)
00238 {
00239 armShoulderSegmentMeters= COROBOT_ARM_SHOULDER_SEGMENT_METERS;
00240 armElbowSegmentMeters= COROBOT_ARM_ELBOW_SEGMENT_METERS;
00241 arm_type = OldCorobot;
00242 }
00243 else if (arm_pincher)
00244 {
00245 armShoulderSegmentMeters= PINCHER_ARM_SHOULDER_SEGMENT_METERS;
00246 armElbowSegmentMeters= PINCHER_ARM_ELBOW_SEGMENT_METERS;
00247 arm_type = Pincher;
00248 }
00249 else if (arm_reactor)
00250 {
00251 armShoulderSegmentMeters= REACTOR_ARM_SHOULDER_SEGMENT_METERS;
00252 armElbowSegmentMeters= REACTOR_ARM_ELBOW_SEGMENT_METERS;
00253 arm_type = Reactor;
00254 }
00255 else if (arm_al5a)
00256 {
00257 armShoulderSegmentMeters= AL5A_ARM_SHOULDER_SEGMENT_METERS;
00258 armElbowSegmentMeters= AL5A_ARM_ELBOW_SEGMENT_METERS;
00259 arm_type = Al5a;
00260 }
00261
00262 printf("ARM_LENGTH %d, %d", armShoulderSegmentMeters, armShoulderSegmentMeters);
00263
00264 QGraphicsScene *scene = this->scene();
00265
00266 joint* joint1 = (joint*)scene->items().at(0);
00267 joint* joint2 = (joint*)scene->items().at(1);
00268 joint* joint3 = (joint*)scene->items().at(2);
00269
00270 double x = armShoulderSegmentMeters;
00271 double y = armElbowSegmentMeters;
00272
00273 joint3->setPos(MetersToPixels(x)+this->sceneRect().left()+ARM_SHOULDER_X+5,-MetersToPixels(y)-ARM_Y+ARM_BODY_TOP+5+this->sceneRect().bottom());
00274 joint2->setPos(this->sceneRect().left()+ARM_SHOULDER_X+5, -MetersToPixels(y)-ARM_Y+ARM_BODY_TOP+5+this->sceneRect().bottom());
00275
00276 ((QGraphicsLineItem*)(scene->items().at(3)))->setLine(joint1->pos().x()-5,joint1->pos().y()-5,joint2->pos().x()-5,joint2->pos().y()-5);
00277 ((QGraphicsLineItem*)(scene->items().at(4)))->setLine(joint2->pos().x()-5,joint2->pos().y()-5,joint3->pos().x()-5,joint3->pos().y()-5);
00278
00279
00280 }
00281
00282
00283 void ArmWidget::itemMoved()
00284
00285 {
00286 if (!timerId)
00287 timerId = startTimer(1000 / 25);
00288 }
00289
00290 void ArmWidget::shoulder_degree(bool value)
00291
00292 {
00293 shoulder = value;
00294
00295 }
00296
00297 void ArmWidget::elbow_degree(bool value)
00298
00299 {
00300 elbow = value;
00301
00302 }
00303
00304 void ArmWidget::moveArmUp()
00305
00306 {
00307 this->scene()->items().at(2)->setPos(end_effector + QPointF(0,-5));
00308 }
00309
00310 void ArmWidget::moveArmDown()
00311
00312 {
00313 this->scene()->items().at(2)->setPos(end_effector + QPointF(0,5));
00314 }
00315
00316 void ArmWidget::moveArmLeft()
00317
00318 {
00319 this->scene()->items().at(2)->setPos(end_effector + QPointF(-5,0));
00320 }
00321
00322 void ArmWidget::moveArmRight()
00323
00324 {
00325 this->scene()->items().at(2)->setPos(end_effector + QPointF(5,0));
00326 }
00327
00328 void ArmWidget::received_pos(double x, double y)
00329
00330 {
00331
00332 QList<joint *> joints;
00333 foreach (QGraphicsItem *item, scene()->items()) {
00334 if (joint *j = qgraphicsitem_cast<joint *>(item))
00335 joints << j;
00336 }
00337
00338 joints.at(2)->setPos(MetersToPixels(x)+this->sceneRect().left()+ARM_SHOULDER_X+5,
00339 -MetersToPixels(y)-ARM_Y+ARM_BODY_TOP+5+this->sceneRect().bottom());
00340
00341
00342 }
00343
00344
00345 void ArmWidget::timerEvent(QTimerEvent *event)
00346
00347 {
00348 Q_UNUSED(event);
00349
00350 QList<joint *> joints;
00351 foreach (QGraphicsItem *item, scene()->items()) {
00352 if (joint *j = qgraphicsitem_cast<joint *>(item))
00353 joints << j;
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 const double LINK_1_LENGTH = MetersToPixels(armShoulderSegmentMeters);
00372 const double LINK_2_LENGTH = MetersToPixels(armElbowSegmentMeters);
00373
00374 float x,y;
00375
00376 x = PixeltoMeter(joints.at(2)->pos().x()-5-(this->sceneRect().left()+ARM_SHOULDER_X));
00377 y = PixeltoMeter(this->sceneRect().bottom()-ARM_Y+ARM_BODY_TOP-joints.at(2)->pos().y()+5);
00378
00379 if(joints.at(2)->x()!=end_effector.x() || joints.at(2)->y()!=end_effector.y()){
00380 double t1,t2;
00381 if(doArmIK(x,y, t1, t2)){
00382
00383
00384
00385 double x = LINK_1_LENGTH * cos(t1);
00386 double y = LINK_1_LENGTH * sin(t1);
00387
00388 int elbowX = ARM_SHOULDER_X + (int)x;
00389 int elbowY = -ARM_Y+ARM_BODY_TOP - (int)y;
00390
00391 joints.at(1)->setPos(this->sceneRect().left()+elbowX+5, this->sceneRect().bottom()+elbowY+5);
00392
00393
00394 if(shoulder)
00395 emit theta1(t1/M_PI*180);
00396 else
00397 emit theta1(t1);
00398 if(elbow)
00399 emit theta2(t2/M_PI*180+180);
00400 else
00401 emit theta2(t2 + M_PI);
00402
00403 if (arm_type == Al5a)
00404 {
00405 emit shoulderAngle_rad(180 - t1);
00406 emit elbowAngle_rad(180 + t2);
00407 }
00408 else
00409 {
00410 emit shoulderAngle_rad(t1);
00411 emit elbowAngle_rad(-t2);
00412 }
00413 QList<QGraphicsLineItem *> lines;
00414 foreach (QGraphicsItem *item, scene()->items()) {
00415 if (QGraphicsLineItem *l = qgraphicsitem_cast<QGraphicsLineItem *>(item))
00416 lines << l;
00417 }
00418
00419 lines.at(0)->setLine(joints.at(0)->pos().x()-5,joints.at(0)->pos().y()-5,joints.at(1)->pos().x()-5,joints.at(1)->pos().y()-5);
00420 lines.at(1)->setLine(joints.at(1)->pos().x()-5,joints.at(1)->pos().y()-5,joints.at(2)->pos().x()-5,joints.at(2)->pos().y()-5);
00421
00422 end_effector = joints.at(2)->pos();
00423 }
00424 else{
00425 joints.at(2)->setPos(end_effector);
00426 }
00427 }
00428
00429
00430
00431 }
00432
00433
00434
00435
00436 void ArmWidget::drawBackground(QPainter *painter, const QRectF &rect)
00437
00438 {
00439 Q_UNUSED(rect);
00440
00441
00442 QRectF sceneRect = this->sceneRect();
00443 QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
00444 QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
00445 if (rightShadow.intersects(rect) || rightShadow.contains(rect))
00446 painter->fillRect(rightShadow, Qt::darkGray);
00447 if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
00448 painter->fillRect(bottomShadow, Qt::darkGray);
00449
00450
00451
00452 QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
00453 gradient.setColorAt(0, Qt::white);
00454 gradient.setColorAt(1, Qt::lightGray);
00455 painter->fillRect(rect.intersect(sceneRect), gradient);
00456 painter->setBrush(Qt::NoBrush);
00457 painter->drawRect(sceneRect);
00458
00459
00460 QRectF robot(sceneRect.left(), sceneRect.bottom()-ARM_Y+ARM_BODY_TOP, ARM_X / 2, ARM_Y - ARM_BODY_TOP);
00461 painter->fillRect(robot, Qt::gray);
00462 painter->setBrush(Qt::NoBrush);
00463 painter->drawRect(robot);
00464
00465
00466
00467 QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4,
00468 sceneRect.width() - 4, sceneRect.height() - 4);
00469
00470 QFont font = painter->font();
00471 font.setBold(true);
00472 font.setPointSize(14);
00473 painter->setFont(font);
00474 painter->setPen(Qt::lightGray);
00475 painter->setPen(Qt::black);
00476 }
00477
00478 void ArmWidget::scaleView(qreal scaleFactor)
00479
00480 {
00481 qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
00482 if (factor < 0.07 || factor > 100)
00483 return;
00484
00485 scale(scaleFactor, scaleFactor);
00486 }
00487
00488
00489
00490