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)
101 can_send(orte_data->can_msg.id, orte_data->can_msg.len, orte_data->can_msg.data);
104 int set_motor_speed(struct robottype_orte_data *orte_data)
106 unsigned char data[4];
108 data[0] = orte_data->motion_speed.right >> 8;
109 data[1] = orte_data->motion_speed.right & 0xff;
110 data[2] = orte_data->motion_speed.left >> 8;
111 data[3] = orte_data->motion_speed.left & 0xff;
112 can_send(CAN_MOTION_CMD, 4, data);
118 * Sends #CAN_LIFT message.
120 * - data[1] = orte_data->lift.pos & 0xFF; // lower byte
121 * - data[0] = orte_data->lift.pos >> 8; // upper byte
123 int set_lift(struct robottype_orte_data *orte_data)
125 unsigned char data[2];
127 data[0] = orte_data->lift.pos >> 8;
128 data[1] = orte_data->lift.pos & 0xFF;
129 can_send(CAN_LIFT, sizeof(data), data);
135 * Sends #CAN_CHELAE message.
137 * - data[1] = orte_data->chelae.left;
138 * - data[0] = orte_data->chelae.right;
140 int set_chelae(struct robottype_orte_data *orte_data)
142 unsigned char data[2];
144 data[0] = orte_data->chelae.left;
145 data[1] = orte_data->chelae.right;
146 can_send(CAN_CHELAE, sizeof(data), data);
152 * Sends #CAN_BELTS message.
154 * - data[1] = orte_data->belts.left;
155 * - data[0] = orte_data->belts.right;
157 int set_belts(struct robottype_orte_data *orte_data)
159 unsigned char data[2];
161 data[0] = orte_data->belts.left;
162 data[1] = orte_data->belts.right;
163 can_send(CAN_BELTS, sizeof(data), data);
169 * Sends #CAN_HOLDER message.
171 * - data[0] = orte_data->holder.pos;
173 int set_holder(struct robottype_orte_data *orte_data)
175 unsigned char data = orte_data->holder.pos;
176 can_send(CAN_HOLDER, sizeof(data), &data);
182 * Sends #CAN_PUSHER message.
184 * - data[1] = orte_data->pusher.pos & 0xFF; // lower byte
185 * - data[0] = orte_data->pusher.pos >> 8; // upper byte
187 int set_pusher(struct robottype_orte_data *orte_data)
189 unsigned char data[2];
191 data[0] = orte_data->pusher.pos >> 8;
192 data[1] = orte_data->pusher.pos & 0xFF;
193 can_send(CAN_PUSHER, sizeof(data), data);
199 * Sends #CAN_HOKUYO_PITCH message.
201 * - data = orte_data->pusher.pos
203 int set_hokuyo_pitch(struct robottype_orte_data *orte_data)
205 unsigned char data = orte_data->hokuyo_pitch.angle;
207 can_send(CAN_HOKUYO_PITCH, sizeof(data), &data);
212 int can_send(canid_t id, unsigned char length, unsigned char *data)
214 struct can_frame frame;
218 frame.can_dlc = length;
220 for(int i=0; i<length; i++)
221 frame.data[i] = data[i];
223 if ((size = write(sock, &frame, sizeof(struct can_frame))) < 0) {
224 perror("cand: can send: write()");
226 } else if (size < sizeof(struct can_frame)) {
227 perror("cand: can send: incomplete CAN frame\n");
235 * Parse frame ID and react as required
237 int cand_parse_frame(struct robottype_orte_data *orte, struct can_frame frame)
244 unsigned short *las_meas;
245 int las_mi, las_di, las_bcnt;
246 static unsigned short prev_meas;
249 switch(frame.can_id) {
250 /* voltage measurements from power board */
252 /* robot commands (start, ..) */
254 orte->robot_cmd.start = frame.data[0];
255 orte->robot_cmd.stop = frame.data[1];
256 ORTEPublicationSend(orte->publication_robot_cmd);
259 /* global sampling period -- time trigger */
261 orte->corr_trig.seq = frame.data[0];
262 ORTEPublicationSend(orte->publication_corr_trig);
265 /* distances measured by ULoPoS */
267 orte->corr_distances.t1 = (frame.data[1]<<8)|(frame.data[0]);
268 orte->corr_distances.t2 = (frame.data[3]<<8)|(frame.data[2]);
269 orte->corr_distances.t3 = (frame.data[5]<<8)|(frame.data[4]);
270 ORTEPublicationSend(orte->publication_corr_distances);
273 /* positioning by odometry */
274 case CAN_MOTION_ODOMETRY_SIMPLE:
275 orte->motion_irc.right =
276 ((frame.data[0]<<24)|
279 orte->motion_irc.left =
280 ((frame.data[3]<<24)|
283 orte->motion_irc.seq = frame.data[6];
284 ORTEPublicationSend(orte->publication_motion_irc);
288 case CAN_MOTION_STATUS:
289 orte->motion_status.err_left =
290 (frame.data[0]<<8)|(frame.data[1]);
291 orte->motion_status.err_right =
292 (frame.data[2]<<8)|(frame.data[3]);
293 if(++status_cnt == 5) {
294 ORTEPublicationSend(orte->publication_motion_status);
299 double volt33, voltBAT;
300 voltBAT = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
301 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
302 volt33 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
303 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
304 orte->pwr_voltage.voltage33 = volt33;
305 orte->pwr_voltage.voltageBAT = voltBAT;
309 double volt80, volt50;
310 volt50 = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
311 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
312 volt80 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
313 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
314 orte->pwr_voltage.voltage80 = volt80;
315 orte->pwr_voltage.voltage50 = volt50;
317 ORTEPublicationSend(orte->publication_pwr_voltage);
320 /* data from the sharp sensor measuring puck to sensor distance */
321 case CAN_ADC_1: /* data from the sharp sensor measuring distance of the puck (column element) */
322 orte->puck_distance.distance = puckSharp_ir2mm(frame.data[0]<<8 | frame.data[1])/1000.0;
323 ORTEPublicationSend(orte->publication_puck_distance);
325 /* lift & pusher status, their position and status bit */
327 /* printf("lift position: %d \n", frame.data[1]<<8 | frame.data[2]); */
328 orte->actuator_status.pusher_pos = frame.data[0]<<8 | frame.data[1];
329 orte->actuator_status.lift_pos = frame.data[2]<<8 | frame.data[3];
330 orte->actuator_status.status = frame.data[4];
331 ORTEPublicationSend(orte->publication_actuator_status);
335 orte->puck_inside.status = frame.data[0];
336 ORTEPublicationSend(orte->publication_puck_inside);
340 // printf("received CAN msg with unknown id: %x\n",frame.can_id);
345 void rcv_pwr_ctrl_cb (const ORTERecvInfo *info, void *vinstance,
346 void *recvCallBackParam)
348 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
350 switch (info->status) {
352 set_pwr_ctrl(orte_data);
355 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
360 void rcv_can_msg_cb (const ORTERecvInfo *info, void *vinstance,
361 void *recvCallBackParam)
363 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
365 switch (info->status) {
367 send_can_msg(orte_data);
370 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
374 void rcv_pwr_alert_cb (const ORTERecvInfo *info, void *vinstance,
375 void *recvCallBackParam)
378 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
379 switch (info->status) {
381 set_pwr_alert(orte_data);
384 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
389 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
390 void *recvCallBackParam)
392 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
394 switch (info->status) {
396 /* reversing motion direction, as it is different, than last year */
397 orte_data->motion_speed.left *= -1;
398 orte_data->motion_speed.right *=-1;
399 set_motor_speed(orte_data);
400 /*printf("motor cmd received\n");*/
403 //printf("motor cmd deadline occurred, stopping motors\n");
404 orte_data->motion_speed.left = 0;
405 orte_data->motion_speed.right = 0;
406 set_motor_speed(orte_data);
411 void rcv_lift_cb (const ORTERecvInfo *info, void *vinstance,
412 void *recvCallBackParam)
414 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
416 switch (info->status) {
421 // printf("ORTE deadline occurred - lift receive\n");
426 void rcv_chelae_cb (const ORTERecvInfo *info, void *vinstance,
427 void *recvCallBackParam)
429 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
431 switch (info->status) {
433 set_chelae(orte_data);
436 // printf("ORTE deadline occurred - chelae receive\n");
441 void rcv_belts_cb (const ORTERecvInfo *info, void *vinstance,
442 void *recvCallBackParam)
444 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
446 switch (info->status) {
448 set_belts(orte_data);
451 // printf("ORTE deadline occurred - belts receive\n");
456 void rcv_holder_cb (const ORTERecvInfo *info, void *vinstance,
457 void *recvCallBackParam)
459 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
461 switch (info->status) {
463 set_holder(orte_data);
466 // printf("ORTE deadline occurred - holder receive\n");
471 void rcv_pusher_cb (const ORTERecvInfo *info, void *vinstance,
472 void *recvCallBackParam)
474 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
476 switch (info->status) {
478 set_pusher(orte_data);
481 // printf("ORTE deadline occurred - pusher receive\n");
486 void rcv_hokuyo_pitch_cb (const ORTERecvInfo *info, void *vinstance,
487 void *recvCallBackParam)
489 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
491 switch (info->status) {
493 set_hokuyo_pitch(orte_data);
496 // printf("ORTE deadline occurred - hokuyo pitch receive\n");
502 int main(int argc, char *argv[])
505 struct timeval timeout;
510 struct robottype_orte_data orte;
511 struct can_frame frame;
513 if (cand_init() < 0) {
514 printf("cand: init failed\n");
517 printf("cand: init OK\n");
522 /* orte initialization */
523 if(robottype_roboorte_init(&orte)) {
524 printf("Roboorte initialization failed! Exiting...\n");
528 printf("Roboorte OK\n");
530 /* creating publishers */
531 robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
532 robottype_publisher_motion_status_create(&orte, NULL, NULL);
533 robottype_publisher_motion_irc_create(&orte, NULL, NULL);
534 robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
535 robottype_publisher_corr_trig_create(&orte, NULL, NULL);
536 robottype_publisher_corr_distances_create(&orte, NULL, NULL);
537 robottype_publisher_puck_distance_create(&orte, NULL, NULL);
538 robottype_publisher_actuator_status_create(&orte, NULL, NULL);
539 robottype_publisher_puck_inside_create(&orte, NULL, NULL);
540 printf("Publishers OK\n");
542 /* creating subscribers */
543 robottype_subscriber_pwr_ctrl_create(&orte, rcv_pwr_ctrl_cb, &orte);
544 robottype_subscriber_pwr_alert_create(&orte, rcv_pwr_alert_cb, &orte);
545 robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
546 robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
547 robottype_subscriber_lift_create(&orte, rcv_lift_cb, &orte);
548 robottype_subscriber_chelae_create(&orte, rcv_chelae_cb, &orte);
549 robottype_subscriber_belts_create(&orte, rcv_belts_cb, &orte);
550 robottype_subscriber_holder_create(&orte, rcv_holder_cb, &orte);
551 robottype_subscriber_pusher_create(&orte, rcv_pusher_cb, &orte);
552 robottype_subscriber_hokuyo_pitch_create(&orte, rcv_hokuyo_pitch_cb, &orte);
554 printf("subscribers OK\n");
558 FD_ZERO(&read_fd_set);
559 FD_SET(sock, &read_fd_set);
561 timeout.tv_usec = 10000;
563 ret = select(FD_SETSIZE, &read_fd_set, NULL, NULL, &timeout);
565 perror("cand: select() error");
569 /* timeout expired, nothing to be done */
573 if (!FD_ISSET(sock, &read_fd_set))
576 /* read data from SocketCAN */
577 size = read(sock, &frame, sizeof(struct can_frame));
580 cand_parse_frame(&orte, frame);