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>
27 #include <path_planner.h>
33 #include <lidar_params.h>
34 #include <actuators.h>
35 #include "PlaygroundScene.h"
37 #include "robomon_orte.h"
38 #include "RobomonAtlantis.h"
39 #include "playgroundview.h"
42 #include <QCoreApplication>
46 #include <QMessageBox>
48 RobomonAtlantis::RobomonAtlantis(QStatusBar *_statusBar)
49 : QWidget(0), statusBar(_statusBar)
55 debugWindowEnabled = false;
60 QHBoxLayout *mainLayout = new QHBoxLayout;
61 mainLayout->addLayout(leftLayout);
62 mainLayout->addLayout(rightLayout);
63 setLayout(mainLayout);
70 // connect(vidle, SIGNAL(valueChanged(int)),
71 // robotEstPosBest, SLOT(setVidle(int)));
73 setFocusPolicy(Qt::StrongFocus);
74 sharedMemoryOpened = false;
75 WDBG("Youuuhouuuu!!");
78 /**********************************************************************
80 **********************************************************************/
81 void RobomonAtlantis::createLeftLayout()
83 leftLayout = new QVBoxLayout();
85 createDebugGroupBox();
86 debugWindowEnabled = true;
87 createPlaygroundGroupBox();
88 leftLayout->addWidget(playgroundGroupBox);
89 //leftLayout->addWidget(debugGroupBox); // FIXME: move this to separate tab
92 void RobomonAtlantis::createRightLayout()
94 rightLayout = new QVBoxLayout();
96 createPositionGroupBox();
97 createObstSimGroupBox();
100 createActuatorsGroupBox();
101 createPowerGroupBox();
103 rightLayout->addWidget(positionGroupBox);
104 rightLayout->addWidget(obstSimGroupBox);
105 rightLayout->addWidget(miscGroupBox);
106 rightLayout->addWidget(fsmGroupBox);
107 //rightLayout->addWidget(powerGroupBox);
108 rightLayout->addWidget(actuatorsGroupBox);
111 void RobomonAtlantis::createPlaygroundGroupBox()
113 playgroundGroupBox = new QGroupBox(tr("Playground"));
114 QHBoxLayout *layout = new QHBoxLayout();
116 playgroundScene = new PlaygroundScene();
117 playgroundSceneView = new PlaygroundView(playgroundScene);
118 //playgroundSceneView->setMinimumWidth(630);
119 //playgroundSceneView->setMinimumHeight(445);
120 playgroundSceneView->setMatrix(QMatrix(1,0,0,-1,0,0), true);
121 playgroundSceneView->fitInView(playgroundScene->itemsBoundingRect());
122 playgroundSceneView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
123 playgroundSceneView->setMouseTracking(true);
124 layout->addWidget(playgroundSceneView);
126 playgroundGroupBox->setLayout(layout);
129 void RobomonAtlantis::createPositionGroupBox()
131 positionGroupBox = new QGroupBox(tr("Position state"));
132 positionGroupBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
133 QGridLayout *layout = new QGridLayout();
135 actPosX = new QLineEdit();
136 actPosY = new QLineEdit();
137 actPosPhi = new QLineEdit();
139 estPosX = new QLineEdit();
140 estPosY = new QLineEdit();
141 estPosPhi = new QLineEdit();
143 actPosX->setReadOnly(true);
144 actPosY->setReadOnly(true);
145 actPosPhi->setReadOnly(true);
147 estPosX->setReadOnly(true);
148 estPosY->setReadOnly(true);
149 estPosPhi->setReadOnly(true);
151 layout->addWidget(MiscGui::createLabel("X"), 1, 0);
152 layout->addWidget(MiscGui::createLabel("Y"), 2, 0);
153 layout->addWidget(MiscGui::createLabel("Phi"), 3, 0);
155 layout->addWidget(MiscGui::createLabel("X"), 5, 0);
156 layout->addWidget(MiscGui::createLabel("Y"), 6, 0);
157 layout->addWidget(MiscGui::createLabel("Phi"), 7, 0);
159 layout->addWidget(MiscGui::createLabel("Reference", Qt::AlignLeft), 0, 1);
160 layout->addWidget(actPosX, 1, 1);
161 layout->addWidget(actPosY, 2, 1);
162 layout->addWidget(actPosPhi, 3, 1);
164 layout->addWidget(MiscGui::createLabel("Estimated (indep. odo.)", Qt::AlignLeft), 4, 1);
165 layout->addWidget(estPosX, 5, 1);
166 layout->addWidget(estPosY, 6, 1);
167 layout->addWidget(estPosPhi, 7, 1);
169 positionGroupBox->setLayout(layout);
172 void RobomonAtlantis::createMiscGroupBox()
174 miscGroupBox = new QGroupBox(tr("Miscellaneous"));
175 miscGroupBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
176 QGridLayout *layout = new QGridLayout();
178 startPlug = new QCheckBox("&Start plug");
179 layout->addWidget(startPlug);
181 colorChoser = new QCheckBox("&Team color");
182 layout->addWidget(colorChoser);
184 strategyButton= new QPushButton(tr("Strategy"));
185 layout->addWidget(strategyButton);
187 miscGroupBox->setLayout(layout);
190 void RobomonAtlantis::createObstSimGroupBox()
192 obstSimGroupBox = new QGroupBox(tr("Obstacle simulation"));
193 obstSimGroupBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
194 QGridLayout *layout = new QGridLayout();
196 hokuyoSimCheckBox = new QCheckBox(tr("&Hokuyo lidar simulation"));
197 hokuyoSimCheckBox->setShortcut(tr("h"));
198 layout->addWidget(hokuyoSimCheckBox);
200 sick331SimCheckBox = new QCheckBox(tr("Sick Tim &331 lidar simulation"));
201 sick331SimCheckBox->setShortcut(tr("3"));
202 layout->addWidget(sick331SimCheckBox);
204 sick551SimCheckBox = new QCheckBox(tr("Sick Tim &551 lidar simulation"));
205 sick551SimCheckBox->setShortcut(tr("5"));
206 layout->addWidget(sick551SimCheckBox);
208 obstSimGroupBox->setLayout(layout);
211 void RobomonAtlantis::createFSMGroupBox()
213 fsmGroupBox = new QGroupBox(tr("FSM"));
214 fsmGroupBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
215 QGridLayout *layout = new QGridLayout();
217 layout->addWidget(MiscGui::createLabel("Main:"), 1, 0);
218 fsm_main_state = new QLabel();
219 fsm_main_state->setMinimumWidth(100);
220 fsm_main_state->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
221 layout->addWidget(fsm_main_state, 1, 1);
223 layout->addWidget(MiscGui::createLabel("Act:"), 2, 0);
224 fsm_act_state = new QLabel();
225 layout->addWidget(fsm_act_state, 2, 1);
227 layout->addWidget(MiscGui::createLabel("Motion:"), 3, 0);
228 fsm_motion_state = new QLabel();
229 layout->addWidget(fsm_motion_state, 3, 1);
231 fsmGroupBox->setLayout(layout);
234 void RobomonAtlantis::createDebugGroupBox()
236 debugGroupBox = new QGroupBox(tr("Debug window"));
237 debugGroupBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
238 QHBoxLayout *layout = new QHBoxLayout();
240 debugWindow = new QTextEdit();
241 debugWindow->setReadOnly(true);
243 layout->addWidget(debugWindow);
244 debugGroupBox->setLayout(layout);
247 void RobomonAtlantis::createActuatorsGroupBox()
249 actuatorsGroupBox = new QGroupBox(tr("Actuators"));
250 actuatorsGroupBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
251 QHBoxLayout *layout = new QHBoxLayout();
252 // vidle = new QDial();
254 // vidle->setMinimum(VIDLE_VYSIP);
255 // vidle->setMaximum((VIDLE_UP-VIDLE_VYSIP)+VIDLE_VYSIP);
256 // vidle->setEnabled(true);
258 //createMotorsGroupBox();
260 layout->setAlignment(Qt::AlignLeft);
261 // layout->addWidget(vidle);
262 //layout->addWidget(enginesGroupBox);
263 actuatorsGroupBox->setLayout(layout);
266 void RobomonAtlantis::createPowerGroupBox()
268 powerGroupBox = new QGroupBox(tr("Power management"));
269 powerGroupBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
270 QGridLayout *layout = new QGridLayout();
272 voltage33CheckBox = new QCheckBox(tr("&3.3V"));
273 voltage50CheckBox = new QCheckBox(tr("&5.0V"));
274 voltage80CheckBox = new QCheckBox(tr("&8.0V"));
276 voltage33CheckBox->setShortcut(tr("3"));
277 voltage50CheckBox->setShortcut(tr("5"));
278 voltage80CheckBox->setShortcut(tr("8"));
280 layout->addWidget(voltage33CheckBox, 0, 0);
281 layout->addWidget(voltage50CheckBox, 1, 0);
282 layout->addWidget(voltage80CheckBox, 2, 0);
283 layout->addWidget(MiscGui::createLabel("BAT"), 3, 0);
285 voltage33LineEdit = new QLineEdit();
286 voltage50LineEdit = new QLineEdit();
287 voltage80LineEdit = new QLineEdit();
288 voltageBATLineEdit = new QLineEdit();
290 voltage33LineEdit->setReadOnly(true);
291 voltage50LineEdit->setReadOnly(true);
292 voltage80LineEdit->setReadOnly(true);
293 voltageBATLineEdit->setReadOnly(true);
295 layout->addWidget(voltage33LineEdit, 0, 1);
296 layout->addWidget(voltage50LineEdit, 1, 1);
297 layout->addWidget(voltage80LineEdit, 2, 1);
298 layout->addWidget(voltageBATLineEdit, 3, 1);
300 powerGroupBox->setLayout(layout);
303 void RobomonAtlantis::createRobots()
305 robotRefPos = new Robot("Ref", QPen(Qt::darkBlue), QBrush(Qt::NoBrush));
306 robotRefPos->setZValue(11);
307 trailRefPos = new Trail(QPen(Qt::darkBlue));
308 trailRefPos->setZValue(11);
310 robotEstPosBest = new Robot("Est", QPen(), QBrush(Qt::darkGray));
311 robotEstPosBest->setZValue(10);
312 trailEstPosBest = new Trail(QPen());
313 trailEstPosBest->setZValue(10);
315 robotEstPosOdo = new Robot("Mot", QPen(Qt::white), QBrush(Qt::darkRed));
316 robotEstPosOdo->setZValue(10);
317 trailOdoPos = new Trail(QPen(Qt::red));
318 trailOdoPos->setZValue(10);
320 robotEstPosIndepOdo = new Robot("Odo", QPen(Qt::white), QBrush(Qt::darkGreen));
321 robotEstPosIndepOdo->setZValue(10);
322 trailPosIndepOdo = new Trail(QPen(Qt::green));
323 trailPosIndepOdo->setZValue(10);
325 playgroundScene->addItem(robotRefPos);
326 playgroundScene->addItem(robotEstPosBest);
327 playgroundScene->addItem(robotEstPosIndepOdo);
328 playgroundScene->addItem(robotEstPosOdo);
332 playgroundScene->addItem(trailRefPos);
333 playgroundScene->addItem(trailPosIndepOdo);
334 playgroundScene->addItem(trailOdoPos);
336 hokuyoScan = new LidarScan(hokuyo_params);
337 hokuyoScan->setZValue(10);
338 playgroundScene->addItem(hokuyoScan);
340 sickScan = new LidarScan(sick_params);
341 sickScan->setZValue(10);
342 playgroundScene->addItem(sickScan);
344 sick551Scan = new LidarScan(sick551_params);
345 sick551Scan->setZValue(10);
346 playgroundScene->addItem(sick551Scan);
349 void RobomonAtlantis::createMap()
351 mapImage = new Map();
352 mapImage->setZValue(5);
353 mapImage->setTransform(QTransform().scale(MAP_CELL_SIZE_MM, MAP_CELL_SIZE_MM), true);
355 playgroundScene->addItem(mapImage);
358 /**********************************************************************
360 **********************************************************************/
361 void RobomonAtlantis::createActions()
363 /* power management */
364 connect(voltage33CheckBox, SIGNAL(stateChanged(int)),
365 this, SLOT(setVoltage33(int)));
366 connect(voltage50CheckBox, SIGNAL(stateChanged(int)),
367 this, SLOT(setVoltage50(int)));
368 connect(voltage80CheckBox, SIGNAL(stateChanged(int)),
369 this, SLOT(setVoltage80(int)));
372 // connect(leftMotorSlider, SIGNAL(valueChanged(int)),
373 // this, SLOT(setLeftMotor(int)));
374 // connect(rightMotorSlider, SIGNAL(valueChanged(int)),
375 // this, SLOT(setRightMotor(int)));
376 // connect(stopMotorsPushButton, SIGNAL(clicked()),
377 // this, SLOT(stopMotors()));
379 connect(startPlug, SIGNAL(stateChanged(int)), this, SLOT(sendStart(int)));
380 connect(colorChoser, SIGNAL(stateChanged(int)), this, SLOT(setTeamColor(int)));
381 connect(strategyButton, SIGNAL(pressed()), this, SLOT(changeStrategy_1()));
382 connect(strategyButton, SIGNAL(released()), this, SLOT(changeStrategy_0()));
384 /* obstacle simulation */
385 hokuyoSimEnabled = 0;
387 sick551SimEnabled = 0;
389 connect(hokuyoSimCheckBox, SIGNAL(stateChanged(int)),
390 this, SLOT(setHokuyoSimulation(int)));
391 connect(hokuyoSimCheckBox, SIGNAL(stateChanged(int)),
392 this, SLOT(setHokuyoObstacleSimulation(int)));
394 connect(sick331SimCheckBox, SIGNAL(stateChanged(int)),
395 this, SLOT(setSick331Simulation(int)));
396 connect(sick331SimCheckBox, SIGNAL(stateChanged(int)),
397 this, SLOT(setSick331ObstacleSimulation(int)));
399 connect(sick551SimCheckBox, SIGNAL(stateChanged(int)),
400 this, SLOT(setSick551Simulation(int)));
401 connect(sick551SimCheckBox, SIGNAL(stateChanged(int)),
402 this, SLOT(setSick551ObstacleSimulation(int)));
404 connect(playgroundScene, SIGNAL(obstacleChanged(QPointF)),
405 this, SLOT(changeObstacle(QPointF)));
408 void RobomonAtlantis::changeStrategy_1()
410 orte.robot_switches.strategy = true;
411 ORTEPublicationSend(orte.publication_robot_switches);
414 void RobomonAtlantis::changeStrategy_0()
416 orte.robot_switches.strategy = false;
417 ORTEPublicationSend(orte.publication_robot_switches);
420 void RobomonAtlantis::setVoltage33(int state)
423 orte.pwr_ctrl.voltage33 = true;
425 orte.pwr_ctrl.voltage33 = false;
428 void RobomonAtlantis::setVoltage50(int state)
431 orte.pwr_ctrl.voltage50 = true;
433 orte.pwr_ctrl.voltage50 = false;
436 void RobomonAtlantis::setVoltage80(int state)
439 orte.pwr_ctrl.voltage80 = true;
441 orte.pwr_ctrl.voltage80 = false;
444 // void RobomonAtlantis::setLeftMotor(int value)
446 // short int leftMotor;
447 // short int rightMotor;
449 // if(bothMotorsCheckBox->isChecked())
450 // rightMotorSlider->setValue(value);
452 // leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
453 // rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
455 // orte.motion_speed.left = leftMotor;
456 // orte.motion_speed.right = rightMotor;
460 // void RobomonAtlantis::setRightMotor(int value)
462 // short int leftMotor;
463 // short int rightMotor;
465 // if(bothMotorsCheckBox->isChecked())
466 // leftMotorSlider->setValue(value);
468 // leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
469 // rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
471 // orte.motion_speed.left = leftMotor;
472 // orte.motion_speed.right = rightMotor;
476 // void RobomonAtlantis::stopMotors()
478 // leftMotorSlider->setValue(0);
479 // rightMotorSlider->setValue(0);
482 void RobomonAtlantis::useOpenGL(bool use)
484 playgroundSceneView->useOpenGL(&use);
487 void RobomonAtlantis::showMap(bool show)
491 if (sharedMemoryOpened == false)
495 mapTimer = new QTimer(this);
496 connect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
497 mapTimer->start(200);
499 if(mapTimer != NULL) {
501 disconnect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
504 mapImage->setVisible(show);
507 void RobomonAtlantis::paintMap()
510 struct map *map = ShmapIsMapInit();
514 for(int i = 0; i < MAP_WIDTH; i++) {
515 for(int j = 0; j < MAP_HEIGHT; j++) {
518 struct map_cell *cell = &map->cells[j][i];
521 if (cell->flags & MAP_FLAG_WALL)
523 if (cell->flags & MAP_FLAG_IGNORE_OBST)
525 if (cell->flags & MAP_FLAG_SIMULATED_WALL)
527 if (cell->flags & MAP_FLAG_PATH)
529 if (cell->flags & MAP_FLAG_START)
531 if (cell->flags & MAP_FLAG_GOAL)
533 if (cell->flags & MAP_FLAG_PLAN_MARGIN) {
534 QColor c(240, 170, 50); /* orange */
537 if (cell->detected_obstacle) {
538 QColor c1(color), c2(blue);
539 double f = (double)cell->detected_obstacle/MAP_NEW_OBSTACLE*0.7;
540 QColor c(c1.red() + (int)(f*(c2.red() - c1.red())),
541 c1.green() + (int)(f*(c2.green() - c1.green())),
542 c1.blue() + (int)(f*(c2.blue() - c1.blue())));
545 if (cell->flags & MAP_FLAG_DET_OBST)
549 mapImage->setPixelColor(i, MAP_HEIGHT - j - 1, color);
554 // void RobomonAtlantis::setSimulation(int state)
557 // robottype_publisher_sick_scan_create(&orte, NULL, this);
558 // robottype_publisher_hokuyo_scan_create(&orte, NULL, this);
560 // if (!simulationEnabled)
562 // robottype_publisher_sick_scan_destroy(&orte);
563 // robottype_publisher_hokuyo_scan_destroy(&orte);
565 // simulationEnabled = state;
568 void RobomonAtlantis::setHokuyoSimulation(int state)
571 robottype_publisher_hokuyo_scan_create(&orte, NULL, this);
573 if (!hokuyoSimEnabled)
575 robottype_publisher_hokuyo_scan_destroy(&orte);
577 hokuyoSimEnabled = state;
580 void RobomonAtlantis::setSick331Simulation(int state)
583 robottype_publisher_sick_scan_create(&orte, NULL, this);
587 robottype_publisher_sick_scan_destroy(&orte);
589 sickSimEnabled = state;
592 void RobomonAtlantis::setSick551Simulation(int state)
595 robottype_publisher_sick551_scan_create(&orte, NULL, this);
597 if (!sick551SimEnabled)
599 robottype_publisher_sick551_scan_destroy(&orte);
601 sick551SimEnabled = state;
605 \fn RobomonAtlantis::setObstacleSimulation(int state)
607 // void RobomonAtlantis::setObstacleSimulation(int state)
610 // /* TODO Maybe it is possible to attach only once to Shmap */
612 // obstacleSimulationTimer = new QTimer(this);
613 // connect(obstacleSimulationTimer, SIGNAL(timeout()),
614 // this, SLOT(simulateObstaclesHokuyo()));
615 // connect(obstacleSimulationTimer, SIGNAL(timeout()),
616 // this, SLOT(simulateObstaclesSick()));
617 // obstacleSimulationTimer->start(100);
618 // setMouseTracking(true);
619 // hokuyoScan->setVisible(true);
620 // sickScan->setVisible(true);
622 // if (obstacleSimulationTimer)
623 // delete obstacleSimulationTimer;
624 // // Hide scans of lidars
625 // hokuyoScan->setVisible(false);
626 // sickScan->setVisible(false);
630 void RobomonAtlantis::setHokuyoObstacleSimulation(int state)
633 /* TODO Maybe it is possible to attach only once to Shmap */
635 obstacleSimulationTimerHokuyo = new QTimer(this);
636 connect(obstacleSimulationTimerHokuyo, SIGNAL(timeout()),
637 this, SLOT(simulateObstaclesHokuyo()));
638 obstacleSimulationTimerHokuyo->start(100);
639 setMouseTracking(true);
640 hokuyoScan->setVisible(true);
642 if (obstacleSimulationTimerHokuyo)
643 delete obstacleSimulationTimerHokuyo;
644 // Hide scans of lidars
645 hokuyoScan->setVisible(false);
649 void RobomonAtlantis::setSick331ObstacleSimulation(int state)
652 /* TODO Maybe it is possible to attach only once to Shmap */
654 obstacleSimulationTimerSick331 = new QTimer(this);
655 connect(obstacleSimulationTimerSick331, SIGNAL(timeout()),
656 this, SLOT(simulateObstaclesSick()));
657 obstacleSimulationTimerSick331->start(100);
658 setMouseTracking(true);
659 sickScan->setVisible(true);
661 if (obstacleSimulationTimerSick331)
662 delete obstacleSimulationTimerSick331;
663 // Hide scans of lidars
664 sickScan->setVisible(false);
668 void RobomonAtlantis::setSick551ObstacleSimulation(int state)
671 /* TODO Maybe it is possible to attach only once to Shmap */
673 obstacleSimulationTimerSick551 = new QTimer(this);
674 connect(obstacleSimulationTimerSick551, SIGNAL(timeout()),
675 this, SLOT(simulateObstaclesSick551()));
676 obstacleSimulationTimerSick551->start(100);
677 setMouseTracking(true);
678 sick551Scan->setVisible(true);
680 if (obstacleSimulationTimerSick551)
681 delete obstacleSimulationTimerSick551;
682 // Hide scans of lidars
683 sick551Scan->setVisible(false);
687 void RobomonAtlantis::simulateObstaclesLidar(const struct lidar_params lidar)
689 double distance, wall_distance;
691 unsigned int data_lenght = 0;
692 uint16_t *lidar_data = NULL;
693 switch (lidar.type) {
695 lidar_data = orte.hokuyo_scan.data;
696 data_lenght = hokuyo_params.data_lenght;
699 lidar_data = orte.sick_scan.data;
700 data_lenght = sick_params.data_lenght;
703 lidar_data = orte.sick551_scan.data;
704 data_lenght = sick551_params.data_lenght;
710 for (i = 0; i < data_lenght; i++) {
711 wall_distance = distanceToWallLidar(lidar, i);
712 distance = distanceToCircularObstacleLidar(lidar, i, simulatedObstacle, SIM_OBST_SIZE_M);
713 if (wall_distance < distance)
714 distance = wall_distance;
715 lidar_data[i] = distance*1000;
718 switch (lidar.type) {
720 orte.hokuyo_scan.data_lenght = hokuyo_params.data_lenght;
721 orte.hokuyo_scan.lidar_type = hokuyo_params.type;
722 ORTEPublicationSend(orte.publication_hokuyo_scan);
725 orte.sick_scan.data_lenght = sick_params.data_lenght;
726 orte.sick_scan.lidar_type = sick_params.type;
727 ORTEPublicationSend(orte.publication_sick_scan);
730 orte.sick551_scan.data_lenght = sick551_params.data_lenght;
731 orte.sick551_scan.lidar_type = sick551_params.type;
732 ORTEPublicationSend(orte.publication_sick551_scan);
739 void RobomonAtlantis::simulateObstaclesHokuyo()
741 simulateObstaclesLidar(hokuyo_params);
744 void RobomonAtlantis::simulateObstaclesSick()
746 simulateObstaclesLidar(sick_params);
749 void RobomonAtlantis::simulateObstaclesSick551()
751 simulateObstaclesLidar(sick551_params);
754 void RobomonAtlantis::changeObstacle(QPointF position)
756 if (!hokuyoSimEnabled && !sickSimEnabled && !sick551SimEnabled) {
757 hokuyoSimEnabled = 1;
759 sick551SimEnabled = 1;
760 hokuyoSimCheckBox->setChecked(true);
761 sick331SimCheckBox->setChecked(true);
762 sick551SimCheckBox->setChecked(true);
765 simulatedObstacle.x = position.x();
766 simulatedObstacle.y = position.y();
769 /**********************************************************************
771 **********************************************************************/
772 bool RobomonAtlantis::event(QEvent *event)
774 switch (event->type()) {
775 case QEVENT(QEV_MOTION_STATUS):
776 emit motionStatusReceivedSignal();
778 case QEVENT(QEV_SICK_SCAN):
779 sickScan->newScan(&orte.sick_scan);
781 case QEVENT(QEV_SICK551_SCAN):
782 sick551Scan->newScan(&orte.sick551_scan);
784 case QEVENT(QEV_HOKUYO_SCAN):
785 hokuyoScan->newScan(&orte.hokuyo_scan);
787 case QEVENT(QEV_REFERENCE_POSITION):
788 emit actualPositionReceivedSignal();
790 case QEVENT(QEV_ESTIMATED_POSITION_INDEP_ODO):
791 estPosX->setText(QString("%1").arg(orte.est_pos_indep_odo.x, 0, 'f', 3));
792 estPosY->setText(QString("%1").arg(orte.est_pos_indep_odo.y, 0, 'f', 3));
793 estPosPhi->setText(QString("%1(%2)")
794 .arg(DEGREES(orte.est_pos_indep_odo.phi), 0, 'f', 0)
795 .arg(orte.est_pos_indep_odo.phi, 0, 'f', 1));
796 robotEstPosIndepOdo->moveRobot(orte.est_pos_indep_odo.x,
797 orte.est_pos_indep_odo.y, orte.est_pos_indep_odo.phi);
798 trailPosIndepOdo->addPoint(QPointF(orte.est_pos_indep_odo.x,
799 orte.est_pos_indep_odo.y));
801 case QEVENT(QEV_ESTIMATED_POSITION_ODO):
802 robotEstPosOdo->moveRobot(orte.est_pos_odo.x,
803 orte.est_pos_odo.y, orte.est_pos_odo.phi);
804 trailOdoPos->addPoint(QPointF(orte.est_pos_odo.x,
805 orte.est_pos_odo.y));
807 case QEVENT(QEV_ESTIMATED_POSITION_BEST):
808 robotEstPosBest->moveRobot(orte.est_pos_best.x,
809 orte.est_pos_best.y, orte.est_pos_best.phi);
810 trailEstPosBest->addPoint(QPointF(orte.est_pos_best.x,
811 orte.est_pos_best.y));
812 hokuyoScan->setPosition(orte.est_pos_best.x,
814 orte.est_pos_best.phi);
815 sickScan->setPosition(orte.est_pos_best.x,
817 orte.est_pos_best.phi);
818 sick551Scan->setPosition(orte.est_pos_best.x,
820 orte.est_pos_best.phi);
822 case QEVENT(QEV_POWER_VOLTAGE):
823 emit powerVoltageReceivedSignal();
825 case QEVENT(QEV_FSM_MAIN):
826 fsm_main_state->setText(orte.fsm_main.state_name);
828 case QEVENT(QEV_FSM_ACT):
829 fsm_act_state->setText(orte.fsm_act.state_name);
831 case QEVENT(QEV_FSM_MOTION):
832 fsm_motion_state->setText(orte.fsm_motion.state_name);
835 if (event->type() == QEvent::Close)
836 closeEvent((QCloseEvent *)event);
837 else if (event->type() == QEvent::KeyPress)
838 keyPressEvent((QKeyEvent *)event);
839 else if (event->type() == QEvent::KeyRelease)
840 keyReleaseEvent((QKeyEvent *)event);
841 else if (event->type() == QEvent::FocusIn)
843 else if (event->type() == QEvent::FocusOut)
855 void RobomonAtlantis::keyPressEvent(QKeyEvent *event)
857 // double peak, gain;
859 if (event->isAutoRepeat()) {
860 switch (event->key()) {
861 // case Qt::Key_Down:
862 // peak = leftMotorSlider->minimum()/2;
863 // if (leftMotorValue < peak ||
864 // rightMotorValue < peak)
868 // leftMotorValue *= gain;
869 // rightMotorValue *= gain;
870 // leftMotorSlider->setValue((int)leftMotorValue);
871 // rightMotorSlider->setValue((int)rightMotorValue);
875 // case Qt::Key_Left:
876 // case Qt::Key_Right:
877 // peak = leftMotorSlider->maximum()/2;
878 // if (leftMotorValue > peak ||
879 // rightMotorValue > peak)
883 // leftMotorValue *= gain;
884 // rightMotorValue *= gain;
885 // leftMotorSlider->setValue((int)leftMotorValue);
886 // rightMotorSlider->setValue((int)rightMotorValue);
896 switch (event->key()) {
898 // leftMotorValue = 1;
899 // rightMotorValue = 1;
900 // bothMotorsCheckBox->setChecked(true);
901 // leftMotorSlider->setValue((int)leftMotorValue);
902 // setLeftMotor((int)leftMotorValue);
904 // case Qt::Key_Down:
905 // leftMotorValue = -1;
906 // rightMotorValue = -1;
907 // bothMotorsCheckBox->setChecked(true);
908 // leftMotorSlider->setValue((int)leftMotorValue);
909 // setLeftMotor((int)leftMotorValue);
911 // case Qt::Key_Left:
912 // leftMotorValue = -1;
913 // rightMotorValue = 1;
914 // leftMotorSlider->setValue((int)leftMotorValue);
915 // rightMotorSlider->setValue((int)rightMotorValue);
916 // setLeftMotor((int)leftMotorValue);
917 // setRightMotor((int)leftMotorValue);
919 // case Qt::Key_Right:
920 // leftMotorValue = 1;
921 // rightMotorValue = -1;
922 // leftMotorSlider->setValue((int)leftMotorValue);
923 // rightMotorSlider->setValue((int)rightMotorValue);
924 // setLeftMotor((int)leftMotorValue);
925 // setRightMotor((int)rightMotorValue);
934 void RobomonAtlantis::keyReleaseEvent(QKeyEvent *event)
936 if (event->isAutoRepeat()) {
941 switch (event->key()) {
943 // case Qt::Key_Down:
944 // case Qt::Key_Left:
945 // case Qt::Key_Right:
946 // leftMotorValue = 0;
947 // rightMotorValue = 0;
948 // bothMotorsCheckBox->setChecked(false);
949 // leftMotorSlider->setValue((int)leftMotorValue);
950 // rightMotorSlider->setValue((int)rightMotorValue);
959 void RobomonAtlantis::closeEvent(QCloseEvent *)
961 robottype_roboorte_destroy(&orte);
964 /**********************************************************************
966 **********************************************************************/
967 void RobomonAtlantis::createOrte()
971 memset(&orte, 0, sizeof(orte));
972 rv = robottype_roboorte_init(&orte);
974 printf("RobomonAtlantis: Unable to initialize ORTE\n");
978 robottype_publisher_motion_speed_create(&orte, dummy_publisher_callback, NULL);
980 robottype_publisher_pwr_ctrl_create(&orte, dummy_publisher_callback, NULL);
981 robottype_publisher_robot_cmd_create(&orte, NULL, &orte);
982 robottype_publisher_robot_switches_create(&orte, dummy_publisher_callback, &orte);
985 robottype_subscriber_pwr_voltage_create(&orte,
986 receivePowerVoltageCallBack, this);
987 robottype_subscriber_motion_status_create(&orte,
988 receiveMotionStatusCallBack, this);
989 robottype_subscriber_ref_pos_create(&orte,
990 receiveActualPositionCallBack, this);
991 robottype_subscriber_est_pos_odo_create(&orte,
992 generic_rcv_cb, new OrteCallbackInfo(this, QEV_ESTIMATED_POSITION_ODO));
993 robottype_subscriber_est_pos_indep_odo_create(&orte,
994 generic_rcv_cb, new OrteCallbackInfo(this, QEV_ESTIMATED_POSITION_INDEP_ODO));
995 robottype_subscriber_est_pos_best_create(&orte,
996 generic_rcv_cb, new OrteCallbackInfo(this, QEV_ESTIMATED_POSITION_BEST));
997 robottype_subscriber_sick_scan_create(&orte,
998 generic_rcv_cb, new OrteCallbackInfo(this, QEV_SICK_SCAN));
999 robottype_subscriber_sick551_scan_create(&orte,
1000 generic_rcv_cb, new OrteCallbackInfo(this, QEV_SICK551_SCAN));
1001 robottype_subscriber_hokuyo_scan_create(&orte,
1002 generic_rcv_cb, new OrteCallbackInfo(this, QEV_HOKUYO_SCAN));
1003 robottype_subscriber_fsm_main_create(&orte,
1004 rcv_fsm_main_cb, this);
1005 robottype_subscriber_fsm_motion_create(&orte,
1006 rcv_fsm_motion_cb, this);
1007 robottype_subscriber_fsm_act_create(&orte,
1008 rcv_fsm_act_cb, this);
1011 orte.motion_speed.left = 0;
1012 orte.motion_speed.right = 0;
1014 /* power management */
1015 orte.pwr_ctrl.voltage33 = true;
1016 orte.pwr_ctrl.voltage50 = true;
1017 orte.pwr_ctrl.voltage80 = true;
1018 voltage33CheckBox->setChecked(true);
1019 voltage50CheckBox->setChecked(true);
1020 voltage80CheckBox->setChecked(true);
1024 /* set actions to do when we receive data from orte */
1025 connect(this, SIGNAL(motionStatusReceivedSignal()),
1026 this, SLOT(motionStatusReceived()));
1027 connect(this, SIGNAL(actualPositionReceivedSignal()),
1028 this, SLOT(actualPositionReceived()));
1029 connect(this, SIGNAL(powerVoltageReceivedSignal()),
1030 this, SLOT(powerVoltageReceived()));
1033 void RobomonAtlantis::motionStatusReceived()
1035 WDBG("ORTE received: motion status");
1038 void RobomonAtlantis::actualPositionReceived()
1040 actPosX->setText(QString("%1").arg(orte.ref_pos.x, 0, 'f', 3));
1041 actPosY->setText(QString("%1").arg(orte.ref_pos.y, 0, 'f', 3));
1042 actPosPhi->setText(QString("%1(%2)")
1043 .arg(DEGREES(orte.ref_pos.phi), 0, 'f', 0)
1044 .arg(orte.ref_pos.phi, 0, 'f', 1));
1045 robotRefPos->moveRobot(orte.ref_pos.x,
1046 orte.ref_pos.y, orte.ref_pos.phi);
1047 trailRefPos->addPoint(QPointF(orte.ref_pos.x, orte.ref_pos.y));
1050 void RobomonAtlantis::powerVoltageReceived()
1052 voltage33LineEdit->setText(QString("%1").arg(
1053 orte.pwr_voltage.voltage33, 0, 'f', 3));
1054 voltage50LineEdit->setText(QString("%1").arg(
1055 orte.pwr_voltage.voltage50, 0, 'f', 3));
1056 voltage80LineEdit->setText(QString("%1").arg(
1057 orte.pwr_voltage.voltage80, 0, 'f', 3));
1058 voltageBATLineEdit->setText(QString("%1").arg(
1059 orte.pwr_voltage.voltageBAT, 0, 'f', 3));
1063 /**********************************************************************
1065 **********************************************************************/
1066 void RobomonAtlantis::openSharedMemory()
1069 int sharedSegmentSize;
1071 if (sharedMemoryOpened)
1074 sharedSegmentSize = sizeof(unsigned int) * MAP_WIDTH * MAP_HEIGHT;
1076 /* Get segment identificator in a read only mode */
1077 segmentId = shmget(SHM_MAP_KEY, sharedSegmentSize, S_IRUSR);
1078 if(segmentId == -1) {
1079 statusBar->showMessage("No external map found - creating a new map.");
1085 /* Attach the shared memory segment */
1086 //map = (_Map*)shmat (segmentId, (void*) 0, 0);
1088 sharedMemoryOpened = true;
1091 double RobomonAtlantis::distanceToWallLidar(const struct lidar_params lidar, int beamnum)
1093 double distance = 4.0, min_distance = 4.0;
1096 struct map *map = ShmapIsMapInit();
1099 return min_distance;
1101 // Simulate obstacles
1102 for(j = 0; j < MAP_HEIGHT; j++) {
1103 for (i = 0; i < MAP_WIDTH; i++) {
1104 struct map_cell *cell = &map->cells[j][i];
1105 if( cell->flags & MAP_FLAG_SIMULATED_WALL) {
1107 ShmapCell2Point(i, j, &wall.x, &wall.y);
1109 distance = distanceToObstacleLidar(lidar, beamnum, wall, MAP_CELL_SIZE_M);
1110 if (distance < min_distance)
1111 min_distance = distance;
1116 return min_distance;
1119 double RobomonAtlantis::distanceToCircularObstacleLidar(const struct lidar_params lidar, int beamnum, Point center, double diameter)
1121 struct robot_pos_type e = orte.est_pos_best;
1125 s.x = lidar.center_offset_m;
1127 s.ang = index2rad(lidar, beamnum);
1129 Point sensor(e.x + s.x*cos(e.phi) - s.y*sin(e.phi),
1130 e.y + s.x*sin(e.phi) + s.y*cos(e.phi));
1131 sensor_a = e.phi + s.ang;
1133 const double sensorRange = 4.0; /*[meters]*/
1135 double distance = sensorRange;
1138 angle = sensor.angleTo(center) - sensor_a;
1139 angle = fmod(angle, 2.0 * M_PI);
1140 if (angle > +M_PI) angle -= 2.0 * M_PI;
1141 if (angle < -M_PI) angle += 2.0 * M_PI;
1142 angle = fabs(angle);
1144 double k = tan(sensor_a);
1145 double r = diameter / 2.0;
1147 double A = 1 + k * k;
1148 double B = 2 * (sensor.y * k - center.x - k * k * sensor.x - center.y * k);
1149 double C = center.x * center.x + center.y * center.y +
1150 k * k * sensor.x * sensor.x - 2*sensor.y*k*sensor.x +
1151 sensor.y * sensor.y + 2 * k * sensor.x *center.y -
1152 2 * sensor.y * center.y - r * r;
1154 double D = B * B - 4 * A * C;
1159 ob1.x = (-B + sqrt(D)) / (2 * A);
1160 ob2.x = (-B - sqrt(D)) / (2 * A);
1161 ob1.y = k * (ob1.x - sensor.x) + sensor.y;
1162 ob2.y = k * (ob2.x - sensor.x) + sensor.y;
1164 double distance1 = sensor.distanceTo(ob1);
1165 double distance2 = sensor.distanceTo(ob2);
1166 distance = (distance1 < distance2) ? distance1 : distance2;
1167 } else if (D == 0) {
1169 ob.x = -B / (2 * A);
1170 ob.y = k * (ob.x - sensor.x) + sensor.y;
1171 distance = sensor.distanceTo(ob);
1173 distance = distance + (drand48() - 0.5) * 3.0e-2;
1174 if (D < 0 || angle > atan(r / distance))
1175 distance = sensorRange;
1176 if (distance > sensorRange)
1177 distance = sensorRange;
1183 * Calculation for Lidar simulation. Calculates distance that would
1184 * be returned by Lidar sensors, if there is only one obstacle (as
1185 * specified by parameters).
1187 * @param beamnum Lidar's bean number [0..LIDAR_CLUSTER_CNT]
1188 * @param obstacle Position of the obstacle (x, y in meters).
1189 * @param obstacleSize Size (diameter) of the obstacle in meters.
1191 * @return Distance measured by sensors in meters.
1193 double RobomonAtlantis::distanceToObstacleLidar(const struct lidar_params lidar, int beamnum, Point obstacle, double obstacleSize)
1195 struct robot_pos_type e = orte.est_pos_best;
1199 s.x = lidar.center_offset_m;
1201 s.ang = index2rad(lidar, beamnum);
1203 Point sensor(e.x + s.x * cos(e.phi) - s.y * sin(e.phi),
1204 e.y + s.x * sin(e.phi) + s.y * cos(e.phi));
1205 sensor_a = e.phi + s.ang;
1207 const double sensorRange = 4.0; /*[meters]*/
1209 double distance, angle;
1211 angle = sensor.angleTo(obstacle) - sensor_a;
1212 angle = fmod(angle, 2.0 * M_PI);
1213 if (angle > +M_PI) angle -= 2.0 * M_PI;
1214 if (angle < -M_PI) angle += 2.0 * M_PI;
1215 angle = fabs(angle);
1216 distance = sensor.distanceTo(obstacle) - obstacleSize/2.0;
1217 if (angle < atan(obstacleSize/2.0 / distance)) {
1218 // We can see the obstackle from here.
1219 if (angle < M_PI/2.0) {
1220 distance = distance / cos(angle);
1222 if (distance > sensorRange)
1223 distance = sensorRange;
1225 distance = sensorRange;
1231 void RobomonAtlantis::sendStart(int plug)
1233 orte.robot_cmd.start_condition = plug ? 0 : 1;
1234 ORTEPublicationSend(orte.publication_robot_cmd);
1237 void RobomonAtlantis::setTeamColor(int plug)
1239 orte.robot_switches.team_color = plug ? 1 : 0;
1240 ORTEPublicationSend(orte.publication_robot_switches);
1243 void RobomonAtlantis::resetTrails()
1245 trailRefPos->reset();
1246 trailEstPosBest->reset();
1247 trailPosIndepOdo->reset();
1248 trailOdoPos->reset();
1251 void RobomonAtlantis::showTrails(bool show)
1253 trailRefPos->setVisible(show && robotRefPos->isVisible());
1254 trailEstPosBest->setVisible(show && robotEstPosBest->isVisible());
1255 trailPosIndepOdo->setVisible(show && robotEstPosIndepOdo->isVisible());
1256 trailOdoPos->setVisible(show && robotEstPosOdo->isVisible());
1259 void RobomonAtlantis::showShapeDetect(bool show)
1261 hokuyoScan->showShapeDetect = show;