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 <actuators.h>
34 #include "PlaygroundScene.h"
36 #include "robomon_orte.h"
37 #include "RobomonAtlantis.h"
38 #include "playgroundview.h"
40 #include <QCoreApplication>
44 #include <QMessageBox>
46 RobomonAtlantis::RobomonAtlantis(QWidget *parent)
53 debugWindowEnabled = false;
58 QHBoxLayout *mainLayout = new QHBoxLayout;
59 mainLayout->addLayout(leftLayout);
60 mainLayout->addLayout(rightLayout);
61 setLayout(mainLayout);
67 setFocusPolicy(Qt::StrongFocus);
68 sharedMemoryOpened = false;
69 WDBG("Youuuhouuuu!!");
72 /**********************************************************************
74 **********************************************************************/
75 void RobomonAtlantis::createLeftLayout()
77 leftLayout = new QVBoxLayout();
79 createDebugGroupBox();
80 debugWindowEnabled = true;
81 createPlaygroundGroupBox();
83 leftLayout->addWidget(playgroundGroupBox);
84 leftLayout->addWidget(debugGroupBox);
87 void RobomonAtlantis::createRightLayout()
89 rightLayout = new QVBoxLayout();
90 QGridLayout *layout = new QGridLayout();
91 QVBoxLayout *vlayout = new QVBoxLayout();
93 createPositionGroupBox();
95 createActuatorsGroupBox();
97 createPowerGroupBox();
98 createSensorsGroupBox();
100 vlayout->addWidget(positionGroupBox);
101 vlayout->addWidget(miscGroupBox);
102 layout->addLayout(vlayout, 0, 0);
103 layout->addWidget(actuatorsGroupBox, 0, 1);
104 // layout->addWidget(dioGroupBox, 0, 2);
106 rightLayout->addLayout(layout);
107 rightLayout->addWidget(powerGroupBox);
108 rightLayout->addWidget(sensorsGroupBox);
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 layout->addWidget(playgroundSceneView);
124 playgroundGroupBox->setLayout(layout);
127 void RobomonAtlantis::createPositionGroupBox()
129 positionGroupBox = new QGroupBox(tr("Position state"));
130 QGridLayout *layout = new QGridLayout();
132 actPosX = new QLineEdit();
133 actPosY = new QLineEdit();
134 actPosPhi = new QLineEdit();
136 estPosX = new QLineEdit();
137 estPosY = new QLineEdit();
138 estPosPhi = new QLineEdit();
140 actPosX->setReadOnly(true);
141 actPosY->setReadOnly(true);
142 actPosPhi->setReadOnly(true);
144 estPosX->setReadOnly(true);
145 estPosY->setReadOnly(true);
146 estPosPhi->setReadOnly(true);
148 layout->addWidget(MiscGui::createLabel("X"), 1, 0);
149 layout->addWidget(MiscGui::createLabel("Y"), 2, 0);
150 layout->addWidget(MiscGui::createLabel("Phi"), 3, 0);
152 layout->addWidget(MiscGui::createLabel("X"), 5, 0);
153 layout->addWidget(MiscGui::createLabel("Y"), 6, 0);
154 layout->addWidget(MiscGui::createLabel("Phi"), 7, 0);
156 layout->addWidget(MiscGui::createLabel("Actual", Qt::AlignLeft), 0, 1);
157 layout->addWidget(actPosX, 1, 1);
158 layout->addWidget(actPosY, 2, 1);
159 layout->addWidget(actPosPhi, 3, 1);
161 layout->addWidget(MiscGui::createLabel("Estimated", Qt::AlignLeft), 4, 1);
162 layout->addWidget(estPosX, 5, 1);
163 layout->addWidget(estPosY, 6, 1);
164 layout->addWidget(estPosPhi, 7, 1);
166 positionGroupBox->setLayout(layout);
169 void RobomonAtlantis::createMiscGroupBox()
171 miscGroupBox = new QGroupBox(tr("Miscellaneous"));
172 QGridLayout *layout = new QGridLayout();
174 showMapPushButton = new QPushButton(tr("Show &map"));
175 showMapPushButton->setShortcut(tr("m"));
177 layout->addWidget(showMapPushButton, 0, 0);
179 miscGroupBox->setLayout(layout);
182 void RobomonAtlantis::createDebugGroupBox()
184 debugGroupBox = new QGroupBox(tr("Debug window"));
185 QHBoxLayout *layout = new QHBoxLayout();
187 debugWindow = new QTextEdit();
188 debugWindow->setReadOnly(true);
190 layout->addWidget(debugWindow);
191 debugGroupBox->setLayout(layout);
194 void RobomonAtlantis::createActuatorsGroupBox()
196 actuatorsGroupBox = new QGroupBox(tr("Actuators"));
197 QHBoxLayout *layout = new QHBoxLayout();
199 createMotorsGroupBox();
200 createPickerGroupBox();
202 layout->setAlignment(Qt::AlignLeft);
203 layout->addWidget(enginesGroupBox);
204 layout->addWidget(pickerGroupBox);
205 actuatorsGroupBox->setLayout(layout);
208 void RobomonAtlantis::createDIOGroupBox()
210 dioGroupBox = new QGroupBox(tr("DIO"));
211 QGridLayout *layout = new QGridLayout();
214 font.setPointSize(5);
215 dioGroupBox->setFont(font);
217 for (int i=0; i<8; i++) {
218 diCheckBox[i] = new QCheckBox(QString("DI%1").arg(i));
219 doCheckBox[i] = new QCheckBox(QString("D0%1").arg(i));
220 layout->addWidget(diCheckBox[i], i, 0);
221 layout->addWidget(doCheckBox[i], i+8, 0);
224 dioGroupBox->setMaximumWidth(70);
225 dioGroupBox->setLayout(layout);
228 void RobomonAtlantis::createPowerGroupBox()
230 powerGroupBox = new QGroupBox(tr("Power management"));
231 QGridLayout *layout = new QGridLayout();
233 voltage33CheckBox = new QCheckBox(tr("&3.3V"));
234 voltage50CheckBox = new QCheckBox(tr("&5.0V"));
235 voltage80CheckBox = new QCheckBox(tr("&8.0V"));
237 voltage33CheckBox->setShortcut(tr("3"));
238 voltage50CheckBox->setShortcut(tr("5"));
239 voltage80CheckBox->setShortcut(tr("8"));
241 layout->addWidget(voltage33CheckBox, 0, 0);
242 layout->addWidget(voltage50CheckBox, 0, 2);
243 layout->addWidget(voltage80CheckBox, 0, 4); //1, 0);
244 layout->addWidget(MiscGui::createLabel("BAT"), 0, 6); //1, 2);
246 voltage33LineEdit = new QLineEdit();
247 voltage50LineEdit = new QLineEdit();
248 voltage80LineEdit = new QLineEdit();
249 voltageBATLineEdit = new QLineEdit();
251 voltage33LineEdit->setReadOnly(true);
252 voltage50LineEdit->setReadOnly(true);
253 voltage80LineEdit->setReadOnly(true);
254 voltageBATLineEdit->setReadOnly(true);
256 layout->addWidget(voltage33LineEdit, 0, 1);
257 layout->addWidget(voltage50LineEdit, 0, 3);
258 layout->addWidget(voltage80LineEdit, 0, 5); //1, 1);
259 layout->addWidget(voltageBATLineEdit, 0, 7); //1, 3);
261 powerGroupBox->setLayout(layout);
264 void RobomonAtlantis::createSensorsGroupBox()
266 sensorsGroupBox = new QGroupBox(tr("Sensors"));
267 QVBoxLayout *layout = new QVBoxLayout();
269 createSharpSensorsLayout();
271 layout->addLayout(sharpSensorsLayout);
272 sensorsGroupBox->setLayout(layout);
275 void RobomonAtlantis::createMotorsGroupBox()
277 enginesGroupBox = new QGroupBox(tr("Motors"));
278 QVBoxLayout *layout = new QVBoxLayout();
279 QHBoxLayout *layout1 = new QHBoxLayout();
280 QHBoxLayout *layout2 = new QHBoxLayout();
282 leftMotorSlider = new QSlider(Qt::Vertical);
283 rightMotorSlider = new QSlider(Qt::Vertical);
284 bothMotorsCheckBox = new QCheckBox(tr("Lock both"));
285 stopMotorsPushButton = new QPushButton(tr("Stop Motors"));
287 leftMotorSlider->setMinimum(-100);
288 leftMotorSlider->setMaximum(100);
289 leftMotorSlider->setTracking(false);
290 leftMotorSlider->setTickPosition(QSlider::TicksLeft);
292 rightMotorSlider->setMinimum(-100);
293 rightMotorSlider->setMaximum(100);
294 rightMotorSlider->setTracking(false);
295 rightMotorSlider->setTickPosition(QSlider::TicksRight);
297 stopMotorsPushButton->setMaximumWidth(90);
299 layout1->addWidget(leftMotorSlider);
300 layout1->addWidget(MiscGui::createLabel("0"));
301 layout1->addWidget(rightMotorSlider);
303 layout2->addWidget(bothMotorsCheckBox);
305 layout->addWidget(MiscGui::createLabel("100"));
306 layout->addLayout(layout1);
307 layout->addWidget(MiscGui::createLabel("-100"));
308 layout->addLayout(layout2);
309 layout->addWidget(stopMotorsPushButton);
310 enginesGroupBox->setLayout(layout);
313 void RobomonAtlantis::createPickerGroupBox()
315 pickerGroupBox = new QGroupBox(tr("Picker"));
316 QVBoxLayout *layout = new QVBoxLayout();
318 leftBeltCheckBox = new QCheckBox(tr("L Belt"));
319 rightBeltCheckBox = new QCheckBox(tr("R Belt"));
320 leftChelaCheckBox = new QCheckBox(tr("L Chela"));
321 rightChelaCheckBox = new QCheckBox(tr("R Chela"));
322 leftBeltDial = new QDial();
323 rightBeltDial = new QDial();
324 leftChelaDial = new QDial();
325 rightChelaDial = new QDial();
326 pickPushButton = new QPushButton(tr("Pick!"));
328 leftBeltDial->setMinimum(0);
329 leftBeltDial->setMaximum(200);
330 leftBeltDial->setValue(100);
332 rightBeltDial->setMinimum(0);
333 rightBeltDial->setMaximum(200);
334 rightBeltDial->setValue(100);
336 leftChelaDial->setMinimum(0);
337 leftChelaDial->setMaximum(255);
338 leftChelaDial->setValue(127);
340 rightChelaDial->setMinimum(0);
341 rightChelaDial->setMaximum(255);
342 rightChelaDial->setValue(127);
344 layout->addWidget(leftChelaDial);
345 layout->addWidget(leftChelaCheckBox);
346 layout->addWidget(rightChelaDial);
347 layout->addWidget(rightChelaCheckBox);
348 layout->addWidget(leftBeltDial);
349 layout->addWidget(leftBeltCheckBox);
350 layout->addWidget(rightBeltDial);
351 layout->addWidget(rightBeltCheckBox);
352 layout->addWidget(pickPushButton);
354 pickerGroupBox->setLayout(layout);
357 void RobomonAtlantis::createSharpSensorsLayout()
359 sharpSensorsLayout = new QVBoxLayout();
360 QGridLayout *layout3 = new QGridLayout();
362 obstacleSimulationCheckBox = new QCheckBox(tr("&Obstacle simulation"));
364 obstacleSimulationCheckBox->setShortcut(tr("o"));
366 layout3->addWidget(obstacleSimulationCheckBox, 0, 1);
368 sharpSensorsLayout->addLayout(layout3);
371 void RobomonAtlantis::createRobots()
373 robotActPos = new Robot(QPen(), QBrush(Qt::darkGray));
374 robotActPos->setZValue(10);
375 robotEstPos = new Robot(QPen(Qt::darkBlue), QBrush(Qt::NoBrush));
376 robotEstPos->setZValue(11);
378 playgroundScene->addItem(robotActPos);
379 playgroundScene->addItem(robotEstPos);
382 /**********************************************************************
384 **********************************************************************/
385 void RobomonAtlantis::createActions()
387 /* power management */
388 connect(voltage33CheckBox, SIGNAL(stateChanged(int)),
389 this, SLOT(setVoltage33(int)));
390 connect(voltage50CheckBox, SIGNAL(stateChanged(int)),
391 this, SLOT(setVoltage50(int)));
392 connect(voltage80CheckBox, SIGNAL(stateChanged(int)),
393 this, SLOT(setVoltage80(int)));
396 connect(leftMotorSlider, SIGNAL(valueChanged(int)),
397 this, SLOT(setLeftMotor(int)));
398 connect(rightMotorSlider, SIGNAL(valueChanged(int)),
399 this, SLOT(setRightMotor(int)));
400 connect(stopMotorsPushButton, SIGNAL(clicked()),
401 this, SLOT(stopMotors()));
404 for (int i=0; i<8; i++)
405 connect(doCheckBox[0], SIGNAL(stateChanged(int)),
406 this, SLOT(setDO(int)));
408 /* path planning map */
409 connect(showMapPushButton, SIGNAL(clicked()),
410 this, SLOT(showMap()));
412 /* obstacle simulation */
413 simulationEnabled = 0;
414 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
415 this, SLOT(setSimulation(int)));
416 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
417 this, SLOT(setObstacleSimulation(int)));
418 connect(obstacleSimulationCheckBox, SIGNAL(stateChanged(int)),
419 playgroundScene, SLOT(showObstacle(int)));
420 connect(playgroundScene, SIGNAL(obstacleChanged(QPointF)),
421 this, SLOT(changeObstacle(QPointF)));
424 connect(pickPushButton, SIGNAL(clicked()), this, SLOT(pick()));
425 connect(leftBeltCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setBelts(int)));
426 connect(rightBeltCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setBelts(int)));
427 connect(leftChelaCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setChelae(int)));
428 connect(rightChelaCheckBox, SIGNAL(stateChanged(int)), this, SLOT(setChelae(int)));
429 connect(leftBeltDial, SIGNAL(valueChanged(int)), this, SLOT(setBelts(int)));
430 connect(rightBeltDial, SIGNAL(valueChanged(int)), this, SLOT(setBelts(int)));
431 connect(leftChelaDial, SIGNAL(valueChanged(int)), this, SLOT(setChelae(int)));
432 connect(rightChelaDial, SIGNAL(valueChanged(int)), this, SLOT(setChelae(int)));
435 void RobomonAtlantis::setVoltage33(int state)
438 orte.pwr_ctrl.voltage33 = true;
440 orte.pwr_ctrl.voltage33 = false;
443 void RobomonAtlantis::setVoltage50(int state)
446 orte.pwr_ctrl.voltage50 = true;
448 orte.pwr_ctrl.voltage50 = false;
451 void RobomonAtlantis::setVoltage80(int state)
454 orte.pwr_ctrl.voltage80 = true;
456 orte.pwr_ctrl.voltage80 = false;
459 void RobomonAtlantis::setLeftMotor(int value)
462 short int rightMotor;
464 if(bothMotorsCheckBox->isChecked())
465 rightMotorSlider->setValue(value);
467 leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
468 rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
470 orte.motion_speed.left = leftMotor;
471 orte.motion_speed.right = rightMotor;
475 void RobomonAtlantis::setRightMotor(int value)
478 short int rightMotor;
480 if(bothMotorsCheckBox->isChecked())
481 leftMotorSlider->setValue(value);
483 leftMotor = (short int)(MOTOR_LIMIT * (leftMotorSlider->value()/100.0));
484 rightMotor = (short int)(MOTOR_LIMIT * (rightMotorSlider->value()/100.0));
486 orte.motion_speed.left = leftMotor;
487 orte.motion_speed.right = rightMotor;
491 void RobomonAtlantis::stopMotors()
493 leftMotorSlider->setValue(0);
494 rightMotorSlider->setValue(0);
498 void RobomonAtlantis::setDO(int state)
501 /* FIXME: digital output control comes here */
504 void RobomonAtlantis::pick()
506 // TODO: send signal to the fsmact
509 void RobomonAtlantis::setBelts(int value)
512 unsigned char leftBelt;
513 unsigned char rightBelt;
515 leftBelt = (unsigned char)leftBeltDial->value();
516 rightBelt = (unsigned char)rightBeltDial->value();
518 act_belts(leftBelt, rightBelt);
521 void RobomonAtlantis::setChelae(int value)
524 unsigned char leftChela;
525 unsigned char rightChela;
527 leftChela = (unsigned char)leftChelaDial->value();
528 rightChela = (unsigned char)rightChelaDial->value();
530 act_chelae(leftChela, rightChela);
533 void RobomonAtlantis::showMap()
537 if (sharedMemoryOpened == false)
540 mapTimer = new QTimer(this);
541 connect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
542 mapTimer->start(200);
544 showMapPushButton->setText(tr("Show Playground"));
545 showMapPushButton->setShortcut(tr("p"));
546 disconnect(showMapPushButton, SIGNAL(clicked()), this, SLOT(showMap()));
547 connect(showMapPushButton, SIGNAL(clicked()),
548 this, SLOT(showPlayground()));
549 playgroundScene->showMap(true);
552 void RobomonAtlantis::showPlayground()
555 disconnect(mapTimer, SIGNAL(timeout()), this, SLOT(paintMap()));
559 showMapPushButton->setText(tr("Show &map"));
560 showMapPushButton->setShortcut(tr("m"));
561 disconnect(showMapPushButton, SIGNAL(clicked()),
562 this, SLOT(showPlayground()));
563 connect(showMapPushButton, SIGNAL(clicked()), this, SLOT(showMap()));
564 playgroundScene->showMap(false);
567 void RobomonAtlantis::paintMap()
571 struct map *map = ShmapIsMapInit();
575 for(int i=0; i < MAP_WIDTH; i++) {
576 for(int j=0; j<MAP_HEIGHT; j++) {
579 struct map_cell *cell = &map->cells[j][i];
581 if (cell->flags & MAP_FLAG_WALL)
583 if (cell->flags & MAP_FLAG_IGNORE_OBST)
585 if (cell->flags & MAP_FLAG_SIMULATED_WALL)
587 if (cell->flags & MAP_FLAG_PATH)
589 if (cell->flags & MAP_FLAG_START)
591 if (cell->flags & MAP_FLAG_GOAL)
593 if (cell->detected_obstacle) {
594 QColor c1(color), c2(blue);
595 double f = (double)cell->detected_obstacle/MAP_NEW_OBSTACLE*0.7;
596 QColor c(c1.red() + (int)(f*(c2.red() - c1.red())),
597 c1.green() + (int)(f*(c2.green() - c1.green())),
598 c1.blue() + (int)(f*(c2.blue() - c1.blue())));
601 if (cell->flags & MAP_FLAG_DET_OBST)
604 playgroundScene->setMapColor(i, j, color);
609 void RobomonAtlantis::setSimulation(int state)
612 robottype_publisher_hokuyo_scan_create(&orte,
613 dummy_publisher_callback, this);
615 if (!simulationEnabled)
617 robottype_publisher_hokuyo_scan_destroy(&orte);
619 simulationEnabled = state;
623 \fn RobomonAtlantis::setObstacleSimulation(int state)
625 void RobomonAtlantis::setObstacleSimulation(int state)
628 /* TODO Maybe it is possible to attach only once to Shmap */
630 obstacleSimulationTimer = new QTimer(this);
631 connect(obstacleSimulationTimer, SIGNAL(timeout()),
632 this, SLOT(simulateObstaclesHokuyo()));
633 obstacleSimulationTimer->start(100);
634 setMouseTracking(true);
636 if (obstacleSimulationTimer)
637 delete obstacleSimulationTimer;
638 //double distance = 0.8;
643 void RobomonAtlantis::simulateObstaclesHokuyo()
645 double distance, wall_distance;
647 uint16_t *hokuyo[34] = { // FIXME should be HOKUYO_CLUSTER_CNT
648 &orte.hokuyo_scan.data1,
649 &orte.hokuyo_scan.data2,
650 &orte.hokuyo_scan.data3,
651 &orte.hokuyo_scan.data4,
652 &orte.hokuyo_scan.data5,
653 &orte.hokuyo_scan.data6,
654 &orte.hokuyo_scan.data7,
655 &orte.hokuyo_scan.data8,
656 &orte.hokuyo_scan.data9,
657 &orte.hokuyo_scan.data10,
658 &orte.hokuyo_scan.data11,
659 &orte.hokuyo_scan.data12,
660 &orte.hokuyo_scan.data13,
661 &orte.hokuyo_scan.data14,
662 &orte.hokuyo_scan.data15,
663 &orte.hokuyo_scan.data16,
664 &orte.hokuyo_scan.data17,
665 &orte.hokuyo_scan.data18,
666 &orte.hokuyo_scan.data19,
667 &orte.hokuyo_scan.data20,
668 &orte.hokuyo_scan.data21,
669 &orte.hokuyo_scan.data22,
670 &orte.hokuyo_scan.data23,
671 &orte.hokuyo_scan.data24,
672 &orte.hokuyo_scan.data25,
673 &orte.hokuyo_scan.data26,
674 &orte.hokuyo_scan.data27,
675 &orte.hokuyo_scan.data28,
676 &orte.hokuyo_scan.data29,
677 &orte.hokuyo_scan.data30,
678 &orte.hokuyo_scan.data31,
679 &orte.hokuyo_scan.data32,
680 &orte.hokuyo_scan.data33,
681 &orte.hokuyo_scan.data34,
685 for (i=0; i<HOKUYO_CLUSTER_CNT; i++) {
686 wall_distance = distanceToWallHokuyo(i);
687 distance = distanceToObstacleHokuyo(i, simulatedObstacle, SIM_OBST_SIZE_M/*meters*/);
688 if (wall_distance < distance)
689 distance = wall_distance;
690 *hokuyo[i] = (uint16_t)(distance*1000);
692 ORTEPublicationSend(orte.publication_hokuyo_scan);
696 void RobomonAtlantis::changeObstacle(QPointF position)
698 if (!simulationEnabled) {
699 simulationEnabled = 1;
700 obstacleSimulationCheckBox->setChecked(true);
703 simulatedObstacle.x = position.x();
704 simulatedObstacle.y = position.y();
705 simulateObstaclesHokuyo();
708 /**********************************************************************
710 **********************************************************************/
711 bool RobomonAtlantis::event(QEvent *event)
713 switch (event->type()) {
714 case QEVENT(QEV_MOTION_STATUS):
715 emit motionStatusReceivedSignal();
717 case QEVENT(QEV_ACTUAL_POSITION):
718 emit actualPositionReceivedSignal();
720 case QEVENT(QEV_ESTIMATED_POSITION):
721 emit estimatedPositionReceivedSignal();
724 emit diReceivedSignal();
726 case QEVENT(QEV_ACCELEROMETER):
727 emit accelerometerReceivedSignal();
729 case QEVENT(QEV_ACCUMULATOR):
730 emit accumulatorReceivedSignal();
732 case QEVENT(QEV_POWER_VOLTAGE):
733 emit powerVoltageReceivedSignal();
736 if (event->type() == QEvent::Close)
737 closeEvent((QCloseEvent *)event);
738 else if (event->type() == QEvent::KeyPress)
739 keyPressEvent((QKeyEvent *)event);
740 else if (event->type() == QEvent::KeyRelease)
741 keyReleaseEvent((QKeyEvent *)event);
742 else if (event->type() == QEvent::FocusIn)
744 else if (event->type() == QEvent::FocusOut)
756 void RobomonAtlantis::keyPressEvent(QKeyEvent *event)
760 if (event->isAutoRepeat()) {
761 switch (event->key()) {
763 peak = leftMotorSlider->minimum()/2;
764 if (leftMotorValue < peak ||
765 rightMotorValue < peak)
769 leftMotorValue *= gain;
770 rightMotorValue *= gain;
771 leftMotorSlider->setValue((int)leftMotorValue);
772 rightMotorSlider->setValue((int)rightMotorValue);
778 peak = leftMotorSlider->maximum()/2;
779 if (leftMotorValue > peak ||
780 rightMotorValue > peak)
784 leftMotorValue *= gain;
785 rightMotorValue *= gain;
786 leftMotorSlider->setValue((int)leftMotorValue);
787 rightMotorSlider->setValue((int)rightMotorValue);
797 switch (event->key()) {
801 bothMotorsCheckBox->setChecked(true);
802 leftMotorSlider->setValue((int)leftMotorValue);
803 setLeftMotor((int)leftMotorValue);
807 rightMotorValue = -1;
808 bothMotorsCheckBox->setChecked(true);
809 leftMotorSlider->setValue((int)leftMotorValue);
810 setLeftMotor((int)leftMotorValue);
815 leftMotorSlider->setValue((int)leftMotorValue);
816 rightMotorSlider->setValue((int)rightMotorValue);
817 setLeftMotor((int)leftMotorValue);
818 setRightMotor((int)leftMotorValue);
822 rightMotorValue = -1;
823 leftMotorSlider->setValue((int)leftMotorValue);
824 rightMotorSlider->setValue((int)rightMotorValue);
825 setLeftMotor((int)leftMotorValue);
826 setRightMotor((int)rightMotorValue);
835 void RobomonAtlantis::keyReleaseEvent(QKeyEvent *event)
837 if (event->isAutoRepeat()) {
842 switch (event->key()) {
849 bothMotorsCheckBox->setChecked(false);
850 leftMotorSlider->setValue((int)leftMotorValue);
851 rightMotorSlider->setValue((int)rightMotorValue);
860 void RobomonAtlantis::closeEvent(QCloseEvent *)
862 robottype_roboorte_destroy(&orte);
865 /**********************************************************************
867 **********************************************************************/
868 void RobomonAtlantis::createOrte()
874 rv = robottype_roboorte_init(&orte);
876 printf("RobomonAtlantis: Unable to initialize ORTE\n");
880 robottype_publisher_motion_speed_create(&orte, dummy_publisher_callback, NULL);
882 robottype_publisher_pwr_ctrl_create(&orte, dummy_publisher_callback, NULL);
883 robottype_publisher_lift_create(&orte, NULL, &orte);
884 robottype_publisher_pusher_create(&orte, NULL, &orte);
885 robottype_publisher_chelae_create(&orte, NULL, &orte);
886 robottype_publisher_belts_create(&orte, NULL, &orte);
887 robottype_publisher_holder_create(&orte, NULL, &orte);
890 robottype_subscriber_pwr_voltage_create(&orte,
891 receivePowerVoltageCallBack, this);
892 robottype_subscriber_motion_status_create(&orte,
893 receiveMotionStatusCallBack, this);
894 robottype_subscriber_ref_pos_create(&orte,
895 receiveActualPositionCallBack, this);
896 robottype_subscriber_est_pos_create(&orte,
897 receiveEstimatedPositionCallBack, this);
899 //robottype_subscriber_actuator_status_create(orte, receiveActuatorStatusCallBack, this);
902 /*createDISubscriber(this, &orteData);*/
903 /*createAccelerometerSubscriber(this, &orteData);*/
904 /*createAccumulatorSubscriber(this, &orteData);*/
906 orte.motion_speed.left = 0;
907 orte.motion_speed.right = 0;
908 /* power management */
909 orte.pwr_ctrl.voltage33 = true;
910 orte.pwr_ctrl.voltage50 = true;
911 orte.pwr_ctrl.voltage80 = true;
912 voltage33CheckBox->setChecked(true);
913 voltage50CheckBox->setChecked(true);
914 voltage80CheckBox->setChecked(true);
918 /* set actions to do when we receive data from orte */
919 connect(this, SIGNAL(motionStatusReceivedSignal()),
920 this, SLOT(motionStatusReceived()));
921 connect(this, SIGNAL(actualPositionReceivedSignal()),
922 this, SLOT(actualPositionReceived()));
923 connect(this, SIGNAL(estimatedPositionReceivedSignal()),
924 this, SLOT(estimatedPositionReceived()));
925 connect(this, SIGNAL(diReceivedSignal()),
926 this, SLOT(diReceived()));
927 connect(this, SIGNAL(accelerometerReceivedSignal()),
928 this, SLOT(accelerometerReceived()));
929 connect(this, SIGNAL(accumulatorReceivedSignal()),
930 this, SLOT(accumulatorReceived()));
931 connect(this, SIGNAL(powerVoltageReceivedSignal()),
932 this, SLOT(powerVoltageReceived()));
935 void RobomonAtlantis::motionStatusReceived()
937 WDBG("ORTE received: motion status");
940 void RobomonAtlantis::actualPositionReceived()
942 actPosX->setText(QString("%1").arg(orte.ref_pos.x, 0, 'f', 3));
943 actPosY->setText(QString("%1").arg(orte.ref_pos.y, 0, 'f', 3));
944 actPosPhi->setText(QString("%1(%2)")
945 .arg(DEGREES(orte.ref_pos.phi), 0, 'f', 0)
946 .arg(orte.ref_pos.phi, 0, 'f', 1));
947 robotActPos->moveRobot(orte.ref_pos.x,
948 orte.ref_pos.y, orte.ref_pos.phi);
951 void RobomonAtlantis::estimatedPositionReceived()
953 estPosX->setText(QString("%1").arg(orte.est_pos.x, 0, 'f', 3));
954 estPosY->setText(QString("%1").arg(orte.est_pos.y, 0, 'f', 3));
955 estPosPhi->setText(QString("%1(%2)")
956 .arg(DEGREES(orte.est_pos.phi), 0, 'f', 0)
957 .arg(orte.est_pos.phi, 0, 'f', 1));
958 robotEstPos->moveRobot(orte.est_pos.x,
959 orte.est_pos.y, orte.est_pos.phi);
962 void RobomonAtlantis::diReceived()
964 WDBG("ORTE received: DI");
967 void RobomonAtlantis::accelerometerReceived()
969 WDBG("ORTE received: accelerometer");
972 void RobomonAtlantis::accumulatorReceived()
974 WDBG("ORTE received: accumulator");
977 void RobomonAtlantis::powerVoltageReceived()
979 voltage33LineEdit->setText(QString("%1").arg(
980 orte.pwr_voltage.voltage33, 0, 'f', 3));
981 voltage50LineEdit->setText(QString("%1").arg(
982 orte.pwr_voltage.voltage50, 0, 'f', 3));
983 voltage80LineEdit->setText(QString("%1").arg(
984 orte.pwr_voltage.voltage80, 0, 'f', 3));
985 voltageBATLineEdit->setText(QString("%1").arg(
986 orte.pwr_voltage.voltageBAT, 0, 'f', 3));
990 /**********************************************************************
992 **********************************************************************/
993 void RobomonAtlantis::openSharedMemory()
996 int sharedSegmentSize;
998 if (sharedMemoryOpened)
1001 sharedSegmentSize = sizeof(char) * MAP_WIDTH * MAP_HEIGHT;
1003 /* Get segment identificator in a read only mode */
1004 segmentId = shmget(SHM_MAP_KEY, sharedSegmentSize, S_IRUSR);
1005 if(segmentId == -1) {
1006 QMessageBox::critical(this, "robomon",
1007 "Unable to open shared memory segment!");
1014 /* Attach the shared memory segment */
1015 //map = (_Map*)shmat (segmentId, (void*) 0, 0);
1017 sharedMemoryOpened = true;
1020 double RobomonAtlantis::distanceToWallHokuyo(int beamnum)
1022 double distance=4.0, min_distance=4.0;
1025 struct map *map = ShmapIsMapInit();
1027 if (!map) return min_distance;
1029 // Simulate obstacles
1030 for(j=0;j<MAP_HEIGHT;j++) {
1031 for (i=0;i<MAP_WIDTH;i++) {
1032 struct map_cell *cell = &map->cells[j][i];
1033 if( cell->flags & MAP_FLAG_SIMULATED_WALL) {
1035 ShmapCell2Point(i, j, &wall.x, &wall.y);
1037 distance = distanceToObstacleHokuyo(beamnum, wall, MAP_CELL_SIZE_M);
1038 if (distance<min_distance) min_distance = distance;
1043 return min_distance;
1047 * Calculation for Hokuyo simulation. Calculates distance that would
1048 * be returned by Hokuyo sensors, if there is only one obstacle (as
1049 * specified by parameters).
1051 * @param beamnum Hokuyo's bean number [0..HOKUYO_CLUSTER_CNT]
1052 * @param obstacle Position of the obstacle (x, y in meters).
1053 * @param obstacleSize Size (diameter) of the obstacle in meters.
1055 * @return Distance measured by sensors in meters.
1057 double RobomonAtlantis::distanceToObstacleHokuyo(int beamnum, Point obstacle, double obstacleSize)
1059 struct est_pos_type e = orte.est_pos;
1063 s.x = HOKUYO_CENTER_OFFSET_M;
1065 s.ang = HOKUYO_CLUSTER_TO_RAD(beamnum);
1067 Point sensor(e.x + s.x*cos(e.phi) - s.y*sin(e.phi),
1068 e.y + s.x*sin(e.phi) + s.y*cos(e.phi));
1069 sensor_a = e.phi + s.ang;
1071 const double sensorRange = 4.0; /*[meters]*/
1073 double distance, angle;
1075 angle = sensor.angleTo(obstacle) - sensor_a;
1076 angle = fmod(angle, 2.0*M_PI);
1077 if (angle > +M_PI) angle -= 2.0*M_PI;
1078 if (angle < -M_PI) angle += 2.0*M_PI;
1079 angle = fabs(angle);
1080 distance = sensor.distanceTo(obstacle)-0.11;
1081 if (angle < atan(obstacleSize/2.0 / (distance+0.001))) {
1082 // We can see the obstackle from here.
1083 if (angle < M_PI/2.0) {
1084 distance = distance/cos(angle);
1086 if (distance > sensorRange)
1087 distance = sensorRange;
1089 distance = sensorRange;