2 * RobomonAtlantis.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>
33 #include "PlaygroundScene.h"
35 #include "robomon_orte.h"
36 #include "RobomonAtlantis.h"
38 #include <QCoreApplication>
42 #include <QMessageBox>
45 RobomonAtlantis::RobomonAtlantis(QWidget *parent)
52 debugWindowEnabled = false;
57 QHBoxLayout *mainLayout = new QHBoxLayout;
58 mainLayout->addLayout(leftLayout);
59 mainLayout->addLayout(rightLayout);
60 setLayout(mainLayout);
66 setFocusPolicy(Qt::StrongFocus);
67 sharedMemoryOpened = false;
68 WDBG("Youuuhouuuu!!");
71 /**********************************************************************
73 **********************************************************************/
74 void RobomonAtlantis::createLeftLayout()
76 leftLayout = new QVBoxLayout();
78 createDebugGroupBox();
79 debugWindowEnabled = true;
80 createPlaygroundGroupBox();
82 leftLayout->addWidget(playgroundGroupBox);
83 leftLayout->addWidget(debugGroupBox);
86 void RobomonAtlantis::createRightLayout()
88 rightLayout = new QVBoxLayout();
89 QGridLayout *layout = new QGridLayout();
90 QVBoxLayout *vlayout = new QVBoxLayout();
92 createPositionGroupBox();
94 createActuatorsGroupBox();
96 createPowerGroupBox();
97 createSensorsGroupBox();
99 vlayout->addWidget(positionGroupBox);
100 vlayout->addWidget(miscGroupBox);
101 layout->addLayout(vlayout, 0, 0);
102 layout->addWidget(actuatorsGroupBox, 0, 1);
103 // layout->addWidget(dioGroupBox, 0, 2);
105 rightLayout->addLayout(layout);
106 rightLayout->addWidget(powerGroupBox);
107 rightLayout->addWidget(sensorsGroupBox);
110 void RobomonAtlantis::createPlaygroundGroupBox()
112 playgroundGroupBox = new QGroupBox(tr("Playground"));
113 QHBoxLayout *layout = new QHBoxLayout();
116 new PlaygroundScene(PlaygroundScene::PLAYGROUND_EUROBOT2008);
117 playgroundSceneView = new QGraphicsView(playgroundScene);
118 playgroundSceneView->setMinimumWidth((int)(playgroundScene->width())+15);
119 playgroundSceneView->setMinimumHeight((int)(playgroundScene->height())+15);
120 layout->addWidget(playgroundSceneView);
122 playgroundGroupBox->setLayout(layout);
125 void RobomonAtlantis::createPositionGroupBox()
127 positionGroupBox = new QGroupBox(tr("Position state"));
128 QGridLayout *layout = new QGridLayout();
130 actPosX = new QLineEdit();
131 actPosY = new QLineEdit();
132 actPosPhi = new QLineEdit();
134 estPosX = new QLineEdit();
135 estPosY = new QLineEdit();
136 estPosPhi = new QLineEdit();
138 actPosX->setReadOnly(true);
139 actPosY->setReadOnly(true);
140 actPosPhi->setReadOnly(true);
142 estPosX->setReadOnly(true);
143 estPosY->setReadOnly(true);
144 estPosPhi->setReadOnly(true);
146 layout->addWidget(MiscGui::createLabel("X"), 1, 0);
147 layout->addWidget(MiscGui::createLabel("Y"), 2, 0);
148 layout->addWidget(MiscGui::createLabel("Phi"), 3, 0);
150 layout->addWidget(MiscGui::createLabel("X"), 5, 0);
151 layout->addWidget(MiscGui::createLabel("Y"), 6, 0);
152 layout->addWidget(MiscGui::createLabel("Phi"), 7, 0);
154 layout->addWidget(MiscGui::createLabel("Actual", Qt::AlignLeft), 0, 1);
155 layout->addWidget(actPosX, 1, 1);
156 layout->addWidget(actPosY, 2, 1);
157 layout->addWidget(actPosPhi, 3, 1);
159 layout->addWidget(MiscGui::createLabel("Estimated", Qt::AlignLeft), 4, 1);
160 layout->addWidget(estPosX, 5, 1);
161 layout->addWidget(estPosY, 6, 1);
162 layout->addWidget(estPosPhi, 7, 1);
164 positionGroupBox->setLayout(layout);
167 void RobomonAtlantis::createMiscGroupBox()
169 miscGroupBox = new QGroupBox(tr("Miscellaneous"));
170 QGridLayout *layout = new QGridLayout();
172 showMapPushButton = new QPushButton(tr("Show &map"));
173 showMapPushButton->setShortcut(tr("m"));
175 laserEngineCheckBox = new QCheckBox(tr("L&aser"));
176 laserEngineCheckBox->setShortcut(tr("a"));
178 layout->addWidget(showMapPushButton, 0, 0);
179 layout->addWidget(laserEngineCheckBox, 1, 0);
181 miscGroupBox->setLayout(layout);
184 void RobomonAtlantis::createDebugGroupBox()
186 debugGroupBox = new QGroupBox(tr("Debug window"));
187 QHBoxLayout *layout = new QHBoxLayout();
189 debugWindow = new QTextEdit();
190 debugWindow->setReadOnly(true);
192 layout->addWidget(debugWindow);
193 debugGroupBox->setLayout(layout);
196 void RobomonAtlantis::createActuatorsGroupBox()
198 actuatorsGroupBox = new QGroupBox(tr("Actuators"));
199 QHBoxLayout *layout = new QHBoxLayout();
201 createMotorsGroupBox();
202 createServosGroupBox();
203 createDrivesGroupBox();
205 layout->setAlignment(Qt::AlignLeft);
206 layout->addWidget(enginesGroupBox);
207 layout->addWidget(servosGroupBox);
208 layout->addWidget(drivesGroupBox);
209 actuatorsGroupBox->setLayout(layout);
212 void RobomonAtlantis::createDIOGroupBox()
214 dioGroupBox = new QGroupBox(tr("DIO"));
215 QGridLayout *layout = new QGridLayout();
218 font.setPointSize(5);
219 dioGroupBox->setFont(font);
221 for (int i=0; i<8; i++) {
222 diCheckBox[i] = new QCheckBox(QString("DI%1").arg(i));
223 doCheckBox[i] = new QCheckBox(QString("D0%1").arg(i));
224 layout->addWidget(diCheckBox[i], i, 0);
225 layout->addWidget(doCheckBox[i], i+8, 0);
228 dioGroupBox->setMaximumWidth(70);
229 dioGroupBox->setLayout(layout);
232 void RobomonAtlantis::createPowerGroupBox()
234 powerGroupBox = new QGroupBox(tr("Power management"));
235 QGridLayout *layout = new QGridLayout();
237 voltage33CheckBox = new QCheckBox(tr("&3.3V"));
238 voltage50CheckBox = new QCheckBox(tr("&5.0V"));
239 voltage80CheckBox = new QCheckBox(tr("&8.0V"));
241 voltage33CheckBox->setShortcut(tr("3"));
242 voltage50CheckBox->setShortcut(tr("5"));
243 voltage80CheckBox->setShortcut(tr("8"));
245 layout->addWidget(voltage33CheckBox, 0, 0);
246 layout->addWidget(voltage50CheckBox, 0, 2);
247 layout->addWidget(voltage80CheckBox, 0, 4); //1, 0);
248 layout->addWidget(MiscGui::createLabel("BAT"), 0, 6); //1, 2);
250 voltage33LineEdit = new QLineEdit();
251 voltage50LineEdit = new QLineEdit();
252 voltage80LineEdit = new QLineEdit();
253 voltageBATLineEdit = new QLineEdit();
255 voltage33LineEdit->setReadOnly(true);
256 voltage50LineEdit->setReadOnly(true);
257 voltage80LineEdit->setReadOnly(true);
258 voltageBATLineEdit->setReadOnly(true);
260 layout->addWidget(voltage33LineEdit, 0, 1);
261 layout->addWidget(voltage50LineEdit, 0, 3);
262 layout->addWidget(voltage80LineEdit, 0, 5); //1, 1);
263 layout->addWidget(voltageBATLineEdit, 0, 7); //1, 3);
265 powerGroupBox->setLayout(layout);
268 void RobomonAtlantis::createSensorsGroupBox()
270 sensorsGroupBox = new QGroupBox(tr("Sensors"));
271 QVBoxLayout *layout = new QVBoxLayout();
273 createSharpSensorsLayout();
275 layout->addLayout(sharpSensorsLayout);
276 sensorsGroupBox->setLayout(layout);
279 void RobomonAtlantis::createMotorsGroupBox()
281 enginesGroupBox = new QGroupBox(tr("Motors"));
282 QVBoxLayout *layout = new QVBoxLayout();
283 QHBoxLayout *layout1 = new QHBoxLayout();
284 QHBoxLayout *layout2 = new QHBoxLayout();
286 leftMotorSlider = new QSlider(Qt::Vertical);
287 rightMotorSlider = new QSlider(Qt::Vertical);
288 bothMotorsCheckBox = new QCheckBox(tr("Lock both"));
289 stopMotorsPushButton = new QPushButton(tr("Stop Motors"));
291 leftMotorSlider->setMinimum(-100);
292 leftMotorSlider->setMaximum(100);
293 leftMotorSlider->setTracking(false);
294 leftMotorSlider->setTickPosition(QSlider::TicksLeft);
296 rightMotorSlider->setMinimum(-100);
297 rightMotorSlider->setMaximum(100);
298 rightMotorSlider->setTracking(false);
299 rightMotorSlider->setTickPosition(QSlider::TicksRight);
301 stopMotorsPushButton->setMaximumWidth(90);
303 layout1->addWidget(leftMotorSlider);
304 layout1->addWidget(MiscGui::createLabel("0"));
305 layout1->addWidget(rightMotorSlider);
307 layout2->addWidget(bothMotorsCheckBox);
309 layout->addWidget(MiscGui::createLabel("100"));
310 layout->addLayout(layout1);
311 layout->addWidget(MiscGui::createLabel("-100"));
312 layout->addLayout(layout2);
313 layout->addWidget(stopMotorsPushButton);
314 enginesGroupBox->setLayout(layout);
317 void RobomonAtlantis::createServosGroupBox()
319 servosGroupBox = new QGroupBox(tr("Servos"));
320 QGridLayout *layout = new QGridLayout();
322 leftBrushCheckBox = new QCheckBox(tr("&Left Brush"));
323 rightBrushCheckBox = new QCheckBox(tr("&Right Brush"));
324 pusherCheckBox = new QCheckBox(tr("&Pusher"));
326 leftBrushCheckBox->setShortcut(tr("l"));
327 rightBrushCheckBox->setShortcut(tr("r"));
328 pusherCheckBox->setShortcut(tr("p"));
330 layout->addWidget(leftBrushCheckBox, 0, 0);
331 layout->addWidget(rightBrushCheckBox, 1, 0);
332 layout->addWidget(pusherCheckBox, 2, 0);
333 servosGroupBox->setLayout(layout);
337 void RobomonAtlantis::createDrivesGroupBox()
339 drivesGroupBox = new QGroupBox(tr("Drives"));
340 QGridLayout *layout = new QGridLayout();
342 leftBrushDial = new QDial();
343 rightBrushDial = new QDial();
344 bagrDial = new QDial();
345 carouselDial = new QDial();
347 leftBrushDriveCheckBox = new QCheckBox(tr("L&eft brush"));
348 rightBrushDriveCheckBox = new QCheckBox(tr("Ri&ght brush"));
349 bagrDriveCheckBox = new QCheckBox(tr("B&agr"));
351 leftBrushDial->setRange(0,200);
352 leftBrushDial->setValue(100);
353 rightBrushDial->setRange(0,200);
354 rightBrushDial->setValue(100);
355 bagrDial->setRange(0,200);
356 bagrDial->setValue(100);
357 carouselDial->setRange(0,4);
358 carouselDial->setNotchesVisible(1);
360 layout->addWidget(leftBrushDial, 0, 0);
361 layout->addWidget(leftBrushDriveCheckBox, 0, 1);
362 layout->addWidget(rightBrushDial, 1, 0);
363 layout->addWidget(rightBrushDriveCheckBox, 1, 1);
364 layout->addWidget(bagrDial, 2, 0);
365 layout->addWidget(bagrDriveCheckBox, 2, 1);
366 layout->addWidget(carouselDial, 3, 0);
367 drivesGroupBox->setLayout(layout);
370 void RobomonAtlantis::createSharpSensorsLayout()
372 sharpSensorsLayout = new QVBoxLayout();
373 QGridLayout *layout3 = new QGridLayout();
375 obstacleSimulationCheckBox = new QCheckBox(tr("&Obstacle simulation"));
377 obstacleSimulationCheckBox->setShortcut(tr("o"));
379 layout3->addWidget(obstacleSimulationCheckBox, 0, 1);
381 sharpSensorsLayout->addLayout(layout3);
384 void RobomonAtlantis::createRobots()
386 robotActPos = new Robot(NULL, playgroundScene, Qt::black);
387 robotActPos->setZValue(10);
388 robotEstPos = new Robot(NULL, playgroundScene, Qt::green);
389 robotEstPos->setZValue(10);
391 playgroundScene->addItem(robotActPos);
392 playgroundScene->addItem(robotEstPos);
395 /**********************************************************************
397 **********************************************************************/
398 void RobomonAtlantis::createActions()
400 /* power management */
401 connect(voltage33CheckBox, SIGNAL(stateChanged(int)),
402 this, SLOT(setVoltage33(int)));
403 connect(voltage50CheckBox, SIGNAL(stateChanged(int)),
404 this, SLOT(setVoltage50(int)));
405 connect(voltage80CheckBox, SIGNAL(stateChanged(int)),
406 this, SLOT(setVoltage80(int)));
409 connect(leftMotorSlider, SIGNAL(valueChanged(int)),
410 this, SLOT(setLeftMotor(int)));
411 connect(rightMotorSlider, SIGNAL(valueChanged(int)),
412 this, SLOT(setRightMotor(int)));
413 connect(stopMotorsPushButton, SIGNAL(clicked()),
414 this, SLOT(stopMotors()));
417 connect(leftBrushCheckBox, SIGNAL(stateChanged(int)),
418 this, SLOT(moveLeftBrush(int)));
419 connect(rightBrushCheckBox, SIGNAL(stateChanged(int)),
420 this, SLOT(moveRightBrush(int)));
423 connect(leftBrushDial, SIGNAL(valueChanged(int)),
424 this, SLOT(setDrives(int)));
425 connect(rightBrushDial, SIGNAL(valueChanged(int)),
426 this, SLOT(setDrives(int)));
427 connect(bagrDial, SIGNAL(valueChanged(int)),
428 this, SLOT(setDrives(int)));
429 connect(carouselDial, SIGNAL(valueChanged(int)),
430 this, SLOT(setDrives(int)));
431 connect(leftBrushDriveCheckBox, SIGNAL(stateChanged(int)),
432 this, SLOT(setLeftBrushDriveCB(int)));
433 connect(rightBrushDriveCheckBox, SIGNAL(stateChanged(int)),
434 this, SLOT(setRightBrushDriveCB(int)));
435 connect(bagrDriveCheckBox, SIGNAL(stateChanged(int)),
436 this, SLOT(setBagrDriveCB(int)));
438 for (int i=0; i<8; i++)
439 connect(doCheckBox[0], SIGNAL(stateChanged(int)),
440 this, SLOT(setDO(int)));
443 connect(laserEngineCheckBox, SIGNAL(stateChanged(int)),
444 this, SLOT(setLaser(int)));
446 /* path planning map */
447 connect(showMapPushButton, SIGNAL(clicked()),
448 this, SLOT(showMap()));
450 /* obstacle simulation */
451 simulationEnabled = 0;
452 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
453 this, SLOT(setSimulation(int)));
454 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
455 this, SLOT(setObstacleSimulation(int)));
456 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
457 playgroundScene, SLOT(showObstacle(int)));
458 connect(playgroundScene, SIGNAL(obstacleChanged(QPointF)),
459 this, SLOT(changeObstacle(QPointF)));
462 void RobomonAtlantis::setVoltage33(int state)
465 orte.pwr_ctrl.voltage33 = true;
467 orte.pwr_ctrl.voltage33 = false;
470 void RobomonAtlantis::setVoltage50(int state)
473 orte.pwr_ctrl.voltage50 = true;
475 orte.pwr_ctrl.voltage50 = false;
478 void RobomonAtlantis::setVoltage80(int state)
481 orte.pwr_ctrl.voltage80 = true;
483 orte.pwr_ctrl.voltage80 = false;
486 void RobomonAtlantis::setLeftMotor(int value)
489 short int rightMotor;
491 if(bothMotorsCheckBox->isChecked())
492 rightMotorSlider->setValue(value);
494 leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
495 rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
497 orte.motion_speed.left = leftMotor;
498 orte.motion_speed.right = rightMotor;
502 void RobomonAtlantis::setRightMotor(int value)
505 short int rightMotor;
507 if(bothMotorsCheckBox->isChecked())
508 leftMotorSlider->setValue(value);
510 leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
511 rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
513 orte.motion_speed.left = leftMotor;
514 orte.motion_speed.right = rightMotor;
518 void RobomonAtlantis::stopMotors()
520 leftMotorSlider->setValue(0);
521 rightMotorSlider->setValue(0);
524 void RobomonAtlantis::moveServos(int value)
526 /* FIXME: servos action comes here */
529 void RobomonAtlantis::moveLeftBrush(int state)
532 orte.servos.brush_left = BRUSH_LEFT_OPEN;
534 orte.servos.brush_left = BRUSH_LEFT_CLOSE;
537 void RobomonAtlantis::moveRightBrush(int state)
540 orte.servos.brush_right = BRUSH_RIGHT_OPEN;
542 orte.servos.brush_right = BRUSH_RIGHT_CLOSE;
545 void RobomonAtlantis::setDrives(int state)
547 orte.drives.brush_left = leftBrushDial->value();
548 orte.drives.brush_right = rightBrushDial->value();
549 orte.drives.bagr = bagrDial->value();
550 orte.drives.carousel_pos = carouselDial->value();
553 void RobomonAtlantis::setLeftBrushDriveCB(int state) {
556 orte.drives.brush_left = LEFT_BRUSH_DRIVE_ON;
558 orte.drives.brush_left = LEFT_BRUSH_DRIVE_OFF;
562 void RobomonAtlantis::setRightBrushDriveCB(int state) {
565 orte.drives.brush_right = RIGHT_BRUSH_DRIVE_ON;
567 orte.drives.brush_right = RIGHT_BRUSH_DRIVE_OFF;
571 void RobomonAtlantis::setBagrDriveCB(int state) {
574 orte.drives.bagr = BAGR_DRIVE_ON;
576 orte.drives.bagr = BAGR_DRIVE_OFF;
579 void RobomonAtlantis::setDO(int state)
581 /* FIXME: digital output control comes here */
584 void RobomonAtlantis::setLaser(int state) {
587 orte.laser_cmd.speed = LASER_DRIVE_ON;
589 orte.laser_cmd.speed = LASER_DRIVE_OFF;
590 ORTEPublicationSend(orte.publication_laser_cmd);
593 void RobomonAtlantis::showMap()
597 if (sharedMemoryOpened == false)
600 mapTimer = new QTimer(this);
601 connect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
602 mapTimer->start(200);
604 showMapPushButton->setText(tr("Show Playground"));
605 showMapPushButton->setShortcut(tr("p"));
606 disconnect(showMapPushButton, SIGNAL(clicked()), this, SLOT(showMap()));
607 connect(showMapPushButton, SIGNAL(clicked()),
608 this, SLOT(showPlayground()));
611 void RobomonAtlantis::showPlayground()
614 disconnect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
618 showMapPushButton->setText(tr("Show &map"));
619 showMapPushButton->setShortcut(tr("m"));
620 disconnect(showMapPushButton, SIGNAL(clicked()),
621 this, SLOT(showPlayground()));
622 connect(showMapPushButton, SIGNAL(clicked()), this, SLOT(showMap()));
625 void RobomonAtlantis::paintMap()
628 static QGraphicsRectItem *rects[MAP_WIDTH][MAP_HEIGHT];
629 static bool firstMap = true;
631 struct map *map = ShmapIsMapInit();
635 for(int i=0; i < MAP_WIDTH; i++) {
636 for(int j=0; j<MAP_HEIGHT; j++) {
637 x = TOP_LEFT_X+i*cellSize;
638 y = TOP_LEFT_Y+j*cellSize;
641 rects[i][j] = playgroundScene->addRect(
642 QRectF(x,y,cellSize,cellSize),
643 QPen(QBrush(Qt::black),
648 QBrush(Qt::lightGray));
649 rects[i][j]->setZValue(4);
654 struct map_cell *cell = &map->cells[j][i];
656 if (cell->flags & MAP_FLAG_WALL)
658 if (cell->flags & MAP_FLAG_IGNORE_OBST)
660 if (cell->flags & MAP_FLAG_SIMULATED_WALL)
662 if (cell->flags & MAP_FLAG_PATH)
664 if (cell->flags & MAP_FLAG_START)
666 if (cell->flags & MAP_FLAG_GOAL)
668 if (cell->detected_obstacle) {
669 QColor c1(color), c2(blue);
670 double f = (double)cell->detected_obstacle/MAP_NEW_OBSTACLE*0.7;
671 QColor c(c1.red() + (int)(f*(c2.red() - c1.red())),
672 c1.green() + (int)(f*(c2.green() - c1.green())),
673 c1.blue() + (int)(f*(c2.blue() - c1.blue())));
676 if (cell->flags & MAP_FLAG_DET_OBST)
679 rects[i][j]->setBrush(QBrush(color));
685 void RobomonAtlantis::setSimulation(int state)
688 robottype_publisher_hokuyo_scan_create(&orte,
689 dummy_publisher_callback, this);
691 if (!simulationEnabled)
693 robottype_publisher_hokuyo_scan_destroy(&orte);
695 simulationEnabled = state;
699 \fn RobomonAtlantis::setObstacleSimulation(int state)
701 void RobomonAtlantis::setObstacleSimulation(int state)
704 /* TODO Maybe it is possible to attach only once to Shmap */
706 obstacleSimulationTimer = new QTimer(this);
707 connect(obstacleSimulationTimer, SIGNAL(timeout()),
708 this, SLOT(simulateObstaclesHokuyo()));
709 obstacleSimulationTimer->start(100);
710 setMouseTracking(true);
712 if (obstacleSimulationTimer)
713 delete obstacleSimulationTimer;
714 double distance = 0.8;
719 void RobomonAtlantis::simulateObstaclesHokuyo()
721 double distance, wall_distance;
723 uint16_t *hokuyo[34] = { // FIXME should be HOKUYO_CLUSTER_CNT
724 &orte.hokuyo_scan.data1,
725 &orte.hokuyo_scan.data2,
726 &orte.hokuyo_scan.data3,
727 &orte.hokuyo_scan.data4,
728 &orte.hokuyo_scan.data5,
729 &orte.hokuyo_scan.data6,
730 &orte.hokuyo_scan.data7,
731 &orte.hokuyo_scan.data8,
732 &orte.hokuyo_scan.data9,
733 &orte.hokuyo_scan.data10,
734 &orte.hokuyo_scan.data11,
735 &orte.hokuyo_scan.data12,
736 &orte.hokuyo_scan.data13,
737 &orte.hokuyo_scan.data14,
738 &orte.hokuyo_scan.data15,
739 &orte.hokuyo_scan.data16,
740 &orte.hokuyo_scan.data17,
741 &orte.hokuyo_scan.data18,
742 &orte.hokuyo_scan.data19,
743 &orte.hokuyo_scan.data20,
744 &orte.hokuyo_scan.data21,
745 &orte.hokuyo_scan.data22,
746 &orte.hokuyo_scan.data23,
747 &orte.hokuyo_scan.data24,
748 &orte.hokuyo_scan.data25,
749 &orte.hokuyo_scan.data26,
750 &orte.hokuyo_scan.data27,
751 &orte.hokuyo_scan.data28,
752 &orte.hokuyo_scan.data29,
753 &orte.hokuyo_scan.data30,
754 &orte.hokuyo_scan.data31,
755 &orte.hokuyo_scan.data32,
756 &orte.hokuyo_scan.data33,
757 &orte.hokuyo_scan.data34,
761 for (i=0; i<HOKUYO_CLUSTER_CNT; i++) {
762 wall_distance = distanceToWallHokuyo(i);
763 distance = distanceToObstacleHokuyo(i, simulatedObstacle, SIM_OBST_SIZE_M/*meters*/);
764 if (wall_distance < distance)
765 distance = wall_distance;
766 *hokuyo[i] = (uint16_t)(distance*1000);
768 ORTEPublicationSend(orte.publication_hokuyo_scan);
772 void RobomonAtlantis::changeObstacle(QPointF position)
774 if (!simulationEnabled) {
775 simulationEnabled = 1;
776 obstacleSimulationCheckBox->setChecked(true);
779 simulatedObstacle.x = position.x();
780 simulatedObstacle.y = position.y();
781 simulateObstaclesHokuyo();
784 /**********************************************************************
786 **********************************************************************/
787 bool RobomonAtlantis::event(QEvent *event)
789 switch (event->type()) {
790 case QEVENT(QEV_MOTION_STATUS):
791 emit motionStatusReceivedSignal();
793 case QEVENT(QEV_ACTUAL_POSITION):
794 emit actualPositionReceivedSignal();
796 case QEVENT(QEV_ESTIMATED_POSITION):
797 emit estimatedPositionReceivedSignal();
800 emit diReceivedSignal();
802 case QEVENT(QEV_ACCELEROMETER):
803 emit accelerometerReceivedSignal();
805 case QEVENT(QEV_ACCUMULATOR):
806 emit accumulatorReceivedSignal();
808 case QEVENT(QEV_POWER_VOLTAGE):
809 emit powerVoltageReceivedSignal();
812 if (event->type() == QEvent::Close)
813 closeEvent((QCloseEvent *)event);
814 else if (event->type() == QEvent::KeyPress)
815 keyPressEvent((QKeyEvent *)event);
816 else if (event->type() == QEvent::KeyRelease)
817 keyReleaseEvent((QKeyEvent *)event);
818 else if (event->type() == QEvent::FocusIn)
820 else if (event->type() == QEvent::FocusOut)
832 void RobomonAtlantis::keyPressEvent(QKeyEvent *event)
836 if (event->isAutoRepeat()) {
837 switch (event->key()) {
839 peak = leftMotorSlider->minimum()/2;
840 if (leftMotorValue < peak ||
841 rightMotorValue < peak)
845 leftMotorValue *= gain;
846 rightMotorValue *= gain;
847 leftMotorSlider->setValue((int)leftMotorValue);
848 rightMotorSlider->setValue((int)rightMotorValue);
854 peak = leftMotorSlider->maximum()/2;
855 if (leftMotorValue > peak ||
856 rightMotorValue > peak)
860 leftMotorValue *= gain;
861 rightMotorValue *= gain;
862 leftMotorSlider->setValue((int)leftMotorValue);
863 rightMotorSlider->setValue((int)rightMotorValue);
873 switch (event->key()) {
877 bothMotorsCheckBox->setChecked(true);
878 leftMotorSlider->setValue((int)leftMotorValue);
879 setLeftMotor((int)leftMotorValue);
883 rightMotorValue = -1;
884 bothMotorsCheckBox->setChecked(true);
885 leftMotorSlider->setValue((int)leftMotorValue);
886 setLeftMotor((int)leftMotorValue);
891 leftMotorSlider->setValue((int)leftMotorValue);
892 rightMotorSlider->setValue((int)rightMotorValue);
893 setLeftMotor((int)leftMotorValue);
894 setRightMotor((int)leftMotorValue);
898 rightMotorValue = -1;
899 leftMotorSlider->setValue((int)leftMotorValue);
900 rightMotorSlider->setValue((int)rightMotorValue);
901 setLeftMotor((int)leftMotorValue);
902 setRightMotor((int)rightMotorValue);
911 void RobomonAtlantis::keyReleaseEvent(QKeyEvent *event)
913 if (event->isAutoRepeat()) {
918 switch (event->key()) {
925 bothMotorsCheckBox->setChecked(false);
926 leftMotorSlider->setValue((int)leftMotorValue);
927 rightMotorSlider->setValue((int)rightMotorValue);
936 void RobomonAtlantis::closeEvent(QCloseEvent *event)
938 robottype_roboorte_destroy(&orte);
941 /**********************************************************************
943 **********************************************************************/
944 void RobomonAtlantis::createOrte()
950 rv = robottype_roboorte_init(&orte);
952 printf("RobomonAtlantis: Unable to initialize ORTE\n");
956 robottype_publisher_motion_speed_create(&orte, dummy_publisher_callback, NULL);
958 robottype_publisher_pwr_ctrl_create(&orte, dummy_publisher_callback, NULL);
960 robottype_publisher_servos_create(&orte, dummy_publisher_callback, NULL);
961 robottype_publisher_drives_create(&orte, dummy_publisher_callback, NULL);
962 robottype_publisher_laser_cmd_create(&orte, NULL, NULL);
965 robottype_subscriber_pwr_voltage_create(&orte,
966 receivePowerVoltageCallBack, this);
967 robottype_subscriber_motion_status_create(&orte,
968 receiveMotionStatusCallBack, this);
969 robottype_subscriber_ref_pos_create(&orte,
970 receiveActualPositionCallBack, this);
971 robottype_subscriber_est_pos_create(&orte,
972 receiveEstimatedPositionCallBack, this);
974 /*createDISubscriber(this, &orteData);*/
975 /*createAccelerometerSubscriber(this, &orteData);*/
976 /*createAccumulatorSubscriber(this, &orteData);*/
978 orte.motion_speed.left = 0;
979 orte.motion_speed.right = 0;
980 /* power management */
981 orte.pwr_ctrl.voltage33 = true;
982 orte.pwr_ctrl.voltage50 = true;
983 orte.pwr_ctrl.voltage80 = true;
984 voltage33CheckBox->setChecked(true);
985 voltage50CheckBox->setChecked(true);
986 voltage80CheckBox->setChecked(true);
989 leftBrushCheckBox->setChecked(false);
990 rightBrushCheckBox->setChecked(false);
995 /* set actions to do when we receive data from orte */
996 connect(this, SIGNAL(motionStatusReceivedSignal()),
997 this, SLOT(motionStatusReceived()));
998 connect(this, SIGNAL(actualPositionReceivedSignal()),
999 this, SLOT(actualPositionReceived()));
1000 connect(this, SIGNAL(estimatedPositionReceivedSignal()),
1001 this, SLOT(estimatedPositionReceived()));
1002 connect(this, SIGNAL(diReceivedSignal()),
1003 this, SLOT(diReceived()));
1004 connect(this, SIGNAL(accelerometerReceivedSignal()),
1005 this, SLOT(accelerometerReceived()));
1006 connect(this, SIGNAL(accumulatorReceivedSignal()),
1007 this, SLOT(accumulatorReceived()));
1008 connect(this, SIGNAL(powerVoltageReceivedSignal()),
1009 this, SLOT(powerVoltageReceived()));
1012 void RobomonAtlantis::motionStatusReceived()
1014 WDBG("ORTE received: motion status");
1017 void RobomonAtlantis::actualPositionReceived()
1019 actPosX->setText(QString("%1").arg(orte.ref_pos.x, 0, 'f', 3));
1020 actPosY->setText(QString("%1").arg(orte.ref_pos.y, 0, 'f', 3));
1021 actPosPhi->setText(QString("%1(%2)")
1022 .arg(DEGREES(orte.ref_pos.phi), 0, 'f', 0)
1023 .arg(orte.ref_pos.phi, 0, 'f', 1));
1024 robotActPos->moveRobot(orte.ref_pos.x,
1025 orte.ref_pos.y, orte.ref_pos.phi);
1028 void RobomonAtlantis::estimatedPositionReceived()
1030 estPosX->setText(QString("%1").arg(orte.est_pos.x, 0, 'f', 3));
1031 estPosY->setText(QString("%1").arg(orte.est_pos.y, 0, 'f', 3));
1032 estPosPhi->setText(QString("%1(%2)")
1033 .arg(DEGREES(orte.est_pos.phi), 0, 'f', 0)
1034 .arg(orte.est_pos.phi, 0, 'f', 1));
1035 robotEstPos->moveRobot(orte.est_pos.x,
1036 orte.est_pos.y, orte.est_pos.phi);
1039 void RobomonAtlantis::diReceived()
1041 WDBG("ORTE received: DI");
1044 void RobomonAtlantis::accelerometerReceived()
1046 WDBG("ORTE received: accelerometer");
1049 void RobomonAtlantis::accumulatorReceived()
1051 WDBG("ORTE received: accumulator");
1054 void RobomonAtlantis::powerVoltageReceived()
1056 voltage33LineEdit->setText(QString("%1").arg(
1057 orte.pwr_voltage.voltage33, 0, 'f', 3));
1058 voltage50LineEdit->setText(QString("%1").arg(
1059 orte.pwr_voltage.voltage50, 0, 'f', 3));
1060 voltage80LineEdit->setText(QString("%1").arg(
1061 orte.pwr_voltage.voltage80, 0, 'f', 3));
1062 voltageBATLineEdit->setText(QString("%1").arg(
1063 orte.pwr_voltage.voltageBAT, 0, 'f', 3));
1067 /**********************************************************************
1069 **********************************************************************/
1070 void RobomonAtlantis::openSharedMemory()
1073 int sharedSegmentSize;
1075 if (sharedMemoryOpened)
1078 cellSize = PG_X / MAP_WIDTH;
1080 sharedSegmentSize = sizeof(char) * MAP_WIDTH * MAP_HEIGHT;
1082 /* Get segment identificator in a read only mode */
1083 segmentId = shmget(SHM_MAP_KEY, sharedSegmentSize, S_IRUSR);
1084 if(segmentId == -1) {
1085 QMessageBox::critical(this, "robomon",
1086 "Unable to open shared memory segment!");
1093 /* Attach the shared memory segment */
1094 //map = (_Map*)shmat (segmentId, (void*) 0, 0);
1096 sharedMemoryOpened = true;
1099 double RobomonAtlantis::distanceToWallHokuyo(int beamnum)
1101 double distance=4.0, min_distance=4.0;
1104 struct map *map = ShmapIsMapInit();
1106 if (!map) return min_distance;
1108 // Simulate obstacles
1109 for(j=0;j<MAP_HEIGHT;j++) {
1110 for (i=0;i<MAP_WIDTH;i++) {
1111 struct map_cell *cell = &map->cells[j][i];
1112 if( cell->flags & MAP_FLAG_SIMULATED_WALL) {
1114 ShmapCell2Point(i, j, &wall.x, &wall.y);
1116 distance = distanceToObstacleHokuyo(beamnum, wall, MAP_CELL_SIZE_M);
1117 if (distance<min_distance) min_distance = distance;
1122 return min_distance;
1126 * Calculation for Hokuyo simulation. Calculates distance that would
1127 * be returned by Hokuyo sensors, if there is only one obstacle (as
1128 * specified by parameters).
1130 * @param beamnum Hokuyo's bean number [0..HOKUYO_CLUSTER_CNT]
1131 * @param obstacle Position of the obstacle (x, y in meters).
1132 * @param obstacleSize Size (diameter) of the obstacle in meters.
1134 * @return Distance measured by sensors in meters.
1136 double RobomonAtlantis::distanceToObstacleHokuyo(int beamnum, Point obstacle, double obstacleSize)
1138 struct est_pos_type e = orte.est_pos;
1142 s.x = HOKUYO_CENTER_OFFSET_M;
1144 s.ang = HOKUYO_CLUSTER_TO_RAD(beamnum);
1146 Point sensor(e.x + s.x*cos(e.phi) - s.y*sin(e.phi),
1147 e.y + s.x*sin(e.phi) + s.y*cos(e.phi));
1148 sensor_a = e.phi + s.ang;
1150 const double sensorRange = 4.0; /*[meters]*/
1152 double distance, angle;
1154 angle = sensor.angleTo(obstacle) - sensor_a;
1155 angle = fmod(angle, 2.0*M_PI);
1156 if (angle > +M_PI) angle -= 2.0*M_PI;
1157 if (angle < -M_PI) angle += 2.0*M_PI;
1158 angle = fabs(angle);
1159 distance = sensor.distanceTo(obstacle)-0.11;
1160 if (angle < atan(obstacleSize/2.0 / (distance+0.001))) {
1161 // We can see the obstackle from here.
1162 if (angle < M_PI/2.0) {
1163 distance = distance/cos(angle);
1165 if (distance > sensorRange)
1166 distance = sensorRange;
1168 distance = sensorRange;