5 * @brief CAN-ORTE bridge
7 * Copyright: (c) 2008 CTU Dragons
8 * CTU FEE - Department of Control Engineering
19 #include <sys/socket.h>
20 #include <sys/ioctl.h>
27 #include <can_msg_masks.h>
28 #include <can_msg_def.h>
32 #include <roboorte_robottype.h>
33 #include <can_msg_masks.h>
38 if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
39 perror("cand: unable to create a socket");
43 can_addr.can_family = AF_CAN;
44 std::strcpy(can_ifreq.ifr_name, "can0");
46 if (ioctl(sock, SIOCGIFINDEX, &can_ifreq) < 0) {
47 perror("cand: SIOCGIFINDEX");
51 can_addr.can_ifindex = can_ifreq.ifr_ifindex;
53 if (!can_addr.can_ifindex) {
54 perror("cand: invalid socket interface");
58 if (bind(sock, (struct sockaddr *)&can_addr, sizeof(can_addr)) < 0) {
59 perror("cand: unable to bind");
66 int set_pwr_ctrl(struct robottype_orte_data *orte_data)
69 if(orte_data->pwr_ctrl.voltage33)
70 data |= CAN_PWR_CTRL_33_ON;
72 data |= CAN_PWR_CTRL_33_OFF;
74 if(orte_data->pwr_ctrl.voltage50)
75 data |= CAN_PWR_CTRL_50_ON;
77 data |= CAN_PWR_CTRL_50_OFF;
79 if(orte_data->pwr_ctrl.voltage80)
80 data |= CAN_PWR_CTRL_80_ON;
82 data |= CAN_PWR_CTRL_80_OFF;
84 can_send(CAN_PWR, 1, &data);
89 int set_pwr_alert(struct robottype_orte_data *orte_data)
92 data = orte_data->pwr_alert.value;
94 can_send(CAN_PWR_ALERT, 1, &data);
99 int send_can_msg(struct robottype_orte_data *orte_data)
103 data[0] = orte_data->can_msg.data1;
104 data[1] = orte_data->can_msg.data2;
105 data[2] = orte_data->can_msg.data3;
106 data[3] = orte_data->can_msg.data4;
107 data[4] = orte_data->can_msg.data5;
108 data[5] = orte_data->can_msg.data6;
109 data[6] = orte_data->can_msg.data7;
110 data[7] = orte_data->can_msg.data8;
112 can_send(orte_data->can_msg.id, orte_data->can_msg.len, data);
115 int set_motor_speed(struct robottype_orte_data *orte_data)
117 unsigned char data[4];
119 data[0] = orte_data->motion_speed.right >> 8;
120 data[1] = orte_data->motion_speed.right & 0xff;
121 data[2] = orte_data->motion_speed.left >> 8;
122 data[3] = orte_data->motion_speed.left & 0xff;
123 can_send(CAN_MOTION_CMD, 4, data);
129 * Sends #CAN_LIFT message.
131 * - data[1] = orte_data->lift.pos & 0xFF; // lower byte
132 * - data[0] = orte_data->lift.pos >> 8; // upper byte
134 int set_lift(struct robottype_orte_data *orte_data)
136 unsigned char data[2];
138 data[0] = orte_data->lift.pos >> 8;
139 data[1] = orte_data->lift.pos & 0xFF;
140 can_send(CAN_LIFT, sizeof(data), data);
146 * FIXME: this function is temporary, just for time LPCs are not ready
147 * Sends #CAN_PICKER message.
149 * - data[0] = orte_data->picker.rightchela;
150 * - data[1] = orte_data->picker.leftchela;
151 * - data[2] = orte_data->picker.leftbelt;
152 * - data[3] = orte_data->picker.rightbelt;
153 * - data[4] = orte_data->picker.timeout;
155 int set_picker(struct robottype_orte_data *orte_data)
157 unsigned char data[5];
159 data[0] = orte_data->picker.rightchela;
160 data[1] = orte_data->picker.leftchela;
161 data[2] = orte_data->picker.leftbelt;
162 data[3] = orte_data->picker.rightbelt;
163 data[4] = orte_data->picker.timeout;
164 can_send(CAN_PICKER, sizeof(data), data);
170 * Sends #CAN_SERVO message.
172 * - data[1] = orte_data->chelas.left;
173 * - data[0] = orte_data->chelas.right;
175 int set_chelas(struct robottype_orte_data *orte_data)
177 unsigned char data[2];
179 data[0] = orte_data->chelas.left;
180 data[1] = orte_data->chelas.right;
181 can_send(CAN_SERVO, sizeof(data), data);
187 * Sends #CAN_DRIVES message.
189 * - data[1] = orte_data->belts.left;
190 * - data[0] = orte_data->belts.right;
192 int set_belts(struct robottype_orte_data *orte_data)
194 unsigned char data[2];
196 data[0] = orte_data->belts.left;
197 data[1] = orte_data->belts.right;
198 can_send(CAN_DRIVES, sizeof(data), data);
204 * Sends #CAN_HOLDER message.
206 * - data[0] = orte_data->holder.pos;
208 int set_holder(struct robottype_orte_data *orte_data)
210 unsigned char data[2];
212 data[0] = orte_data->holder.pos;
213 can_send(CAN_HOLDER, sizeof(data), data);
219 * Sends #CAN_PUSHER message.
221 * - data[1] = orte_data->pusher.pos & 0xFF; // lower byte
222 * - data[0] = orte_data->pusher.pos >> 8; // upper byte
224 int set_pusher(struct robottype_orte_data *orte_data)
226 unsigned char data[2];
228 data[0] = orte_data->pusher.pos >> 8;
229 data[1] = orte_data->pusher.pos & 0xFF;
230 can_send(CAN_PUSHER, sizeof(data), data);
236 int can_send(canid_t id, unsigned char length, unsigned char *data)
238 struct can_frame frame;
242 frame.can_dlc = length;
244 for(int i=0; i<length; i++)
245 frame.data[i] = data[i];
247 if ((size = write(sock, &frame, sizeof(struct can_frame))) < 0) {
248 perror("cand: can send: write()");
250 } else if (size < sizeof(struct can_frame)) {
251 perror("cand: can send: incomplete CAN frame\n");
259 * Parse frame ID and react as required
261 int cand_parse_frame(struct robottype_orte_data *orte, struct can_frame frame)
268 unsigned short *las_meas;
269 int las_mi, las_di, las_bcnt;
270 static unsigned short prev_meas;
273 switch(frame.can_id) {
274 /* voltage measurements from power board */
276 /* robot commands (start, ..) */
278 orte->robot_cmd.start = frame.data[0];
279 orte->robot_cmd.stop = frame.data[1];
280 ORTEPublicationSend(orte->publication_robot_cmd);
283 /* global sampling period -- time trigger */
285 orte->corr_trig.seq = frame.data[0];
286 ORTEPublicationSend(orte->publication_corr_trig);
289 /* distances measured by ULoPoS */
291 orte->corr_distances.t1 = (frame.data[1]<<8)|(frame.data[0]);
292 orte->corr_distances.t2 = (frame.data[3]<<8)|(frame.data[2]);
293 orte->corr_distances.t3 = (frame.data[5]<<8)|(frame.data[4]);
294 ORTEPublicationSend(orte->publication_corr_distances);
297 /* positioning by odometry */
298 case CAN_MOTION_ODOMETRY_SIMPLE:
299 orte->motion_irc.right =
300 ((frame.data[0]<<24)|(frame.data[1]<<16)|
301 (frame.data[2]<<8)|(frame.data[3]));
302 orte->motion_irc.left =
303 ((frame.data[4]<<24)|(frame.data[5]<<16)|
304 (frame.data[6]<<8)|(frame.data[7]));
305 ORTEPublicationSend(orte->publication_motion_irc);
309 case CAN_MOTION_STATUS:
310 orte->motion_status.err_left =
311 (frame.data[0]<<8)|(frame.data[1]);
312 orte->motion_status.err_right =
313 (frame.data[2]<<8)|(frame.data[3]);
314 if(++status_cnt == 5) {
315 ORTEPublicationSend(orte->publication_motion_status);
320 double volt33, voltBAT;
321 voltBAT = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
322 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
323 volt33 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
324 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
325 orte->pwr_voltage.voltage33 = volt33;
326 orte->pwr_voltage.voltageBAT = voltBAT;
330 double volt80, volt50;
331 volt50 = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
332 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
333 volt80 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
334 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
335 orte->pwr_voltage.voltage80 = volt80;
336 orte->pwr_voltage.voltage50 = volt50;
338 ORTEPublicationSend(orte->publication_pwr_voltage);
342 // ORTEPublicationSend(orte->publication_sharps);
347 orte->cmu.color = frame.data[0];
348 ORTEPublicationSend(orte->publication_cmu);
352 // printf("received CAN msg with unknown id: %x\n",frame.can_id);
357 void rcv_pwr_ctrl_cb (const ORTERecvInfo *info, void *vinstance,
358 void *recvCallBackParam)
360 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
362 switch (info->status) {
364 set_pwr_ctrl(orte_data);
367 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
372 void rcv_can_msg_cb (const ORTERecvInfo *info, void *vinstance,
373 void *recvCallBackParam)
375 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
377 switch (info->status) {
379 send_can_msg(orte_data);
382 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
386 void rcv_pwr_alert_cb (const ORTERecvInfo *info, void *vinstance,
387 void *recvCallBackParam)
390 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
391 switch (info->status) {
393 set_pwr_alert(orte_data);
396 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
401 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
402 void *recvCallBackParam)
404 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
406 switch (info->status) {
408 /* reversing motion direction, as it is different, than last year */
409 orte_data->motion_speed.left *= -1;
410 orte_data->motion_speed.right *=-1;
411 set_motor_speed(orte_data);
412 /*printf("motor cmd received\n");*/
415 printf("motor cmd deadline occurred, stopping motors\n");
416 orte_data->motion_speed.left = 0;
417 orte_data->motion_speed.right = 0;
418 set_motor_speed(orte_data);
423 void rcv_lift_cb (const ORTERecvInfo *info, void *vinstance,
424 void *recvCallBackParam)
426 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
428 switch (info->status) {
433 // printf("ORTE deadline occurred - lift receive\n");
438 void rcv_picker_cb (const ORTERecvInfo *info, void *vinstance,
439 void *recvCallBackParam)
441 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
443 switch (info->status) {
445 set_picker(orte_data);
448 // printf("ORTE deadline occurred - chelas receive\n");
453 void rcv_chelas_cb (const ORTERecvInfo *info, void *vinstance,
454 void *recvCallBackParam)
456 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
458 switch (info->status) {
460 set_chelas(orte_data);
463 // printf("ORTE deadline occurred - chelas receive\n");
468 void rcv_belts_cb (const ORTERecvInfo *info, void *vinstance,
469 void *recvCallBackParam)
471 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
473 switch (info->status) {
475 set_belts(orte_data);
478 // printf("ORTE deadline occurred - belts receive\n");
483 void rcv_holder_cb (const ORTERecvInfo *info, void *vinstance,
484 void *recvCallBackParam)
486 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
488 switch (info->status) {
490 set_holder(orte_data);
493 // printf("ORTE deadline occurred - holder receive\n");
498 void rcv_pusher_cb (const ORTERecvInfo *info, void *vinstance,
499 void *recvCallBackParam)
501 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
503 switch (info->status) {
505 set_pusher(orte_data);
508 // printf("ORTE deadline occurred - pusher receive\n");
513 int main(int argc, char *argv[])
516 struct timeval timeout;
521 struct robottype_orte_data orte;
522 struct can_frame frame;
524 if (cand_init() < 0) {
525 printf("cand: init failed\n");
528 printf("cand: init OK\n");
533 /* orte initialization */
534 if(robottype_roboorte_init(&orte)) {
535 printf("Roboorte initialization failed! Exiting...\n");
539 /* creating publishers */
540 robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
541 robottype_publisher_motion_status_create(&orte, NULL, NULL);
542 robottype_publisher_motion_irc_create(&orte, NULL, NULL);
543 robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
544 robottype_publisher_cmu_create(&orte, NULL, NULL);
546 /* creating subscribers */
547 robottype_subscriber_pwr_ctrl_create(&orte, rcv_pwr_ctrl_cb, &orte);
548 robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
549 robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
550 robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
551 robottype_subscriber_lift_create(&orte, rcv_lift_cb, &orte);
552 robottype_subscriber_chelas_create(&orte, rcv_chelas_cb, &orte);
553 robottype_subscriber_belts_create(&orte, rcv_belts_cb, &orte);
554 robottype_subscriber_picker_create(&orte, rcv_picker_cb, &orte); // FIXME: temporary (LPCs not ready)
555 robottype_subscriber_holder_create(&orte, rcv_holder_cb, &orte);
556 robottype_subscriber_pusher_create(&orte, rcv_pusher_cb, &orte);
560 FD_ZERO(&read_fd_set);
561 FD_SET(sock, &read_fd_set);
563 timeout.tv_usec = 10000;
565 ret = select(FD_SETSIZE, &read_fd_set, NULL, NULL, &timeout);
567 perror("cand: select() error");
571 /* timeout expired, nothing to be done */
575 if (!FD_ISSET(sock, &read_fd_set))
578 /* read data from SocketCAN */
579 size = read(sock, &frame, sizeof(struct can_frame));
582 cand_parse_frame(&orte, frame);