2 * RobomonExplorer.cpp 07/10/31
4 * Robot`s visualization and control GUI for robot of the
5 * Eurobot 2008 (Mission to Mars).
7 * Copyright: (c) 2008 CTU Dragons
8 * CTU FEE - Department of Control Engineering
9 * Authors: Martin Zidek, Michal Sojka, Tran Duy Khanh
10 * License: GNU GPL v.2
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
26 #include <path_planner.h>
27 #include <robodim_eb2008.h>
32 #include "PlaygroundScene.h"
34 #include "robomon_orte.h"
35 #include "RobomonExplorer.h"
37 #include <QCoreApplication>
41 #include <QMessageBox>
42 #include <servos_eb2008.h>
44 RobomonExplorer::RobomonExplorer(QWidget *parent)
51 debugWindowEnabled = false;
56 QHBoxLayout *mainLayout = new QHBoxLayout;
57 mainLayout->addLayout(leftLayout);
58 mainLayout->addLayout(rightLayout);
59 setLayout(mainLayout);
65 setFocusPolicy(Qt::StrongFocus);
66 sharedMemoryOpened = false;
67 WDBG("Youuuhouuuu!!");
70 /**********************************************************************
72 **********************************************************************/
73 void RobomonExplorer::createLeftLayout()
75 leftLayout = new QVBoxLayout();
77 createDebugGroupBox();
78 debugWindowEnabled = true;
79 createPlaygroundGroupBox();
81 leftLayout->addWidget(playgroundGroupBox);
82 leftLayout->addWidget(debugGroupBox);
85 void RobomonExplorer::createRightLayout()
87 rightLayout = new QVBoxLayout();
88 QGridLayout *layout = new QGridLayout();
89 QVBoxLayout *vlayout = new QVBoxLayout();
91 createPositionGroupBox();
93 createActuatorsGroupBox();
95 createPowerGroupBox();
96 createSensorsGroupBox();
98 vlayout->addWidget(positionGroupBox);
99 vlayout->addWidget(miscGroupBox);
100 layout->addLayout(vlayout, 0, 0);
101 layout->addWidget(actuatorsGroupBox, 0, 1);
102 // layout->addWidget(dioGroupBox, 0, 2);
104 rightLayout->addLayout(layout);
105 rightLayout->addWidget(powerGroupBox);
106 rightLayout->addWidget(sensorsGroupBox);
109 void RobomonExplorer::createPlaygroundGroupBox()
111 playgroundGroupBox = new QGroupBox(tr("Playground"));
112 QHBoxLayout *layout = new QHBoxLayout();
115 new PlaygroundScene(PlaygroundScene::PLAYGROUND_EUROBOT2008);
116 playgroundSceneView = new QGraphicsView(playgroundScene);
117 playgroundSceneView->setMinimumWidth((int)(playgroundScene->width())+15);
118 playgroundSceneView->setMinimumHeight((int)(playgroundScene->height())+15);
119 layout->addWidget(playgroundSceneView);
121 playgroundGroupBox->setLayout(layout);
124 void RobomonExplorer::createPositionGroupBox()
126 positionGroupBox = new QGroupBox(tr("Position state"));
127 QGridLayout *layout = new QGridLayout();
129 actPosX = new QLineEdit();
130 actPosY = new QLineEdit();
131 actPosPhi = new QLineEdit();
133 estPosX = new QLineEdit();
134 estPosY = new QLineEdit();
135 estPosPhi = new QLineEdit();
137 actPosX->setReadOnly(true);
138 actPosY->setReadOnly(true);
139 actPosPhi->setReadOnly(true);
141 estPosX->setReadOnly(true);
142 estPosY->setReadOnly(true);
143 estPosPhi->setReadOnly(true);
145 layout->addWidget(MiscGui::createLabel("X"), 1, 0);
146 layout->addWidget(MiscGui::createLabel("Y"), 2, 0);
147 layout->addWidget(MiscGui::createLabel("Phi"), 3, 0);
149 layout->addWidget(MiscGui::createLabel("X"), 5, 0);
150 layout->addWidget(MiscGui::createLabel("Y"), 6, 0);
151 layout->addWidget(MiscGui::createLabel("Phi"), 7, 0);
153 layout->addWidget(MiscGui::createLabel("Actual", Qt::AlignLeft), 0, 1);
154 layout->addWidget(actPosX, 1, 1);
155 layout->addWidget(actPosY, 2, 1);
156 layout->addWidget(actPosPhi, 3, 1);
158 layout->addWidget(MiscGui::createLabel("Estimated", Qt::AlignLeft), 4, 1);
159 layout->addWidget(estPosX, 5, 1);
160 layout->addWidget(estPosY, 6, 1);
161 layout->addWidget(estPosPhi, 7, 1);
163 positionGroupBox->setLayout(layout);
166 void RobomonExplorer::createMiscGroupBox()
168 miscGroupBox = new QGroupBox(tr("Miscellaneous"));
169 QGridLayout *layout = new QGridLayout();
171 showMapPushButton = new QPushButton(tr("Show &map"));
172 showMapPushButton->setShortcut(tr("m"));
174 laserEngineCheckBox = new QCheckBox(tr("L&aser"));
175 laserEngineCheckBox->setShortcut(tr("a"));
177 layout->addWidget(showMapPushButton, 0, 0);
178 layout->addWidget(laserEngineCheckBox, 1, 0);
180 miscGroupBox->setLayout(layout);
183 void RobomonExplorer::createDebugGroupBox()
185 debugGroupBox = new QGroupBox(tr("Debug window"));
186 QHBoxLayout *layout = new QHBoxLayout();
188 debugWindow = new QTextEdit();
189 debugWindow->setReadOnly(true);
191 layout->addWidget(debugWindow);
192 debugGroupBox->setLayout(layout);
195 void RobomonExplorer::createActuatorsGroupBox()
197 actuatorsGroupBox = new QGroupBox(tr("Actuators"));
198 QHBoxLayout *layout = new QHBoxLayout();
200 createMotorsGroupBox();
201 createServosGroupBox();
202 createDrivesGroupBox();
204 layout->setAlignment(Qt::AlignLeft);
205 layout->addWidget(enginesGroupBox);
206 layout->addWidget(servosGroupBox);
207 layout->addWidget(drivesGroupBox);
208 actuatorsGroupBox->setLayout(layout);
211 void RobomonExplorer::createDIOGroupBox()
213 dioGroupBox = new QGroupBox(tr("DIO"));
214 QGridLayout *layout = new QGridLayout();
217 font.setPointSize(5);
218 dioGroupBox->setFont(font);
220 for (int i=0; i<8; i++) {
221 diCheckBox[i] = new QCheckBox(QString("DI%1").arg(i));
222 doCheckBox[i] = new QCheckBox(QString("D0%1").arg(i));
223 layout->addWidget(diCheckBox[i], i, 0);
224 layout->addWidget(doCheckBox[i], i+8, 0);
227 dioGroupBox->setMaximumWidth(70);
228 dioGroupBox->setLayout(layout);
231 void RobomonExplorer::createPowerGroupBox()
233 powerGroupBox = new QGroupBox(tr("Power management"));
234 QGridLayout *layout = new QGridLayout();
236 voltage33CheckBox = new QCheckBox(tr("&3.3V"));
237 voltage50CheckBox = new QCheckBox(tr("&5.0V"));
238 voltage80CheckBox = new QCheckBox(tr("&8.0V"));
240 voltage33CheckBox->setShortcut(tr("3"));
241 voltage50CheckBox->setShortcut(tr("5"));
242 voltage80CheckBox->setShortcut(tr("8"));
244 layout->addWidget(voltage33CheckBox, 0, 0);
245 layout->addWidget(voltage50CheckBox, 0, 2);
246 layout->addWidget(voltage80CheckBox, 0, 4); //1, 0);
247 layout->addWidget(MiscGui::createLabel("BAT"), 0, 6); //1, 2);
249 voltage33LineEdit = new QLineEdit();
250 voltage50LineEdit = new QLineEdit();
251 voltage80LineEdit = new QLineEdit();
252 voltageBATLineEdit = new QLineEdit();
254 voltage33LineEdit->setReadOnly(true);
255 voltage50LineEdit->setReadOnly(true);
256 voltage80LineEdit->setReadOnly(true);
257 voltageBATLineEdit->setReadOnly(true);
259 layout->addWidget(voltage33LineEdit, 0, 1);
260 layout->addWidget(voltage50LineEdit, 0, 3);
261 layout->addWidget(voltage80LineEdit, 0, 5); //1, 1);
262 layout->addWidget(voltageBATLineEdit, 0, 7); //1, 3);
264 powerGroupBox->setLayout(layout);
267 void RobomonExplorer::createSensorsGroupBox()
269 sensorsGroupBox = new QGroupBox(tr("Sensors"));
270 QVBoxLayout *layout = new QVBoxLayout();
272 createSharpSensorsLayout();
274 layout->addLayout(sharpSensorsLayout);
275 sensorsGroupBox->setLayout(layout);
278 void RobomonExplorer::createMotorsGroupBox()
280 enginesGroupBox = new QGroupBox(tr("Motors"));
281 QVBoxLayout *layout = new QVBoxLayout();
282 QHBoxLayout *layout1 = new QHBoxLayout();
283 QHBoxLayout *layout2 = new QHBoxLayout();
285 leftMotorSlider = new QSlider(Qt::Vertical);
286 rightMotorSlider = new QSlider(Qt::Vertical);
287 bothMotorsCheckBox = new QCheckBox(tr("Lock both"));
288 stopMotorsPushButton = new QPushButton(tr("Stop Motors"));
290 leftMotorSlider->setMinimum(-100);
291 leftMotorSlider->setMaximum(100);
292 leftMotorSlider->setTracking(false);
293 leftMotorSlider->setTickPosition(QSlider::TicksLeft);
295 rightMotorSlider->setMinimum(-100);
296 rightMotorSlider->setMaximum(100);
297 rightMotorSlider->setTracking(false);
298 rightMotorSlider->setTickPosition(QSlider::TicksRight);
300 stopMotorsPushButton->setMaximumWidth(90);
302 layout1->addWidget(leftMotorSlider);
303 layout1->addWidget(MiscGui::createLabel("0"));
304 layout1->addWidget(rightMotorSlider);
306 layout2->addWidget(bothMotorsCheckBox);
308 layout->addWidget(MiscGui::createLabel("100"));
309 layout->addLayout(layout1);
310 layout->addWidget(MiscGui::createLabel("-100"));
311 layout->addLayout(layout2);
312 layout->addWidget(stopMotorsPushButton);
313 enginesGroupBox->setLayout(layout);
316 void RobomonExplorer::createServosGroupBox()
318 servosGroupBox = new QGroupBox(tr("Servos"));
319 QGridLayout *layout = new QGridLayout();
321 bottomDoorCheckBox = new QCheckBox(tr("Bottom &Door"));
322 backDoorCheckBox = new QCheckBox(tr("&Back Door"));
323 topDoorCheckBox = new QCheckBox(tr("&Top Door"));
324 leftBrushCheckBox = new QCheckBox(tr("&Left Brush"));
325 rightBrushCheckBox = new QCheckBox(tr("&Right Brush"));
327 bottomDoorCheckBox->setShortcut(tr("d"));
328 backDoorCheckBox->setShortcut(tr("b"));
329 topDoorCheckBox->setShortcut(tr("t"));
330 leftBrushCheckBox->setShortcut(tr("l"));
331 rightBrushCheckBox->setShortcut(tr("r"));
333 layout->addWidget(bottomDoorCheckBox, 0, 0);
334 layout->addWidget(backDoorCheckBox, 1, 0);
335 layout->addWidget(topDoorCheckBox, 2, 0);
336 layout->addWidget(leftBrushCheckBox, 3, 0);
337 layout->addWidget(rightBrushCheckBox, 4, 0);
338 servosGroupBox->setLayout(layout);
342 void RobomonExplorer::createDrivesGroupBox()
344 drivesGroupBox = new QGroupBox(tr("Drives"));
345 QGridLayout *layout = new QGridLayout();
347 leftBrushDial = new QDial();
348 rightBrushDial = new QDial();
349 bagrDial = new QDial();
350 carouselDial = new QDial();
352 leftBrushDriveCheckBox = new QCheckBox(tr("L&eft brush"));
353 rightBrushDriveCheckBox = new QCheckBox(tr("Ri&ght brush"));
354 bagrDriveCheckBox = new QCheckBox(tr("B&agr"));
356 leftBrushDial->setRange(0,200);
357 leftBrushDial->setValue(100);
358 rightBrushDial->setRange(0,200);
359 rightBrushDial->setValue(100);
360 bagrDial->setRange(0,200);
361 bagrDial->setValue(100);
362 carouselDial->setRange(0,4);
363 carouselDial->setNotchesVisible(1);
365 layout->addWidget(leftBrushDial, 0, 0);
366 layout->addWidget(leftBrushDriveCheckBox, 0, 1);
367 layout->addWidget(rightBrushDial, 1, 0);
368 layout->addWidget(rightBrushDriveCheckBox, 1, 1);
369 layout->addWidget(bagrDial, 2, 0);
370 layout->addWidget(bagrDriveCheckBox, 2, 1);
371 layout->addWidget(carouselDial, 3, 0);
372 drivesGroupBox->setLayout(layout);
375 void RobomonExplorer::createSharpSensorsLayout()
377 sharpSensorsLayout = new QVBoxLayout();
378 QGridLayout *layout1 = new QGridLayout();
379 QGridLayout *layout2 = new QGridLayout();
380 QGridLayout *layout3 = new QGridLayout();
382 sensorsSimulationCheckBox = new QCheckBox(tr("&Sensor simulation"));
383 obstacleSimulationCheckBox = new QCheckBox(tr("&Obstacle simulation"));
385 sensorsSimulationCheckBox->setShortcut(tr("s"));
386 obstacleSimulationCheckBox->setShortcut(tr("o"));
388 layout3->addWidget(sensorsSimulationCheckBox, 0, 0);
389 layout3->addWidget(obstacleSimulationCheckBox, 0, 1);
391 for (int i=0; i<SHARP_LONG_CNT; i++) {
392 sharpLongsSlider[i] = new QSlider(Qt::Horizontal);
393 sharpLongsProgressBar[i] = new QProgressBar();
394 sharpLongsProgressBar[i]->setMinimum(0);
395 sharpLongsProgressBar[i]->setMaximum(800);
396 sharpLongsProgressBar[i]->setValue(0);
398 MiscGui::createLabel(QString("LONG%1").arg(i+1));
399 layout1->addWidget(sharpLongsLabel[i], 0, i);
400 layout1->addWidget(sharpLongsSlider[i], 1, i);
401 layout1->addWidget(sharpLongsProgressBar[i], 2, i);
404 for (int i=0; i<SHARP_SHORT_CNT; i++) {
405 sharpShortsSlider[i] = new QSlider(Qt::Horizontal);
406 sharpShortsProgressBar[i] = new QProgressBar();
407 sharpShortsProgressBar[i]->setMinimum(0);
408 sharpShortsProgressBar[i]->setMaximum(300);
409 sharpShortsProgressBar[i]->setValue(0);
410 sharpShortsLabel[i] =
411 MiscGui::createLabel(QString("SHORT%1").arg(i+1));
412 layout2->addWidget(sharpShortsLabel[i], 0, i);
413 layout2->addWidget(sharpShortsSlider[i], 1, i);
414 layout2->addWidget(sharpShortsProgressBar[i], 2, i);
417 sharpSensorsLayout->addLayout(layout3);
418 sharpSensorsLayout->addLayout(layout1);
419 sharpSensorsLayout->addLayout(layout2);
422 void RobomonExplorer::createRobots()
424 robotActPos = new Robot(NULL, playgroundScene, Qt::black);
425 robotActPos->setZValue(10);
426 robotEstPos = new Robot(NULL, playgroundScene, Qt::green);
427 robotEstPos->setZValue(10);
429 playgroundScene->addItem(robotActPos);
430 playgroundScene->addItem(robotEstPos);
433 /**********************************************************************
435 **********************************************************************/
436 void RobomonExplorer::createActions()
438 /* power management */
439 connect(voltage33CheckBox, SIGNAL(stateChanged(int)),
440 this, SLOT(setVoltage33(int)));
441 connect(voltage50CheckBox, SIGNAL(stateChanged(int)),
442 this, SLOT(setVoltage50(int)));
443 connect(voltage80CheckBox, SIGNAL(stateChanged(int)),
444 this, SLOT(setVoltage80(int)));
447 connect(leftMotorSlider, SIGNAL(valueChanged(int)),
448 this, SLOT(setLeftMotor(int)));
449 connect(rightMotorSlider, SIGNAL(valueChanged(int)),
450 this, SLOT(setRightMotor(int)));
451 connect(stopMotorsPushButton, SIGNAL(clicked()),
452 this, SLOT(stopMotors()));
455 connect(bottomDoorCheckBox, SIGNAL(stateChanged(int)),
456 this, SLOT(moveFrontDoor(int)));
457 connect(backDoorCheckBox, SIGNAL(stateChanged(int)),
458 this, SLOT(moveBackDoor(int)));
459 connect(topDoorCheckBox, SIGNAL(stateChanged(int)),
460 this, SLOT(moveTopDoor(int)));
461 connect(leftBrushCheckBox, SIGNAL(stateChanged(int)),
462 this, SLOT(moveLeftBrush(int)));
463 connect(rightBrushCheckBox, SIGNAL(stateChanged(int)),
464 this, SLOT(moveRightBrush(int)));
467 connect(leftBrushDial, SIGNAL(valueChanged(int)),
468 this, SLOT(setDrives(int)));
469 connect(rightBrushDial, SIGNAL(valueChanged(int)),
470 this, SLOT(setDrives(int)));
471 connect(bagrDial, SIGNAL(valueChanged(int)),
472 this, SLOT(setDrives(int)));
473 connect(carouselDial, SIGNAL(valueChanged(int)),
474 this, SLOT(setDrives(int)));
475 connect(leftBrushDriveCheckBox, SIGNAL(stateChanged(int)),
476 this, SLOT(setLeftBrushDriveCB(int)));
477 connect(rightBrushDriveCheckBox, SIGNAL(stateChanged(int)),
478 this, SLOT(setRightBrushDriveCB(int)));
479 connect(bagrDriveCheckBox, SIGNAL(stateChanged(int)),
480 this, SLOT(setBagrDriveCB(int)));
482 for (int i=0; i<8; i++)
483 connect(doCheckBox[0], SIGNAL(stateChanged(int)),
484 this, SLOT(setDO(int)));
487 connect(laserEngineCheckBox, SIGNAL(stateChanged(int)),
488 this, SLOT(setLaser(int)));
490 /* path planning map */
491 connect(showMapPushButton, SIGNAL(clicked()),
492 this, SLOT(showMap()));
494 /* sensors simulation */
495 simulationEnabled = 0;
496 connect(sensorsSimulationCheckBox, SIGNAL(stateChanged(int)),
497 this, SLOT(setSimulation(int)));
498 for (int i=0; i<3; i++)
499 connect(sharpLongsSlider[i], SIGNAL(valueChanged(int)),
500 this, SLOT(setSharpValues(int)));
501 for (int i=0; i<4; i++)
502 connect(sharpShortsSlider[i], SIGNAL(valueChanged(int)),
503 this, SLOT(setSharpValues(int)));
505 /* obstacle simulation */
506 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
507 this, SLOT(setSimulation(int)));
508 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
509 this, SLOT(setObstacleSimulation(int)));
510 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
511 playgroundScene, SLOT(showObstacle(int)));
512 connect(playgroundScene, SIGNAL(obstacleChanged(QPointF)),
513 this, SLOT(changeObstacle(QPointF)));
516 void RobomonExplorer::setVoltage33(int state)
519 orte_generic.pwr_ctrl.voltage33 = true;
521 orte_generic.pwr_ctrl.voltage33 = false;
524 void RobomonExplorer::setVoltage50(int state)
527 orte_generic.pwr_ctrl.voltage50 = true;
529 orte_generic.pwr_ctrl.voltage50 = false;
532 void RobomonExplorer::setVoltage80(int state)
535 orte_generic.pwr_ctrl.voltage80 = true;
537 orte_generic.pwr_ctrl.voltage80 = false;
540 void RobomonExplorer::setLeftMotor(int value)
543 short int rightMotor;
545 if(bothMotorsCheckBox->isChecked())
546 rightMotorSlider->setValue(value);
548 leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
549 rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
551 orte_generic.motion_speed.left = leftMotor;
552 orte_generic.motion_speed.right = rightMotor;
556 void RobomonExplorer::setRightMotor(int value)
559 short int rightMotor;
561 if(bothMotorsCheckBox->isChecked())
562 leftMotorSlider->setValue(value);
564 leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
565 rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
567 orte_generic.motion_speed.left = leftMotor;
568 orte_generic.motion_speed.right = rightMotor;
572 void RobomonExplorer::stopMotors()
574 leftMotorSlider->setValue(0);
575 rightMotorSlider->setValue(0);
578 void RobomonExplorer::moveServos(int value)
580 /* FIXME: servos action comes here */
583 void RobomonExplorer::moveFrontDoor(int state)
586 orte_eb2008.servos.door_bottom = BOTTOM_DOOR_OPEN;
588 orte_eb2008.servos.door_bottom = BOTTOM_DOOR_CLOSE;
591 void RobomonExplorer::moveTopDoor(int state)
594 orte_eb2008.servos.door_top = TOP_DOOR_OPEN;
596 orte_eb2008.servos.door_top = TOP_DOOR_CLOSE;
599 void RobomonExplorer::moveBackDoor(int state)
602 orte_eb2008.servos.door_back = BACK_DOOR_OPEN;
604 orte_eb2008.servos.door_back = BACK_DOOR_CLOSE;
607 void RobomonExplorer::moveLeftBrush(int state)
610 orte_eb2008.servos.brush_left = BRUSH_LEFT_OPEN;
612 orte_eb2008.servos.brush_left = BRUSH_LEFT_CLOSE;
615 void RobomonExplorer::moveRightBrush(int state)
618 orte_eb2008.servos.brush_right = BRUSH_RIGHT_OPEN;
620 orte_eb2008.servos.brush_right = BRUSH_RIGHT_CLOSE;
623 void RobomonExplorer::setDrives(int state)
625 orte_eb2008.drives.brush_left = leftBrushDial->value();
626 orte_eb2008.drives.brush_right = rightBrushDial->value();
627 orte_eb2008.drives.bagr = bagrDial->value();
628 orte_eb2008.drives.carousel_pos = carouselDial->value();
631 void RobomonExplorer::setLeftBrushDriveCB(int state) {
634 orte_eb2008.drives.brush_left = LEFT_BRUSH_DRIVE_ON;
636 orte_eb2008.drives.brush_left = LEFT_BRUSH_DRIVE_OFF;
640 void RobomonExplorer::setRightBrushDriveCB(int state) {
643 orte_eb2008.drives.brush_right = RIGHT_BRUSH_DRIVE_ON;
645 orte_eb2008.drives.brush_right = RIGHT_BRUSH_DRIVE_OFF;
649 void RobomonExplorer::setBagrDriveCB(int state) {
652 orte_eb2008.drives.bagr = BAGR_DRIVE_ON;
654 orte_eb2008.drives.bagr = BAGR_DRIVE_OFF;
657 void RobomonExplorer::setDO(int state)
659 /* FIXME: digital output control comes here */
662 void RobomonExplorer::setLaser(int state) {
665 orte_eb2008.laser_cmd.speed = LASER_DRIVE_ON;
667 orte_eb2008.laser_cmd.speed = LASER_DRIVE_OFF;
668 ORTEPublicationSend(orte_eb2008.publication_laser_cmd);
671 void RobomonExplorer::showMap()
675 if (sharedMemoryOpened == false)
678 mapTimer = new QTimer(this);
679 connect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
680 mapTimer->start(200);
682 showMapPushButton->setText(tr("Show Playground"));
683 showMapPushButton->setShortcut(tr("p"));
684 disconnect(showMapPushButton, SIGNAL(clicked()), this, SLOT(showMap()));
685 connect(showMapPushButton, SIGNAL(clicked()),
686 this, SLOT(showPlayground()));
689 void RobomonExplorer::showPlayground()
692 disconnect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
696 showMapPushButton->setText(tr("Show &map"));
697 showMapPushButton->setShortcut(tr("m"));
698 disconnect(showMapPushButton, SIGNAL(clicked()),
699 this, SLOT(showPlayground()));
700 connect(showMapPushButton, SIGNAL(clicked()), this, SLOT(showMap()));
703 void RobomonExplorer::paintMap()
706 static QGraphicsRectItem *rects[MAP_WIDTH][MAP_HEIGHT];
707 static bool firstMap = true;
709 struct map *map = ShmapIsMapInit();
713 for(int i=0; i < MAP_WIDTH; i++) {
714 for(int j=0; j<MAP_HEIGHT; j++) {
715 x = TOP_LEFT_X+i*cellSize;
716 y = TOP_LEFT_Y+j*cellSize;
719 rects[i][j] = playgroundScene->addRect(
720 QRectF(x,y,cellSize,cellSize),
721 QPen(QBrush(Qt::black),
726 QBrush(Qt::lightGray));
727 rects[i][j]->setZValue(4);
732 struct map_cell *cell = &map->cells[j][i];
734 if (cell->flags & MAP_FLAG_WALL)
736 if (cell->flags & MAP_FLAG_SIMULATED_WALL)
738 if (cell->flags & MAP_FLAG_PATH)
740 if (cell->flags & MAP_FLAG_START)
742 if (cell->flags & MAP_FLAG_GOAL)
744 if (cell->detected_obstacle) {
745 QColor c1(color), c2(blue);
746 double f = (double)cell->detected_obstacle/MAP_NEW_OBSTACLE*0.7;
747 QColor c(c1.red() + (int)(f*(c2.red() - c1.red())),
748 c1.green() + (int)(f*(c2.green() - c1.green())),
749 c1.blue() + (int)(f*(c2.blue() - c1.blue())));
752 if (cell->flags & MAP_FLAG_DET_OBST)
755 rects[i][j]->setBrush(QBrush(color));
761 void RobomonExplorer::setSharpValues(int value)
763 // FIXME: sharp control
765 if (!simulationEnabled) {
766 simulationEnabled = 1;
767 createSharpLongsPublisher(this, &orteData);
768 createSharpShortsPublisher(this, &orteData);
769 sensorsSimulationCheckBox->setChecked(true);
772 orteData.orteSharpWaste.short1 = sharpShortsSlider[0]->value();
773 orteData.orteSharpWaste.short2 = sharpShortsSlider[1]->value();
774 orteData.orteSharpWaste.short3 = sharpShortsSlider[2]->value();
775 orteData.orteSharpWaste.short4 = sharpShortsSlider[3]->value();
776 ORTEPublicationSend(orteData.publisherSharpShort);
777 orteData.orteSharpOpponent.longSharpDist1 =
778 sharpLongsSlider[0]->value()/1000.0;
779 orteData.orteSharpOpponent.longSharpDist2 =
780 sharpLongsSlider[1]->value()/1000.0;
781 orteData.orteSharpOpponent.longSharpDist3 =
782 sharpLongsSlider[2]->value()/1000.0;
783 ORTEPublicationSend(orteData.publisherSharpLong);
787 void RobomonExplorer::setSimulation(int state)
790 eb2008_publisher_sharps_create(&orte_eb2008,
791 dummy_publisher_callback, this);
793 if (!simulationEnabled)
795 eb2008_publisher_sharps_destroy(&orte_eb2008);
797 simulationEnabled = state;
801 \fn RobomonExplorer::setObstacleSimulation(int state)
803 void RobomonExplorer::setObstacleSimulation(int state)
806 /* TODO Maybe it is possible to attach only once to Shmap */
808 obstacleSimulationTimer = new QTimer(this);
809 connect(obstacleSimulationTimer, SIGNAL(timeout()),
810 this, SLOT(simulateObstacles()));
811 obstacleSimulationTimer->start(100);
812 setMouseTracking(true);
814 if (obstacleSimulationTimer)
815 delete obstacleSimulationTimer;
816 double distance = 0.8;
817 orte_eb2008.sharps.left = distance;
818 orte_eb2008.sharps.front_left = distance;
819 orte_eb2008.sharps.front_right = distance;
820 orte_eb2008.sharps.right = distance;
821 ORTEPublicationSend(orte_eb2008.publication_sharps);
826 \fn RobomonExplorer::simulateObstacles()
828 void RobomonExplorer::simulateObstacles()
830 double distance, wall_distance;
833 &orte_eb2008.sharps.left,
834 &orte_eb2008.sharps.right,
835 &orte_eb2008.sharps.front_left,
836 &orte_eb2008.sharps.front_right
840 for (i=0; i<4; i++) {
841 wall_distance = distanceToWall(i);
842 distance = distanceToObstacle(i, simulatedObstacle, 0.5/*meters*/);
843 if (wall_distance < distance)
844 distance = wall_distance;
845 *sharp[i] = distance;
847 ORTEPublicationSend(orte_eb2008.publication_sharps);
851 orteData.orteSharpOpponent.longSharpDist1 = distance;
852 orteData.orteSharpOpponent.longSharpDist2 = distance;
853 orteData.orteSharpOpponent.longSharpDist3 = distance;
854 ORTEPublicationSend(orteData.publisherSharpLong);*/
857 void RobomonExplorer::changeObstacle(QPointF position)
859 if (!simulationEnabled) {
860 simulationEnabled = 1;
862 // createSharpLongsPublisher(this, &orteData);
863 // createSharpShortsPublisher(this, &orteData);
864 obstacleSimulationCheckBox->setChecked(true);
867 simulatedObstacle.x = position.x();
868 simulatedObstacle.y = position.y();
872 /**********************************************************************
874 **********************************************************************/
875 bool RobomonExplorer::event(QEvent *event)
877 switch (event->type()) {
878 case QEVENT(QEV_MOTION_STATUS):
879 emit motionStatusReceivedSignal();
881 case QEVENT(QEV_ACTUAL_POSITION):
882 emit actualPositionReceivedSignal();
884 case QEVENT(QEV_ESTIMATED_POSITION):
885 emit estimatedPositionReceivedSignal();
887 case QEVENT(QEV_SHARP_LONGS):
888 emit sharpLongsReceivedSignal();
890 case QEVENT(QEV_SHARP_SHORTS):
891 emit sharpShortsReceivedSignal();
893 case QEVENT(QEV_SHARPS):
894 emit sharpsReceivedSignal();
897 emit diReceivedSignal();
899 case QEVENT(QEV_ACCELEROMETER):
900 emit accelerometerReceivedSignal();
902 case QEVENT(QEV_ACCUMULATOR):
903 emit accumulatorReceivedSignal();
905 case QEVENT(QEV_POWER_VOLTAGE):
906 emit powerVoltageReceivedSignal();
909 if (event->type() == QEvent::Close)
910 closeEvent((QCloseEvent *)event);
911 else if (event->type() == QEvent::KeyPress)
912 keyPressEvent((QKeyEvent *)event);
913 else if (event->type() == QEvent::KeyRelease)
914 keyReleaseEvent((QKeyEvent *)event);
915 else if (event->type() == QEvent::FocusIn)
917 else if (event->type() == QEvent::FocusOut)
929 void RobomonExplorer::keyPressEvent(QKeyEvent *event)
933 if (event->isAutoRepeat()) {
934 switch (event->key()) {
936 peak = leftMotorSlider->minimum()/2;
937 if (leftMotorValue < peak ||
938 rightMotorValue < peak)
942 leftMotorValue *= gain;
943 rightMotorValue *= gain;
944 leftMotorSlider->setValue((int)leftMotorValue);
945 rightMotorSlider->setValue((int)rightMotorValue);
951 peak = leftMotorSlider->maximum()/2;
952 if (leftMotorValue > peak ||
953 rightMotorValue > peak)
957 leftMotorValue *= gain;
958 rightMotorValue *= gain;
959 leftMotorSlider->setValue((int)leftMotorValue);
960 rightMotorSlider->setValue((int)rightMotorValue);
970 switch (event->key()) {
974 bothMotorsCheckBox->setChecked(true);
975 leftMotorSlider->setValue((int)leftMotorValue);
976 setLeftMotor((int)leftMotorValue);
980 rightMotorValue = -1;
981 bothMotorsCheckBox->setChecked(true);
982 leftMotorSlider->setValue((int)leftMotorValue);
983 setLeftMotor((int)leftMotorValue);
988 leftMotorSlider->setValue((int)leftMotorValue);
989 rightMotorSlider->setValue((int)rightMotorValue);
990 setLeftMotor((int)leftMotorValue);
991 setRightMotor((int)leftMotorValue);
995 rightMotorValue = -1;
996 leftMotorSlider->setValue((int)leftMotorValue);
997 rightMotorSlider->setValue((int)rightMotorValue);
998 setLeftMotor((int)leftMotorValue);
999 setRightMotor((int)rightMotorValue);
1008 void RobomonExplorer::keyReleaseEvent(QKeyEvent *event)
1010 if (event->isAutoRepeat()) {
1015 switch (event->key()) {
1021 rightMotorValue = 0;
1022 bothMotorsCheckBox->setChecked(false);
1023 leftMotorSlider->setValue((int)leftMotorValue);
1024 rightMotorSlider->setValue((int)rightMotorValue);
1033 void RobomonExplorer::closeEvent(QCloseEvent *event)
1035 generic_roboorte_destroy(&orte_generic);
1036 eb2008_roboorte_destroy(&orte_eb2008);
1039 /**********************************************************************
1041 **********************************************************************/
1042 void RobomonExplorer::createOrte()
1044 orte_generic.strength = 11;
1045 orte_eb2008.strength = 11;
1047 generic_roboorte_init(&orte_generic);
1048 eb2008_roboorte_init(&orte_eb2008);
1051 generic_publisher_motion_speed_create(&orte_generic, dummy_publisher_callback, NULL);
1053 generic_publisher_pwr_ctrl_create(&orte_generic, dummy_publisher_callback, NULL);
1055 eb2008_publisher_servos_create(&orte_eb2008, dummy_publisher_callback, NULL);
1056 eb2008_publisher_drives_create(&orte_eb2008, dummy_publisher_callback, NULL);
1057 eb2008_publisher_laser_cmd_create(&orte_eb2008, NULL, NULL);
1060 generic_subscriber_pwr_voltage_create(&orte_generic,
1061 receivePowerVoltageCallBack, this);
1062 generic_subscriber_motion_status_create(&orte_generic,
1063 receiveMotionStatusCallBack, this);
1064 generic_subscriber_ref_pos_create(&orte_generic,
1065 receiveActualPositionCallBack, this);
1066 generic_subscriber_est_pos_create(&orte_generic,
1067 receiveEstimatedPositionCallBack, this);
1069 eb2008_subscriber_sharps_create(&orte_eb2008,
1070 receiveSharpsCallBack, this);
1072 /*createDISubscriber(this, &orteData);*/
1073 /*createAccelerometerSubscriber(this, &orteData);*/
1074 /*createAccumulatorSubscriber(this, &orteData);*/
1076 orte_generic.motion_speed.left = 0;
1077 orte_generic.motion_speed.right = 0;
1078 /* power management */
1079 orte_generic.pwr_ctrl.voltage33 = true;
1080 orte_generic.pwr_ctrl.voltage50 = true;
1081 orte_generic.pwr_ctrl.voltage80 = true;
1082 voltage33CheckBox->setChecked(true);
1083 voltage50CheckBox->setChecked(true);
1084 voltage80CheckBox->setChecked(true);
1087 orte_eb2008.servos.door_bottom = FRONT_DOOR_UP; //FIXME
1088 orte_eb2008.servos.door_back = BACK_DOOR_UP; //FIXME
1089 orte_eb2008.servos.door_top = TOP_DOOR_UP; //FIXME
1090 bottomDoorCheckBox->setChecked(true);
1091 backDoorCheckBox->setChecked(true);
1092 topDoorCheckBox->setChecked(true);
1093 leftBrushCheckBox->setChecked(false);
1094 rightBrushCheckBox->setChecked(false);
1099 /* set actions to do when we receive data from orte */
1100 connect(this, SIGNAL(motionStatusReceivedSignal()),
1101 this, SLOT(motionStatusReceived()));
1102 connect(this, SIGNAL(actualPositionReceivedSignal()),
1103 this, SLOT(actualPositionReceived()));
1104 connect(this, SIGNAL(estimatedPositionReceivedSignal()),
1105 this, SLOT(estimatedPositionReceived()));
1106 connect(this, SIGNAL(sharpsReceivedSignal()),
1107 this, SLOT(sharpsReceived()));
1108 connect(this, SIGNAL(diReceivedSignal()),
1109 this, SLOT(diReceived()));
1110 connect(this, SIGNAL(accelerometerReceivedSignal()),
1111 this, SLOT(accelerometerReceived()));
1112 connect(this, SIGNAL(accumulatorReceivedSignal()),
1113 this, SLOT(accumulatorReceived()));
1114 connect(this, SIGNAL(powerVoltageReceivedSignal()),
1115 this, SLOT(powerVoltageReceived()));
1118 void RobomonExplorer::motionStatusReceived()
1120 WDBG("ORTE received: motion status");
1123 void RobomonExplorer::actualPositionReceived()
1125 actPosX->setText(QString("%1").arg(orte_generic.ref_pos.x, 0, 'f', 3));
1126 actPosY->setText(QString("%1").arg(orte_generic.ref_pos.y, 0, 'f', 3));
1127 actPosPhi->setText(QString("%1(%2)")
1128 .arg(DEGREES(orte_generic.ref_pos.phi), 0, 'f', 0)
1129 .arg(orte_generic.ref_pos.phi, 0, 'f', 1));
1130 robotActPos->moveRobot(orte_generic.ref_pos.x,
1131 orte_generic.ref_pos.y, orte_generic.ref_pos.phi);
1134 void RobomonExplorer::estimatedPositionReceived()
1136 estPosX->setText(QString("%1").arg(orte_generic.est_pos.x, 0, 'f', 3));
1137 estPosY->setText(QString("%1").arg(orte_generic.est_pos.y, 0, 'f', 3));
1138 estPosPhi->setText(QString("%1(%2)")
1139 .arg(DEGREES(orte_generic.est_pos.phi), 0, 'f', 0)
1140 .arg(orte_generic.est_pos.phi, 0, 'f', 1));
1141 robotEstPos->moveRobot(orte_generic.est_pos.x,
1142 orte_generic.est_pos.y, orte_generic.est_pos.phi);
1145 void RobomonExplorer::sharpsReceived()
1147 int val_long[SHARP_LONG_CNT];
1148 int val_short[SHARP_SHORT_CNT];
1150 // WDBG("ORTE received: sharps");
1152 val_long[0] = (int)((double)orte_eb2008.sharps.left * 1000);
1153 val_long[1] = (int)((double)orte_eb2008.sharps.front_left * 1000);
1154 val_long[2] = (int)((double)orte_eb2008.sharps.front_right * 1000);
1155 val_long[3] = (int)((double)orte_eb2008.sharps.right * 1000);
1157 val_short[0] = (int)((double)orte_eb2008.sharps.back_left * 1000);
1158 val_short[1] = (int)((double)orte_eb2008.sharps.back_right * 1000);
1160 for (int i=0; i<SHARP_LONG_CNT; i++) {
1161 sharpLongsLabel[i]->setText(QString("%1mm").arg(val_long[i]));
1162 if (val_long[i] > sharpLongsProgressBar[i]->maximum())
1163 val_long[i] = sharpLongsProgressBar[i]->maximum();
1164 sharpLongsProgressBar[i]->setValue(
1165 sharpLongsProgressBar[i]->maximum()-val_long[i]);
1168 for (int i=0; i<SHARP_SHORT_CNT; i++) {
1169 sharpShortsLabel[i]->setText(QString("%1").arg(val_short[i]));
1170 sharpShortsProgressBar[i]->setValue(
1171 sharpShortsProgressBar[i]->maximum()-val_short[i]);
1176 void RobomonExplorer::diReceived()
1178 WDBG("ORTE received: DI");
1181 void RobomonExplorer::accelerometerReceived()
1183 WDBG("ORTE received: accelerometer");
1186 void RobomonExplorer::accumulatorReceived()
1188 WDBG("ORTE received: accumulator");
1191 void RobomonExplorer::powerVoltageReceived()
1193 voltage33LineEdit->setText(QString("%1").arg(
1194 orte_generic.pwr_voltage.voltage33, 0, 'f', 3));
1195 voltage50LineEdit->setText(QString("%1").arg(
1196 orte_generic.pwr_voltage.voltage50, 0, 'f', 3));
1197 voltage80LineEdit->setText(QString("%1").arg(
1198 orte_generic.pwr_voltage.voltage80, 0, 'f', 3));
1199 voltageBATLineEdit->setText(QString("%1").arg(
1200 orte_generic.pwr_voltage.voltageBAT, 0, 'f', 3));
1204 /**********************************************************************
1206 **********************************************************************/
1207 void RobomonExplorer::openSharedMemory()
1210 int sharedSegmentSize;
1212 if (sharedMemoryOpened)
1215 cellSize = PG_X / MAP_WIDTH;
1217 sharedSegmentSize = sizeof(char) * MAP_WIDTH * MAP_HEIGHT;
1219 /* Get segment identificator in a read only mode */
1220 segmentId = shmget(SHM_MAP_KEY, sharedSegmentSize, S_IRUSR);
1221 if(segmentId == -1) {
1222 QMessageBox::critical(this, "robomon",
1223 "Unable to open shared memory segment!");
1230 /* Attach the shared memory segment */
1231 //map = (_Map*)shmat (segmentId, (void*) 0, 0);
1233 sharedMemoryOpened = true;
1236 double RobomonExplorer::distanceToWall(int sharpnum)
1238 double distance=0.8, min_distance=0.8;
1241 struct map *map = ShmapIsMapInit();
1243 if (!map) return min_distance;
1245 // Simulate obstacles
1246 for(j=0;j<MAP_HEIGHT;j++) {
1247 for (i=0;i<MAP_WIDTH;i++) {
1248 struct map_cell *cell = &map->cells[j][i];
1249 if( cell->flags & MAP_FLAG_SIMULATED_WALL) {
1251 ShmapCell2Point(i, j, &wall.x, &wall.y);
1253 distance = distanceToObstacle(sharpnum, wall, MAP_CELL_SIZE_M);
1254 if (distance<min_distance) min_distance = distance;
1259 return min_distance;
1263 * Calculation for sensor simulation. Calculates distance that would
1264 * be returned by IR sensors, if there is only one obstacle (as
1265 * specified by parameters).
1267 * @param obstacle Position of the obstacle (x, y in meters).
1268 * @param obstacleSize Size (diameter) of the obstacle in meters.
1270 * @return Distance measured by sensors in meters.
1272 double RobomonExplorer::distanceToObstacle(int sharpnum, Point obstacle, double obstacleSize)
1274 struct est_pos_type e = orte_generic.est_pos;
1276 struct sharp_pos s = sharp[sharpnum];
1277 Point sensor(e.x + s.x*cos(e.phi) - s.y*sin(e.phi),
1278 e.y + s.x*sin(e.phi) + s.y*cos(e.phi));
1279 sensor_a = e.phi + s.ang;
1281 const double sensorRange = 0.8; /*[meters]*/
1283 double distance, angle;
1285 angle = sensor.angleTo(obstacle) - sensor_a;
1286 angle = fmod(angle, 2.0*M_PI);
1287 if (angle > +M_PI) angle -= 2.0*M_PI;
1288 if (angle < -M_PI) angle += 2.0*M_PI;
1289 angle = fabs(angle);
1290 distance = sensor.distanceTo(obstacle)-0.11;
1291 if (angle < atan(obstacleSize/2.0 / (distance+0.001))) {
1292 // We can see the obstackle from here.
1293 if (angle < M_PI/2.0) {
1294 distance = distance/cos(angle);
1296 if (distance > sensorRange)
1297 distance = sensorRange;
1299 distance = sensorRange;