Cheetah Software  1.0
SimControlPanel.cpp
Go to the documentation of this file.
1 #include "SimControlPanel.h"
3 #include <QFileDialog>
4 #include <QMessageBox>
5 #include "ui_SimControlPanel.h"
6 
7 
11 static void createErrorMessage(const std::string& text) {
12  QMessageBox mb;
13  mb.setText(QString(text.c_str()));
14  mb.exec();
15 }
16 
21  QTableWidget& table) {
22  table.setRowCount((s32)params.collection._map.size());
23  table.setColumnCount(2);
24 
25  s32 i = 0;
26  for (auto& kv : params.collection._map) {
27  (void)kv;
28  for (s32 col = 0; col < 2; col++) {
29  QTableWidgetItem* cell = table.item(i, col);
30  if (!cell) {
31  cell = new QTableWidgetItem;
32  table.setItem(i, col, cell);
33  }
34  }
35 
36  table.item(i, 0)->setText(QString(kv.first.c_str()));
37  table.item(i, 1)->setText(QString(kv.second->toString().c_str()));
38  i++;
39  }
40 }
41 
46  : QMainWindow(parent),
47  ui(new Ui::SimControlPanel),
48  _userParameters("user-parameters"),
49  _terrainFileName(getConfigDirectoryPath() + DEFAULT_TERRAIN_FILE) {
50 
51  ui->setupUi(this); // QT setup
52  updateUiEnable(); // enable/disable buttons as needed.
53  updateTerrainLabel(); // display name of loaded terrain file
54 
55  // attempt to load default user settings.
56  _loadedUserSettings = true;
57 
58  try {
60  } catch (std::runtime_error& ex) {
61  _loadedUserSettings = false;
62  }
63 
64  if(!_loadedUserSettings) {
65  printf("[SimControlPanel] Failed to load default user settings!\n");
66  } else {
67  // display user settings in qtable if we loaded successfully
69  }
70 
71  // load simulator parameters
72  printf("[SimControlPanel] Init simulator parameters...\n");
76  printf(
77  "[ERROR] Simulator parameters are not fully initialized. You forgot: "
78  "\n%s\n",
80  throw std::runtime_error("simulator not initialized");
81  } else {
82  printf("\tsim parameters are all good\n");
83  }
85 }
86 
88  delete _simulation;
89  delete _interfaceTaskManager;
90  delete _robotInterface;
91  delete _graphicsWindow;
92  delete ui;
93 }
94 
99  ui->startButton->setEnabled(!_started);
100  ui->stopButton->setEnabled(_started);
101  ui->joystickButton->setEnabled(_started);
102  ui->robotTable->setEnabled(_started);
103  ui->goHomeButton->setEnabled(_started);
104 }
105 
110  ui->terrainFileLabel->setText(QString(_terrainFileName.c_str()));
111 }
112 
117  // get robot type
118  RobotType robotType;
119 
120  if (ui->cheetah3Button->isChecked()) {
121  robotType = RobotType::CHEETAH_3;
122  } else if (ui->miniCheetahButton->isChecked()) {
123  robotType = RobotType::MINI_CHEETAH;
124  } else {
125  createErrorMessage("Error: you must select a robot");
126  return;
127  }
128 
129  // get run type
130  if (!ui->simulatorButton->isChecked() && !ui->robotButton->isChecked()) {
132  "Error: you must select either robot or simulation mode");
133  return;
134  }
135 
136  _simulationMode = ui->simulatorButton->isChecked();
137 
138  // graphics
139  printf("[SimControlPanel] Initialize Graphics...\n");
140  _graphicsWindow = new Graphics3D();
141  _graphicsWindow->show();
142  _graphicsWindow->resize(1280, 720);
143 
144  if (_simulationMode) {
145  // run a simulation
146  printf("[SimControlPanel] Initialize simulator...\n");
150 
151  // terrain
152  printf("[SimControlParameter] Load terrain...\n");
154 
155  // start sim
156  _simThread = std::thread([this]() { _simulation->runAtSpeed(); });
157 
158  // graphics start
160  } else {
161  printf("[SimControlPanel] Init Robot Interface...\n");
168  }
169 
170  _started = true;
171  updateUiEnable();
172 }
173 
178  if (_simulation) {
179  _simulation->stop();
180  _simThread.join();
181  } else {
183  }
184 
185  if (_graphicsWindow) {
187  _graphicsWindow->hide();
188  }
189 
190  delete _interfaceTaskManager;
191  delete _robotInterface;
192  delete _simulation;
193  delete _graphicsWindow;
194 
195  _simulation = nullptr;
196  _graphicsWindow = nullptr;
197  _robotInterface = nullptr;
198  _interfaceTaskManager = nullptr;
199 
200  _started = false;
201  updateUiEnable();
202 }
203 
204 
205 
210  SimulatorControlParameters& params) {
211  _ignoreTableCallbacks = true;
212  updateQtableWithParameters(params, *ui->simulatorTable);
213  _ignoreTableCallbacks = false;
214 }
215 
220  _ignoreTableCallbacks = true;
221  updateQtableWithParameters(params, *ui->robotTable);
222  _ignoreTableCallbacks = false;
223 }
224 
229  _ignoreTableCallbacks = true;
230  updateQtableWithParameters(params, *ui->userControlTable);
231  _ignoreTableCallbacks = false;
232 }
233 
239 }
240 
242 
247  if (_ignoreTableCallbacks) return;
248 
249  // we only allow values to change, which are in column 1
250  if (column != 1) {
251  return;
252  }
253 
254  // get the name of the parameter....
255  auto cell = ui->simulatorTable->item(row, 0);
256  std::string cellName = cell->text().toStdString();
257 
258  if (cellName == "") {
259  return;
260  }
261 
262  // get the parameters
263  auto& parameter = _parameters.collection.lookup(cellName);
264  ControlParameterValueKind kind = parameter._kind;
265  ControlParameterValue oldValue = parameter.get(kind);
266 
267  bool success = true;
268 
269  // attempt to set, based on string.
270  try {
271  parameter.setFromString(
272  ui->simulatorTable->item(row, 1)->text().toStdString());
273  } catch (std::exception& e) {
274  success = false;
275  }
276 
277  // if it fails (bad user input string), restore to the old value
278  if (!success) {
279  printf("[ERROR] invalid data, restoring old data!\n");
280  // set parameter value
281  parameter.set(oldValue, kind);
282 
283  assert(!_ignoreTableCallbacks);
284 
285  // manually fix the table
286  _ignoreTableCallbacks = true;
287  ui->simulatorTable->item(row, 1)->setText(
288  QString(_parameters.collection.lookup(cellName).toString().c_str()));
289  _ignoreTableCallbacks = false;
290  } else {
291  // this update "rewrites" the value in the table. If it's an integer, it kills any
292  // decimal. If it's a float, it puts in scientific notation if needed.
293  _ignoreTableCallbacks = true;
294  ui->simulatorTable->item(row, 1)->setText(
295  QString(parameter.toString().c_str()));
296  _ignoreTableCallbacks = false;
297  }
298 }
299 
304  QString fileName = QFileDialog::getSaveFileName(
305  nullptr, ("Save Simulator Table Values"), "../config", "All Files (*)");
306  if (fileName == nullptr || fileName == "") {
307  createErrorMessage("File name is invalid");
308  return;
309  }
310 
312  _parameters.writeToYamlFile(fileName.toStdString());
314 }
315 
320  QString fileName = QFileDialog::getOpenFileName(
321  nullptr, ("Load Simulator Table Values"), "../config", "All Files (*)");
322  if (fileName == nullptr || fileName == "") {
323  createErrorMessage("File name is invalid");
324  return;
325  };
327  _parameters.initializeFromYamlFile(fileName.toStdString());
329  printf(
330  "new settings file %s doesn't contain the following simulator "
331  "parameters:\n%s\n",
332  fileName.toStdString().c_str(),
334  throw std::runtime_error("bad new settings file");
335  }
338 }
339 
341  if (_ignoreTableCallbacks) return;
342  if (column != 1) {
343  return;
344  }
345 
346  auto cell = ui->robotTable->item(row, 0);
347  std::string cellName = cell->text().toStdString();
348 
349  if (cellName == "") {
350  return;
351  }
352 
353  auto& parameter = (_simulationMode ? _simulation->getRobotParams()
355  .collection.lookup(cellName);
356  ControlParameterValueKind kind = parameter._kind;
357  ControlParameterValue oldValue = parameter.get(kind);
358 
359  bool success = true;
360 
361  try {
362  parameter.setFromString(ui->robotTable->item(row, 1)->text().toStdString());
363  } catch (std::exception& e) {
364  success = false;
365  }
366 
367  if (!success) {
368  printf("[ERROR] invalid data, restoring old data!\n");
369  parameter.set(oldValue, kind);
370 
371  assert(!_ignoreTableCallbacks);
372 
373  _ignoreTableCallbacks = true;
374  ui->robotTable->item(row, 1)->setText(
375  QString(parameter
376  .toString()
377  .c_str()));
378  _ignoreTableCallbacks = false;
379  } else {
380  if (_simulationMode) {
381  if (_simulation->isRobotConnected()) {
383  cellName, parameter.get(parameter._kind), parameter._kind, false);
384  }
385 
386  _ignoreTableCallbacks = true;
387  ui->robotTable->item(row, 1)->setText(
388  QString(parameter.toString().c_str()));
389  _ignoreTableCallbacks = false;
390  } else {
392  cellName, parameter.get(parameter._kind), parameter._kind, false);
393  }
394  }
395 }
396 
398  QString fileName = QFileDialog::getSaveFileName(
399  nullptr, ("Save Robot Table Values"), "../config", "All Files (*)");
400  if (fileName == nullptr || fileName == "") {
401  createErrorMessage("File name is invalid");
402  return;
403  }
404  _simulation->getRobotParams().writeToYamlFile(fileName.toStdString());
405 }
406 
408  QString fileName = QFileDialog::getOpenFileName(
409  nullptr, ("Load Quadruped Table Values"), "../config", "All Files (*)");
410  if (fileName == nullptr || fileName == "") {
411  createErrorMessage("File name is invalid");
412  return;
413  }
414 
415  if (_simulationMode) {
419  fileName.toStdString());
421  printf(
422  "new settings file %s doesn't contain the following robot "
423  "parameters:\n%s\n",
424  fileName.toStdString().c_str(),
426  throw std::runtime_error("bad new settings file");
427  }
429 
430  if (_simulation->isRobotConnected()) {
431  for (auto& kv : _simulation->getRobotParams().collection._map) {
433  kv.first, kv.second->get(kv.second->_kind), kv.second->_kind, false);
434  }
435  }
437  } else {
440  _robotInterface->getParams().initializeFromYamlFile(fileName.toStdString());
442  printf(
443  "new settings file %s doesn't contain the following robot "
444  "parameters:\n%s\n",
445  fileName.toStdString().c_str(),
447  throw std::runtime_error("bad new settings file");
448  }
450 
451  for (auto& kv : _robotInterface->getParams().collection._map) {
453  kv.first, kv.second->get(kv.second->_kind), kv.second->_kind, false);
454  }
455 
457  }
458 }
459 
461  QString fileName = QFileDialog::getOpenFileName(
462  nullptr, ("Load Terrain Definition"), "../config", "All Files (*)");
463  if (fileName == nullptr || fileName == "") {
464  createErrorMessage("File name is invalid");
465  return;
466  }
467 
468  _terrainFileName = fileName.toStdString();
470 }
471 
473  if (_ignoreTableCallbacks) return;
474  if (column != 1) {
475  return;
476  }
477 
478  auto cell = ui->userControlTable->item(row, 0);
479  std::string cellName = cell->text().toStdString();
480 
481  if (cellName == "") {
482  return;
483  }
484 
485  auto& parameter = _userParameters.collection.lookup(cellName);
486 // auto& parameter = (_simulationMode ? _simulation->getRobotParams()
487 // : _robotInterface->getParams())
488 // .collection.lookup(cellName);
489  ControlParameterValueKind kind = parameter._kind;
490  ControlParameterValue oldValue = parameter.get(kind);
491 
492  bool success = true;
493 
494  try {
495  parameter.setFromString(ui->userControlTable->item(row, 1)->text().toStdString());
496  } catch (std::exception& e) {
497  success = false;
498  }
499 
500  if (!success) {
501  printf("[ERROR] invalid data, restoring old data!\n");
502  parameter.set(oldValue, kind);
503 
504  assert(!_ignoreTableCallbacks);
505 
506  _ignoreTableCallbacks = true;
507  ui->userControlTable->item(row, 1)->setText(
508  QString(_userParameters
509  .collection.lookup(cellName)
510  .toString()
511  .c_str()));
512  _ignoreTableCallbacks = false;
513  } else {
514  if(_started) {
515  if (_simulationMode) {
518  cellName, parameter.get(parameter._kind), parameter._kind, true);
519  }
520 
521  _ignoreTableCallbacks = true;
522  ui->userControlTable->item(row, 1)->setText(
523  QString(parameter.toString().c_str()));
524  _ignoreTableCallbacks = false;
525  } else {
527  cellName, parameter.get(parameter._kind), parameter._kind, true);
528  }
529  }
530  }
531 }
532 
534  QString fileName = QFileDialog::getOpenFileName(
535  nullptr, ("Load User Table Values"), "../config", "All Files (*)");
536  if (fileName == nullptr || fileName == "") {
537  createErrorMessage("File name is invalid");
538  return;
539  }
540 
544  fileName.toStdString());
547  _loadedUserSettings = true;
548 
549  if(_started) {
550  if (_simulationMode) {
552  for (auto& kv : _userParameters.collection._map) {
554  kv.first, kv.second->get(kv.second->_kind), kv.second->_kind, true);
555  }
556  }
557  } else {
558  for (auto& kv : _userParameters.collection._map) {
560  kv.first, kv.second->get(kv.second->_kind), kv.second->_kind, true);
561  }
562 
563  }
564  }
565 }
566 
568  QString fileName = QFileDialog::getSaveFileName(
569  nullptr, ("Save User Table Values"), "../config", "All Files (*)");
570  if (fileName == nullptr || fileName == "") {
571  createErrorMessage("File name is invalid");
572  return;
573  }
574  _userParameters.writeToYamlFile(fileName.toStdString());
575 }
576 
578  printf("go home\n");
579  FBModelState<double> homeState;
580  homeState.bodyOrientation << 1, 0, 0, 0;
581  homeState.bodyPosition = Vec3<double>(0, 0, 0.4);
582  homeState.bodyVelocity = SVec<double>::Zero();
583  homeState.q = DVec<double>(12);
584  homeState.q << -0.05, -0.8, 1.7, 0.05, -0.8, 1.7, -0.05, -0.8, 1.7, 0.05, -0.8, 1.7;
585  homeState.qd = homeState.q;
586 
587  _simulation->setRobotState(homeState);
588 }
589 
591  // velocity of the floating base:
592  SVec<double> kickVelocity;
593  kickVelocity << ui->kickAngularX->text().toDouble(),
594  ui->kickAngularY->text().toDouble(), ui->kickAngularZ->text().toDouble(),
595  ui->kickLinearX->text().toDouble(), ui->kickLinearY->text().toDouble(),
596  ui->kickLinearZ->text().toDouble();
597 
599  state.bodyVelocity += kickVelocity;
600  _simulation->setRobotState(state);
601 }
void resetGameController()
Definition: Graphics3D.h:54
Vec3< T > bodyPosition
void stop()
Definition: Simulation.h:96
static void updateQtableWithParameters(ControlParameters &params, QTableWidget &table)
const FBModelState< double > & getRobotState()
Definition: Simulation.h:94
Simulation * _simulation
void runAtSpeed(bool graphics=true)
Definition: Simulation.cpp:579
void on_goHomeButton_clicked()
ControlParameterCollection collection
SVec< T > bodyVelocity
void on_loadSimulatorButton_clicked()
ControlParameterValueKind _kind
void sendControlParameter(const std::string &name, ControlParameterValue value, ControlParameterValueKind kind, bool isUser)
void on_loadRobotButton_clicked()
ControlParameterValueKind
std::map< std::string, ControlParameter * > _map
void on_setTerrainButton_clicked()
SimControlPanel(QWidget *parent=nullptr)
ControlParameters _userParameters
RobotInterface * _robotInterface
typename Eigen::Matrix< T, 3, 1 > Vec3
Definition: cppTypes.h:26
#define SIMULATOR_DEFAULT_PARAMETERS
SimulatorControlParameters _parameters
std::string toString()
void on_saveUserButton_clicked()
void loadRobotParameters(RobotControlParameters &params)
void loadTerrainFile(const std::string &terrainFileName, bool addGraphics=true)
Definition: Simulation.cpp:638
void on_joystickButton_clicked()
void on_userControlTable_cellChanged(int row, int column)
std::string getConfigDirectoryPath()
Definition: utilities.cpp:30
typename Eigen::Matrix< T, 6, 1 > SVec
Definition: cppTypes.h:62
void writeToYamlFile(const std::string &path)
std::thread _simThread
#define DEFAULT_TERRAIN_FILE
void setRobotState(FBModelState< double > &state)
Definition: Simulation.h:48
void on_robotTable_cellChanged(int row, int column)
PeriodicTaskManager * _interfaceTaskManager
bool checkIfAllSet()
are all the control parameters initialized?
ControlParameter & lookup(const std::string &name)
RobotControlParameters & getRobotParams()
Definition: Simulation.h:108
void loadUserParameters(ControlParameters &params)
RobotControlParameters & getParams()
Ui::SimControlPanel * ui
Graphics3D * _graphicsWindow
void setAnimating(bool animating)
Definition: Graphics3D.cpp:331
int32_t s32
Definition: cTypes.h:23
void on_saveSimulatorButton_clicked()
static void createErrorMessage(const std::string &text)
QT gui for the simulator.
void on_simulatorTable_cellChanged(int row, int column)
void defineAndInitializeFromYamlFile(const std::string &path)
typename Eigen::Matrix< T, Eigen::Dynamic, 1 > DVec
Definition: cppTypes.h:102
void loadSimulationParameters(SimulatorControlParameters &params)
RobotType
Definition: cppTypes.h:120
Interface to set gains/control parameters for simulator and robot These are designed to be updated in...
void on_loadUserButton_clicked()
#define DEFAULT_USER_FILE
void initializeFromYamlFile(const std::string &path)
SimulatorControlParameters & getSimParams()
Definition: Simulation.h:106
void sendControlParameter(const std::string &name, ControlParameterValue value, ControlParameterValueKind kind, bool isUser)
Definition: Simulation.cpp:216
void on_saveRobotButton_clicked()
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Quat< T > bodyOrientation
std::string generateUnitializedList()
void on_driverButton_clicked()
std::string _terrainFileName
bool isRobotConnected()
Definition: Simulation.h:111