Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / DiWheelDrive.cpp @ ba75ee1d

History | View | Annotate | Download (11.046 KB)

1 58fe0e0b Thomas Schöpping
#include "ch.hpp"
2
#include "hal.h"
3
#include "qei.h"
4
#include "DiWheelDrive.h"
5 8c99e03a galberding
// #include <chprintf.h>
6 58fe0e0b Thomas Schöpping
7 9c46b728 galberding
8 58fe0e0b Thomas Schöpping
#include <global.hpp>
9
10
using namespace chibios_rt;
11
using namespace amiro;
12
using namespace types;
13
14
extern volatile uint32_t shutdown_now;
15
extern Global global;
16
17
DiWheelDrive::DiWheelDrive(CANDriver *can)
18
    : ControllerAreaNetworkTx(can, CAN::DI_WHEEL_DRIVE_ID),
19
      ControllerAreaNetworkRx(can, CAN::DI_WHEEL_DRIVE_ID),
20
      bcCounter(0)
21
{
22
}
23
24
msg_t DiWheelDrive::receiveMessage(CANRxFrame *frame) {
25
  int deviceId = this->decodeDeviceId(frame);
26
27
  switch (deviceId) {
28
29
    case CAN::SHELL_REPLY_ID(CAN::DI_WHEEL_DRIVE_ID):
30
      if (frame->DLC > 0) {
31
        sdWrite(&SD1, frame->data8, frame->DLC);
32
        return RDY_OK;
33
      }
34
      break;
35
36
    case CAN::SHELL_QUERY_ID(CAN::DI_WHEEL_DRIVE_ID):
37
      if (frame->DLC != 0) {
38
        global.sercanmux1.convCan2Serial(frame->data8, frame->DLC);
39
        return RDY_OK;
40
      } else {
41
        global.sercanmux1.rcvSwitchCmd(this->decodeBoardId(frame));
42
        return RDY_OK;
43
      }
44
      break;
45
46
    case CAN::TARGET_SPEED_ID:
47
      if (frame->DLC == 8) {
48
        global.distcontrol.deactivateController();
49
        kinematic targetVelocity;
50
        targetVelocity.x = frame->data32[0];
51
        targetVelocity.w_z = frame->data32[1];
52
        global.motorcontrol.setTargetSpeed(targetVelocity);
53
        return RDY_OK;
54
      }
55
      break;
56
57
    case CAN::TARGET_RPM_ID:
58
      if (frame->DLC == 8) {
59
        global.distcontrol.deactivateController();
60
        global.motorcontrol.setTargetRPM(frame->data32[0], frame->data32[1]);
61
        return RDY_OK;
62
      }
63
      break;
64
65
    case CAN::SET_ODOMETRY_ID:
66
      if (frame->DLC == 8) {
67
        int32_t robotPositionX = (frame->data8[0] << 8 | frame->data8[1] << 16 | frame->data8[2] << 24);
68
        int32_t robotPositionY = (frame->data8[3] << 8 | frame->data8[4] << 16 | frame->data8[5] << 24);
69
        int32_t robotPositionF_Z = (frame->data8[6] << 8 | frame->data8[7] << 16);
70
        global.odometry.setPosition(float(robotPositionX)*1e-6,float(robotPositionY)*1e-6,float(robotPositionF_Z)*1e-6);
71
        return RDY_OK;
72
      }
73
      break;
74
75
    case CAN::BROADCAST_SHUTDOWN:
76
      if (frame->DLC == 2 && frame->data16[0] == CAN::SHUTDOWN_MAGIC) {
77
        shutdown_now = 0x4;
78
        return RDY_OK;
79
      }
80
      break;
81
82
    case CAN::CALIBRATE_PROXIMITY_FLOOR:
83
      // Dont care about the payload but start the calibration
84
      // TODO Care about the payload. Differ between:
85
      // 1: Do fresh calibration (Save values to memory and to temporary values)
86
      // 2: Remove temporary Calibration and get uncalibrated values
87
      // 3: Load calibration from memory
88
      this->calibrate();
89
      break;
90
91
    case CAN::TARGET_POSITION_ID:
92
      if (frame->DLC == 8) {
93
        // Robot target position [x] = µm, [f_z] = µrad, [t] = ms
94
        int32_t robotPositionX = (frame->data8[0] << 8 | frame->data8[1] << 16 | frame->data8[2] << 24);
95
        int32_t robotPositionF_Z = (frame->data8[3] << 8 | frame->data8[4] << 16 | frame->data8[5] << 24);
96
        uint16_t targetTimeMilliSeconds = (frame->data8[6] | frame->data8[7] << 8);
97
        //chprintf((BaseSequentialStream*) &SD1, "\nx=%d\nf_z=%d\nt=%d", robotPositionX, robotPositionF_Z, targetTimeMilliSeconds);
98
        global.distcontrol.setTargetPosition(robotPositionX, robotPositionF_Z, targetTimeMilliSeconds);
99
        return RDY_OK;
100
      }
101
      break;
102 c76baf23 Georg Alberding
    case CAN::SET_LINE_FOLLOW_SPEED:
103 9c46b728 galberding
      if (frame->DLC == 8) {
104
        uint8_t speedForward    = frame->data8[0];
105
        uint8_t speedSoftLeft0  = frame->data8[1];
106
        uint8_t speedSoftLeft1  = frame->data8[2];
107
        uint8_t speedHardLeft0  = frame->data8[3];
108
        uint8_t speedHardLeft1  = frame->data8[4];
109
        global.rpmForward[0] = speedForward;
110
        global.rpmForward[1] = speedForward;
111
        global.rpmSoftLeft[0] = speedSoftLeft0;
112
        global.rpmSoftLeft[1] = speedSoftLeft1;
113
        global.rpmHardLeft[0] = speedHardLeft0;
114
        global.rpmHardLeft[1] = speedHardLeft1;
115
        global.rpmSoftRight[0] = global.rpmSoftLeft[1];
116
        global.rpmSoftRight[1] = global.rpmSoftLeft[0];
117
        global.rpmHardRight[0] = global.rpmHardLeft[1];
118
        global.rpmHardRight[1] = global.rpmHardLeft[0];
119
        return RDY_OK;
120
      }
121
      break;
122 d607fcef galberding
    case CAN::SET_LINE_FOLLOW_MSG:
123 8c99e03a galberding
      // chprintf((BaseSequentialStream*) &SD1, "Received Strategy!\n");
124 9c46b728 galberding
      if (frame->DLC == 1) {
125
        global.lfStrategy = frame->data8[0];
126 d607fcef galberding
        global.msgReceived = true;
127 8c99e03a galberding
        // return RDY_OK;
128 9c46b728 galberding
      }
129
      break;
130 58fe0e0b Thomas Schöpping
    case CAN::SET_KINEMATIC_CONST_ID:
131
      if (frame->DLC == 8) {
132
/*        // Set (but do not store) Ed
133
        global.motorcontrol.setWheelDiameterCorrectionFactor(static_cast<float>(frame->data32[0]), false);
134
        // Set (but do not store) Eb
135
        global.motorcontrol.setActualWheelBaseDistance(static_cast<float>(frame->data32[1]), false);
136
        return RDY_OK;*/
137
        // Set (but do not store) Ed
138
        uint32_t ed_int = static_cast<uint32_t>(frame->data32[0]);
139
        float ed_float = static_cast<float>(ed_int)/1000000.0;
140
        global.motorcontrol.setWheelDiameterCorrectionFactor(ed_float, false);
141
        // Set (but do not store) Eb
142
        uint32_t eb_int = static_cast<uint32_t>(frame->data32[1]);
143
        float eb_float = static_cast<float>(eb_int)/1000000.0;
144
        global.motorcontrol.setActualWheelBaseDistance(eb_float, false);
145
        //chprintf((BaseSequentialStream*) &SD1, "Edi=%i, Edf=%f, Ebi=%i, Ebf=%f\n", ed_int, ed_float, eb_int, eb_float);
146
        return RDY_OK;
147
      }
148
      break;
149
150
    case CAN::POWER_STATUS_ID:
151
      if (frame->DLC == 6) {
152
        // The power status is evaluated by inherited ControllerAreaNetworkRx object, but depending on the flags the power path controller needs to enabled or disabled.
153 8c99e03a galberding
154 58fe0e0b Thomas Schöpping
        types::power_status::ChargingState charging_flags;
155
        charging_flags.value = frame->data8[0];
156
        global.ltc4412.enable(charging_flags.content.diwheeldrive_enable_power_path);
157 8c99e03a galberding
        
158 58fe0e0b Thomas Schöpping
        // Do not return with RDY_OK, or the inherited ControllerAreaNetworkRx object would not evaluate the rest of this message.
159
      }
160
    break;
161
162
    default:
163
      break;
164
  }
165
  return -1;
166
}
167
168
msg_t DiWheelDrive::updateSensorVal() {
169
170
  // Update robot velocity values
171
  kinematic currentVelocity = global.motorcontrol.getCurrentVelocity();
172
  this->actualSpeed[0] = currentVelocity.x;
173
  this->actualSpeed[1] = currentVelocity.w_z;
174
175
  // Update odometry values
176
  this->robotPosition = global.odometry.getPosition();
177
178
  // Update proximity values
179
  for (int idx = 0; idx < 4; ++idx)
180
    this->proximityFloorValue[idx] = global.vcnl4020[idx].getProximityScaledWoOffset();
181
182 b4885314 Thomas Schöpping
  // Update magnetometer values
183
  for (uint8_t axis = 0; axis < 3; ++axis) {
184
    this->magnetometerValue[axis] = global.hmc5883l.getMagnetizationGauss(axis);
185
  }
186
187
  // Update gyroscope values
188
  for (uint8_t axis = 0; axis < 3; ++axis) {
189
    this->gyroscopeValue[axis] = global.l3g4200d.getAngularRate(axis);
190
  }
191
192 58fe0e0b Thomas Schöpping
  return 0;
193
}
194
195 8c99e03a galberding
void DiWheelDrive::requestCharging(uint8_t power){
196
  CANTxFrame frame;
197
  frame.SID = 0;
198
  this->encodeDeviceId(&frame, CAN::REQUEST_CHARGING_OVER_PIN);
199
  frame.data8[0] = power;
200
  frame.DLC = 1;
201
  this->transmitMessage(&frame);
202
}
203
204 58fe0e0b Thomas Schöpping
void DiWheelDrive::periodicBroadcast() {
205
  CANTxFrame frame;
206
  frame.SID = 0;
207
208
  // Send the velocites µm/s of the x axis and µrad/s around z axis: start
209
  this->encodeDeviceId(&frame, CAN::ACTUAL_SPEED_ID);
210
  frame.data32[0] = this->actualSpeed[0];
211
  frame.data32[1] = this->actualSpeed[1];
212
  frame.DLC = 8;
213
  this->transmitMessage(&frame);
214 8c99e03a galberding
  // Send Message for either activate or deactivate it
215
216
217
218
 
219 58fe0e0b Thomas Schöpping
220
  // Send the valocites µm/s of the x axis and µrad/s around z axis: end
221
  // Send the odometry: start
222 b4885314 Thomas Schöpping
  BaseThread::sleep(US2ST(10)); // Use to sleep for 10 CAN cycle (@1Mbit), otherwise the cognition-board might not receive all messagee
223 58fe0e0b Thomas Schöpping
  // Set the frame id
224
  frame.SID = 0;
225
  this->encodeDeviceId(&frame, CAN::ODOMETRY_ID);
226
  // Cut of the first byte, which precission is not needed
227
  int32_t x_mm = (this->robotPosition.x >> 8);
228
  int32_t y_mm = (this->robotPosition.y >> 8);
229
  int16_t f_z_mrad = int16_t(this->robotPosition.f_z >> 8 );
230
  // Copy the data structure
231
  memcpy((uint8_t *)&(frame.data8[0]), (uint8_t *)&x_mm, 3);
232
  memcpy((uint8_t *)&(frame.data8[3]), (uint8_t *)&y_mm, 3);
233
  memcpy((uint8_t *)&(frame.data8[6]), (uint8_t *)&f_z_mrad, 2);
234
  frame.DLC = 8;
235
  this->transmitMessage(&frame);
236
237
  // Send the odometry: end
238
  // Send the proximity values of the floor: start
239 b4885314 Thomas Schöpping
  BaseThread::sleep(US2ST(10)); // Use to sleep for 10 CAN cycle (@1Mbit), otherwise the cognition-board might not receive all messagee
240 58fe0e0b Thomas Schöpping
  // Set the frame id
241
  frame.SID = 0;
242
  this->encodeDeviceId(&frame, CAN::PROXIMITY_FLOOR_ID);
243
  frame.data16[0] = this->proximityFloorValue[0];
244
  frame.data16[1] = this->proximityFloorValue[1];
245
  frame.data16[2] = this->proximityFloorValue[2];
246
  frame.data16[3] = this->proximityFloorValue[3];
247
  frame.DLC = 8;
248
  this->transmitMessage(&frame);
249
250 b4885314 Thomas Schöpping
  // Send the magnetometer data
251
  for (uint8_t axis = 0; axis < 3; ++axis) {
252
    frame.SID = 0;
253
    this->encodeDeviceId(&frame, CAN::MAGNETOMETER_X_ID + axis); // Y- and Z-axis have according IDs
254
    frame.data32[0] = this->magnetometerValue[axis];
255
    frame.DLC = 4;
256
    this->transmitMessage(&frame);
257
  }
258
259
  // Send gyroscope data
260
  frame.SID = 0;
261
  this->encodeDeviceId(&frame, CAN::GYROSCOPE_ID);
262
  frame.data16[0] = this->gyroscopeValue[0];
263
  frame.data16[1] = this->gyroscopeValue[1];
264
  frame.data16[2] = this->gyroscopeValue[2];
265
  frame.DLC = 6;
266
  this->transmitMessage(&frame);
267
268 d607fcef galberding
  
269
270 58fe0e0b Thomas Schöpping
  // Send the board ID (board ID of DiWheelDrive = Robot ID)
271
  if (this->bcCounter % 10 == 0) {
272
    frame.SID = 0;
273
    this->encodeDeviceId(&frame, CAN::ROBOT_ID);
274
    frame.data8[0] = this->robotId;
275
    frame.DLC = 1;
276
    this->transmitMessage(&frame);
277
  }
278
279
  ++this->bcCounter;
280
}
281
282
void DiWheelDrive::calibrate() {
283
  // Stop sending and receiving of values to indicate the calibration phase
284
//   eventTimerEvtSource->unregister(&this->eventTimerEvtListener);
285
//   rxFullCanEvtSource->unregister(&this->rxFullCanEvtListener);
286
287
  this->calibrateProximityFloorValues();
288
289
  // Start sending and receving of values
290
//   eventTimerEvtSource->registerOne(&this->eventTimerEvtListener, CAN::PERIODIC_TIMER_ID);
291
//   rxFullCanEvtSource->registerOne(&this->rxFullCanEvtListener, CAN::RECEIVED_ID);
292
293
}
294
295
void DiWheelDrive::calibrateProximityFloorValues() {
296
297
  uint16_t buffer;
298
  for (uint8_t idx = 0; idx < 4; ++idx) {
299
    global.vcnl4020[idx].calibrate();
300
    buffer = global.vcnl4020[idx].getProximityOffset();
301
    global.memory.setVcnl4020Offset(buffer,idx);
302
  }
303
304
}
305
306
ThreadReference DiWheelDrive::start(tprio_t PRIO) {
307
  // set the robot ID as the board ID, which is read from the memory
308
  if (global.memory.getBoardId(&this->robotId) != fileSystemIo::FileSystemIoBase::OK) {
309
    this->robotId = 0;
310
  }
311
312
  this->ControllerAreaNetworkRx::start(PRIO + 1);
313
  this->ControllerAreaNetworkTx::start(PRIO);
314
  return NULL;
315
}
316
317
msg_t
318
DiWheelDrive::terminate(void) {
319
  msg_t ret = RDY_OK;
320
321
  this->ControllerAreaNetworkTx::requestTerminate();
322
  ret |= this->ControllerAreaNetworkTx::wait();
323
  this->ControllerAreaNetworkRx::requestTerminate();
324
  ret |= this->ControllerAreaNetworkRx::wait();
325
326
  return ret;
327
}