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>
28 #include <can_msg_masks.h>
29 #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 send_can_msg(struct robottype_orte_data *orte_data)
91 return can_send(orte_data->can_msg.id, orte_data->can_msg.len, orte_data->can_msg.data);
94 int set_motor_speed(struct robottype_orte_data *orte_data)
96 unsigned char data[4];
98 data[0] = orte_data->motion_speed.right >> 8;
99 data[1] = orte_data->motion_speed.right & 0xff;
100 data[2] = orte_data->motion_speed.left >> 8;
101 data[3] = orte_data->motion_speed.left & 0xff;
102 can_send(CAN_MOTION_CMD, 4, data);
107 int set_jaws_cmd(struct robottype_orte_data *orte_data)
109 unsigned char data[3];
111 data[0] = orte_data->jaws_cmd.req_pos.left >> 8;
112 data[1] = orte_data->jaws_cmd.req_pos.left & 0xff;
113 data[2] = orte_data->jaws_cmd.speed.left;
114 can_send(CAN_JAW_LEFT_CMD, 3, data);
116 data[0] = orte_data->jaws_cmd.req_pos.right >> 8;
117 data[1] = orte_data->jaws_cmd.req_pos.right & 0xff;
118 data[2] = orte_data->jaws_cmd.speed.right;
119 can_send(CAN_JAW_RIGHT_CMD, 3, data);
124 int set_lift_cmd(struct robottype_orte_data *orte_data)
126 unsigned char data[4];
128 data[0] = orte_data->lift_cmd.req_pos >> 8;
129 data[1] = orte_data->lift_cmd.req_pos & 0xff;
130 data[2] = orte_data->lift_cmd.speed;
131 data[3] = orte_data->lift_cmd.homing;
132 can_send(CAN_LIFT_CMD, 4, data);
137 int can_send(canid_t id, unsigned char length, unsigned char *data)
139 struct can_frame frame;
143 frame.can_dlc = length;
145 for(int i=0; i<length; i++)
146 frame.data[i] = data[i];
148 if ((size = write(sock, &frame, sizeof(struct can_frame))) < 0) {
149 perror("cand: can send: write()");
151 } else if (size < sizeof(struct can_frame)) {
152 perror("cand: can send: incomplete CAN frame\n");
160 * Parse frame ID and react as required
162 void cand_parse_frame(struct robottype_orte_data *orte, struct can_frame frame)
164 static int status_cnt = 0;
166 switch(frame.can_id) {
167 /* robot commands (start, ..) */
168 case CAN_CL_SENSOR_STATUS:
169 orte->cl_sensor_status.pattern_match = frame.data[0];
170 ORTEPublicationSend(orte->publication_cl_sensor_status);
172 case CAN_JAW_LEFT_STATUS:
173 orte->jaws_status.act_pos.left = (frame.data[0] << 8) | frame.data[1];
174 orte->jaws_status.response.left = (frame.data[2] << 8) | frame.data[3];
175 orte->jaws_status.flags.left = frame.data[4];
176 ORTEPublicationSend(orte->publication_jaws_status);
178 case CAN_JAW_RIGHT_STATUS:
179 orte->jaws_status.act_pos.right = (frame.data[0] << 8) | frame.data[1];
180 orte->jaws_status.response.right = (frame.data[2] << 8) | frame.data[3];
181 orte->jaws_status.flags.right = frame.data[4];
182 ORTEPublicationSend(orte->publication_jaws_status);
184 case CAN_LIFT_STATUS:
185 orte->lift_status.act_pos = (frame.data[0] << 8) | frame.data[1];
186 orte->lift_status.response = (frame.data[2] << 8) | frame.data[3];
187 orte->lift_status.flags = frame.data[4];
188 ORTEPublicationSend(orte->publication_lift_status);
191 orte->robot_cmd.start_condition = frame.data[0];
192 ORTEPublicationSend(orte->publication_robot_cmd);
194 case CAN_ROBOT_SWITCHES:
197 if (frame.data[0] & CAN_SWITCH_COLOR_0) tmp_color += 1;
198 if (frame.data[0] & CAN_SWITCH_COLOR_1) tmp_color += 2;
199 orte->robot_switches.team_color = tmp_color;
201 orte->robot_switches.team_color = frame.data[0] & (CAN_SWITCH_COLOR_0 + CAN_SWITCH_COLOR_1);
202 orte->robot_switches.strategy = (frame.data[0] & CAN_SWITCH_STRATEGY ? 1 : 0);
203 orte->robot_switches.home = (frame.data[0] & CAN_SWITCH_HOME ? 1 : 0);
204 ORTEPublicationSend(orte->publication_robot_switches);
206 case CAN_ROBOT_BUMPERS:
207 orte->robot_bumpers.bumper_left = (frame.data[0] & CAN_BUMPER_LEFT) ? 0 : 1;
208 orte->robot_bumpers.bumper_left_across = (frame.data[0] & CAN_BUMPER_LEFT_ACROSS) ? 0 : 1;
209 orte->robot_bumpers.bumper_right = (frame.data[0] & CAN_BUMPER_RIGHT) ? 0 : 1;
210 orte->robot_bumpers.bumper_right_across = (frame.data[0] & CAN_BUMPER_RIGHT_ACROSS) ? 0 : 1;
211 orte->robot_bumpers.bumper_rear_left = (frame.data[0] & CAN_BUMPER_REAR_LEFT) ? 0 : 1;
212 orte->robot_bumpers.bumper_rear_right = (frame.data[0] & CAN_BUMPER_REAR_RIGHT) ? 0 : 1;
213 ORTEPublicationSend(orte->publication_robot_bumpers);
216 /* positioning by independent odometry */
218 orte->odo_data.right =
219 ((frame.data[0]<<24)|
222 orte->odo_data.left =
223 ((frame.data[3]<<24)|
226 ORTEPublicationSend(orte->publication_odo_data);
229 /* positioning by odometry from motors*/
230 case CAN_MOTION_ODOMETRY_SIMPLE:
231 orte->motion_irc.left =
232 ((frame.data[0]<<24)|
235 orte->motion_irc.right =
236 ((frame.data[3]<<24)|
239 orte->motion_irc.seq = frame.data[6];
240 ORTEPublicationSend(orte->publication_motion_irc);
244 case CAN_MOTION_STATUS:
245 orte->motion_status.err_left =
246 (frame.data[0]<<8)|(frame.data[1]);
247 orte->motion_status.err_right =
248 (frame.data[2]<<8)|(frame.data[3]);
249 if(++status_cnt == 2) { // h8eurobot sends duplicite can messages
250 ORTEPublicationSend(orte->publication_motion_status);
254 /* voltage measurements from power board */
256 double volt33, voltBAT;
257 voltBAT = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
258 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
259 volt33 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
260 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
261 orte->pwr_voltage.voltage33 = volt33;
262 orte->pwr_voltage.voltageBAT = voltBAT;
266 double volt80, volt50;
267 volt50 = ((frame.data[0] << 24) | (frame.data[1] << 16) | \
268 (frame.data[2] << 8) | (frame.data[3]))/10000.0;
269 volt80 = ((frame.data[4] << 24) | (frame.data[5] << 16) | \
270 (frame.data[6] << 8) | (frame.data[7]))/10000.0;
271 orte->pwr_voltage.voltage80 = volt80;
272 orte->pwr_voltage.voltage50 = volt50;
274 ORTEPublicationSend(orte->publication_pwr_voltage);
279 orte->pwr_alert.alert_33 = (frame.data[0] & CAN_PWR_ALERT_33 ? 1 : 0);
280 orte->pwr_alert.alert_50 = (frame.data[0] & CAN_PWR_ALERT_50 ? 1 : 0);
281 orte->pwr_alert.alert_80 = (frame.data[0] & CAN_PWR_ALERT_80 ? 1 : 0);
282 orte->pwr_alert.bat_full = (frame.data[0] & CAN_PWR_BATT_FULL ? 1 : 0);
283 orte->pwr_alert.bat_mean = (frame.data[0] & CAN_PWR_BATT_MEAN ? 1 : 0);
284 orte->pwr_alert.bat_low = (frame.data[0] & CAN_PWR_BATT_LOW ? 1 : 0);
285 orte->pwr_alert.bat_critical = (frame.data[0] & CAN_PWR_BATT_CRITICAL ? 1 : 0);
287 ORTEPublicationSend(orte->publication_pwr_alert);
291 //FIXME: add logging here (Filip)
292 // printf("received CAN msg with unknown id: %x\n",frame.can_id);
297 void rcv_pwr_ctrl_cb (const ORTERecvInfo *info, void *vinstance,
298 void *recvCallBackParam)
300 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
302 switch (info->status) {
304 set_pwr_ctrl(orte_data);
307 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
312 void rcv_can_msg_cb (const ORTERecvInfo *info, void *vinstance,
313 void *recvCallBackParam)
315 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
317 switch (info->status) {
319 send_can_msg(orte_data);
322 //printf("ORTE deadline occurred - PWR_CTRL receive\n");
327 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
328 void *recvCallBackParam)
330 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
332 switch (info->status) {
334 /* reversing motion direction, as it is different, than last year */
335 orte_data->motion_speed.left *= 1;
336 orte_data->motion_speed.right *= 1;
337 set_motor_speed(orte_data);
338 /*printf("motor cmd received\n");*/
341 //printf("motor cmd deadline occurred, stopping motors\n");
342 orte_data->motion_speed.left = 0;
343 orte_data->motion_speed.right = 0;
344 set_motor_speed(orte_data);
349 void rcv_jaws_cmd_cb(const ORTERecvInfo *info, void *vinstance,
350 void *recvCallBackParam)
352 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
354 switch (info->status) {
356 set_jaws_cmd(orte_data);
363 void rcv_lift_cmd_cb(const ORTERecvInfo *info, void *vinstance,
364 void *recvCallBackParam)
366 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
368 switch (info->status) {
370 set_lift_cmd(orte_data);
377 void rcv_cl_sensor_cmd_cb(const ORTERecvInfo *info, void *vinstance,
378 void *recvCallBackParam)
380 struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
382 switch (info->status) {
384 unsigned char data[1];
385 data[0] = orte_data->cl_sensor_cmd.bank_nbr;
386 can_send(CAN_CL_SENSOR_CMD, 1, data);
393 int main(int argc, char *argv[])
398 struct robottype_orte_data orte;
399 struct can_frame frame;
401 if (cand_init() < 0) {
402 printf("cand: init failed\n");
405 printf("cand: init OK\n");
410 /* orte initialization */
411 if(robottype_roboorte_init(&orte)) {
412 printf("Roboorte initialization failed! Exiting...\n");
416 printf("Roboorte OK\n");
418 /* creating publishers */
419 robottype_publisher_pwr_voltage_create(&orte, NULL, NULL);
420 robottype_publisher_motion_status_create(&orte, NULL, NULL);
421 robottype_publisher_odo_data_create(&orte, NULL, NULL);
422 robottype_publisher_motion_irc_create(&orte, NULL, NULL);
423 robottype_publisher_robot_cmd_create(&orte, NULL, NULL);
424 robottype_publisher_robot_switches_create(&orte, NULL, NULL);
425 robottype_publisher_robot_bumpers_create(&orte, NULL, NULL);
426 robottype_publisher_jaws_status_create(&orte, NULL, NULL);
427 robottype_publisher_lift_status_create(&orte, NULL, NULL);
428 robottype_publisher_cl_sensor_status_create(&orte, NULL, NULL);
429 printf("Publishers OK\n");
431 /* creating subscribers */
432 robottype_subscriber_pwr_ctrl_create(&orte, rcv_pwr_ctrl_cb, &orte);
433 robottype_subscriber_motion_speed_create(&orte, rcv_motion_speed_cb, &orte);
434 robottype_subscriber_jaws_cmd_create(&orte, rcv_jaws_cmd_cb, &orte);
435 robottype_subscriber_lift_cmd_create(&orte, rcv_lift_cmd_cb, &orte);
436 robottype_subscriber_can_msg_create(&orte, rcv_can_msg_cb, &orte);
437 robottype_subscriber_cl_sensor_cmd_create(&orte, rcv_cl_sensor_cmd_cb, &orte);
438 printf("subscribers OK\n");
442 struct pollfd pfd[1] = {{sock, POLLIN, 0}};
444 ret = poll(pfd, 1, -1);
446 perror("cand: poll() error");
450 /* timeout expired, nothing to be done */
454 /* read data from SocketCAN */
455 size = read(sock, &frame, sizeof(struct can_frame));
459 cand_parse_frame(&orte, frame);