Cheetah Software  1.0
HardwareBridge.cpp
Go to the documentation of this file.
1 #include "HardwareBridge.h"
2 #include <sys/mman.h>
3 #include <unistd.h>
4 #include <cstring>
5 #include <thread>
6 #include "rt/rt_interface_lcm.h"
7 #include "rt/rt_sbus.h"
8 #include "rt/rt_spi.h"
9 #include "rt/rt_vectornav.h"
10 
17 void HardwareBridge::initError(const char* reason, bool printErrno) {
18  printf("FAILED TO INITIALIZE HARDWARE: %s\n", reason);
19 
20  if (printErrno) {
21  printf("Error: %s\n", strerror(errno));
22  }
23 
24  exit(-1);
25 }
26 
31  printf("[HardwareBridge] Init stack\n");
32  prefaultStack();
33  printf("[HardwareBridge] Init scheduler\n");
35  if (!_interfaceLCM.good()) {
36  initError("_interfaceLCM failed to initialize\n", false);
37  }
38 
39  printf("[HardwareBridge] Subscribe LCM\n");
40  _interfaceLCM.subscribe("interface", &HardwareBridge::handleGamepadLCM, this);
41  _interfaceLCM.subscribe("interface_request",
43 
44  printf("[HardwareBridge] Start interface LCM handler\n");
46 }
47 
49  while (!_interfaceLcmQuit) _interfaceLCM.handle();
50 }
51 
61  printf("[Init] Prefault stack...\n");
62  volatile char stack[MAX_STACK_SIZE];
63  memset(const_cast<char*>(stack), 0, MAX_STACK_SIZE);
64  if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
65  initError(
66  "mlockall failed. This is likely because you didn't run robot as "
67  "root.\n",
68  true);
69  }
70 }
71 
76  printf("[Init] Setup RT Scheduler...\n");
77  struct sched_param params;
78  params.sched_priority = TASK_PRIORITY;
79  if (sched_setscheduler(0, SCHED_FIFO, &params) == -1) {
80  initError("sched_setscheduler failed.\n", true);
81  }
82 }
83 
84 void HardwareBridge::handleGamepadLCM(const lcm::ReceiveBuffer* rbuf,
85  const std::string& chan,
86  const gamepad_lcmt* msg) {
87  (void)rbuf;
88  (void)chan;
89  _gamepadCommand.set(msg);
90 }
91 
93  const lcm::ReceiveBuffer* rbuf, const std::string& chan,
94  const control_parameter_request_lcmt* msg) {
95  (void)rbuf;
96  (void)chan;
97  if (msg->requestNumber <= _parameter_response_lcmt.requestNumber) {
98  // nothing to do!
99  printf(
100  "[HardwareBridge] Warning: the interface has run a ControlParameter "
101  "iteration, but there is no new request!\n");
102  // return;
103  }
104 
105  // sanity check
106  s64 nRequests = msg->requestNumber - _parameter_response_lcmt.requestNumber;
107  if (nRequests != 1) {
108  printf("[ERROR] Hardware bridge: we've missed %ld requests\n",
109  nRequests - 1);
110  }
111 
112  switch (msg->requestKind) {
115  printf("[Warning] Got user param %s, but not using user parameters!\n",
116  (char*)msg->name);
117  } else {
118  std::string name((char*)msg->name);
120 
121  // type check
122  if ((s8)param._kind != msg->parameterKind) {
123  throw std::runtime_error(
124  "type mismatch for parameter " + name + ", robot thinks it is " +
126  " but received a command to set it to " +
128  (ControlParameterValueKind)msg->parameterKind));
129  }
130 
131  // do the actual set
133  memcpy(&v, msg->value, sizeof(v));
134  param.set(v, (ControlParameterValueKind)msg->parameterKind);
135 
136  // respond:
137  _parameter_response_lcmt.requestNumber =
138  msg->requestNumber; // acknowledge that the set has happened
139  _parameter_response_lcmt.parameterKind =
140  msg->parameterKind; // just for debugging print statements
141  memcpy(_parameter_response_lcmt.value, msg->value, 64);
142  //_parameter_response_lcmt.value = _parameter_request_lcmt.value; // just
143  //for debugging print statements
144  strcpy((char*)_parameter_response_lcmt.name,
145  name.c_str()); // just for debugging print statements
146  _parameter_response_lcmt.requestKind = msg->requestKind;
147 
148  printf("[User Control Parameter] set %s to %s\n", name.c_str(),
150  v, (ControlParameterValueKind)msg->parameterKind)
151  .c_str());
152  }
153  } break;
154 
156  std::string name((char*)msg->name);
158 
159  // type check
160  if ((s8)param._kind != msg->parameterKind) {
161  throw std::runtime_error(
162  "type mismatch for parameter " + name + ", robot thinks it is " +
164  " but received a command to set it to " +
166  (ControlParameterValueKind)msg->parameterKind));
167  }
168 
169  // do the actual set
171  memcpy(&v, msg->value, sizeof(v));
172  param.set(v, (ControlParameterValueKind)msg->parameterKind);
173 
174  // respond:
175  _parameter_response_lcmt.requestNumber =
176  msg->requestNumber; // acknowledge that the set has happened
177  _parameter_response_lcmt.parameterKind =
178  msg->parameterKind; // just for debugging print statements
179  memcpy(_parameter_response_lcmt.value, msg->value, 64);
180  //_parameter_response_lcmt.value = _parameter_request_lcmt.value; // just
181  //for debugging print statements
182  strcpy((char*)_parameter_response_lcmt.name,
183  name.c_str()); // just for debugging print statements
184  _parameter_response_lcmt.requestKind = msg->requestKind;
185 
186  printf("[Robot Control Parameter] set %s to %s\n", name.c_str(),
188  v, (ControlParameterValueKind)msg->parameterKind)
189  .c_str());
190 
191  } break;
192 
193  default: {
194  throw std::runtime_error("parameter type unsupported");
195  }
196  break;
197  }
198  _interfaceLCM.publish("interface_response", &_parameter_response_lcmt);
199 }
200 
202  : HardwareBridge(robot_ctrl), _spiLcm(getLcmUrl(255)) {}
203 
205  initCommon();
206  initHardware();
207 
208  //_robotRunner = new RobotRunner(&taskManager, 0.001f, "robot-control");
209 
218 
219  while (!_robotParams.isFullyInitialized()) {
220  printf("[Hardware Bridge] Waiting for robot parameters...\n");
221  usleep(1000000);
222  }
223 
226  printf("[Hardware Bridge] Waiting for user parameters...\n");
227  usleep(1000000);
228  }
229  }
230 
231  printf("[Hardware Bridge] Got all parameters, starting up!\n");
232 
233  _robotRunner->init();
234  _firstRun = false;
235 
236  // init control thread
237 
238  statusTask.start();
239 
240  // spi Task start
242  &taskManager, .002, "spi", &MiniCheetahHardwareBridge::runSpi, this);
243  spiTask.start();
244 
245  // robot controller start
246  _robotRunner->start();
247 
248  // visualization start
250  &taskManager, .0167, "lcm-vis",
252  visualizationLCMTask.start();
253 
254  // rc controller
255  _port = init_sbus(false); // Not Simulation
257  &taskManager, .005, "rc_controller", &HardwareBridge::run_sbus, this);
258  sbusTask.start();
259 
260  for (;;) {
261  usleep(1000000);
262  // printf("joy %f\n", _robotRunner->driverCommand->leftStickAnalog[0]);
263  }
264 }
265 
267  if (_port > 0) {
268  int x = receive_sbus(_port);
269  if (x) {
271  }
272  }
273 }
274 
276  printf("[MiniCheetahHardware] Init vectornav\n");
277  _vectorNavData.quat << 1, 0, 0, 0;
279  initError("failed to initialize vectornav!\n", false);
280  }
281 
282  init_spi();
283 
284  // init spi
285  // init sbus
286  // init lidarlite
287 
288  // init LCM hardware logging thread
289 
290  //
291 }
292 
294  spi_command_t* cmd = get_spi_command();
295  spi_data_t* data = get_spi_data();
296 
297  memcpy(cmd, &_spiCommand, sizeof(spi_command_t));
298  spi_driver_run();
299  memcpy(&_spiData, data, sizeof(spi_data_t));
300 
301  _spiLcm.publish("spi_data", data);
302  _spiLcm.publish("spi_command", cmd);
303 }
304 
306  cheetah_visualization_lcmt visualization_data;
307  for (int i = 0; i < 3; i++) {
308  visualization_data.x[i] = _mainCheetahVisualization.p[i];
309  }
310 
311  for (int i = 0; i < 4; i++) {
312  visualization_data.quat[i] = _mainCheetahVisualization.quat[i];
313  visualization_data.rgba[i] = _mainCheetahVisualization.color[i];
314  }
315 
316  for (int i = 0; i < 12; i++) {
317  visualization_data.q[i] = _mainCheetahVisualization.q[i];
318  }
319 
320  _visualizationLCM.publish("main_cheetah_visualization", &visualization_data);
321 }
void handleInterfaceLCM()
SpiCommand * spiCommand
Definition: RobotRunner.h:51
control_parameter_respones_lcmt _parameter_response_lcmt
SpiData * spiData
Definition: RobotRunner.h:50
ControlParameterCollection collection
ControlParameterValueKind _kind
ControlParameters * _userControlParameters
void publishVisualizationLCM()
Interface between robot code and robot hardware.
ControlParameterValueKind
GamepadCommand _gamepadCommand
std::string controlParameterValueKindToString(ControlParameterValueKind valueKind)
bool init_vectornav(VectorNavData *vd_data)
VectorNavData * vectorNavData
Definition: RobotRunner.h:48
MiniCheetahHardwareBridge(RobotController *)
volatile bool _interfaceLcmQuit
lcm::LCM _interfaceLCM
SpiCommand _spiCommand
VisualizationData _visualizationData
int64_t s64
Definition: cTypes.h:24
void handleControlParameter(const lcm::ReceiveBuffer *rbuf, const std::string &chan, const control_parameter_request_lcmt *msg)
std::string getLcmUrl(s64 ttl)
Definition: utilities.cpp:32
void init() override
Definition: RobotRunner.cpp:28
void set(ControlParameterValue value, ControlParameterValueKind kind)
void sbus_packet_complete()
Function which handles the completion of an SBUS Packet and overrides the LCM control settings as des...
GamepadCommand * driverCommand
Definition: RobotRunner.h:46
CheetahVisualization * cheetahMainVisualization
Definition: RobotRunner.h:56
lcm::LCM _visualizationLCM
int init_sbus(int is_simulator)
Definition: rt_sbus.cpp:119
void spi_driver_run()
Definition: rt_spi.cpp:319
int8_t s8
Definition: cTypes.h:21
ControlParameter & lookup(const std::string &name)
void init_spi()
Definition: rt_spi.cpp:110
RobotControlParameters * controlParameters
Definition: RobotRunner.h:54
std::string controlParameterValueToString(ControlParameterValue v, ControlParameterValueKind kind)
void set(const gamepad_lcmt *lcmt)
spi_data_t * get_spi_data()
Definition: rt_spi.cpp:337
Quat< float > quat
Definition: IMUTypes.h:16
void initError(const char *reason, bool printErrno=false)
#define MAX_STACK_SIZE
std::thread _interfaceLcmThread
PrintTaskStatus statusTask
int receive_sbus(int port)
Definition: rt_sbus.cpp:108
VectorNavData _vectorNavData
PeriodicTaskManager taskManager
#define TASK_PRIORITY
VisualizationData * visualizationData
Definition: RobotRunner.h:55
RobotControlParameters _robotParams
void handleGamepadLCM(const lcm::ReceiveBuffer *rbuf, const std::string &chan, const gamepad_lcmt *msg)
RobotRunner * _robotRunner
spi_command_t * get_spi_command()
Definition: rt_spi.cpp:332
CheetahVisualization _mainCheetahVisualization
RobotType robotType
Definition: RobotRunner.h:47