5 * @brief Module providing communication through ORTE
9 * robot_orte.c 08/04/21
11 * Robot's orte stuffs.
13 * Copyright: (c) 2008-2010 CTU Dragons
14 * CTU FEE - Department of Control Engineering
15 * License: GNU GPL v.2
19 #include <roboorte_robottype.h>
22 #include <movehelper.h>
25 #include "map_handling.h"
26 #include "match-timing.h"
28 #include <can_msg_def.h>
29 #include <actuators.h>
32 UL_LOG_CUST(ulogd_robot_orte); /* Log domain name = ulogd + name of the file */
35 #define DBG(format, ...) ul_logdeb(format, ##__VA_ARGS__)
37 #define DBG(format, ...)
41 extern sem_t measurement_received;
43 /* ----------------------------------------------------------------------
44 * PUBLISHER CALLBACKS - GENERIC
45 * ---------------------------------------------------------------------- */
47 void send_ref_pos_cb(const ORTESendInfo *info, void *vinstance,
48 void *sendCallBackParam)
50 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
53 *instance = robot.ref_pos;
54 ROBOT_UNLOCK(ref_pos);
57 void send_est_pos_odo_cb(const ORTESendInfo *info, void *vinstance,
58 void *sendCallBackParam)
60 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
62 ROBOT_LOCK(est_pos_odo);
63 *instance = robot.est_pos_odo;
64 ROBOT_UNLOCK(est_pos_odo);
67 void send_est_pos_indep_odo_cb(const ORTESendInfo *info, void *vinstance,
68 void *sendCallBackParam)
70 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
72 ROBOT_LOCK(est_pos_indep_odo);
73 *instance = robot.est_pos_indep_odo;
74 ROBOT_UNLOCK(est_pos_indep_odo);
77 static void send_est_pos_best_cb(const ORTESendInfo *info, void *vinstance,
78 void *sendCallBackParam)
80 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
82 robot_get_est_pos(&instance->x, &instance->y, &instance->phi);
85 void send_dummy_cb(const ORTESendInfo *info, void *vinstance,
86 void *sendCallBackParam)
90 void send_match_time_cb(const ORTESendInfo *info, void *vinstance,
91 void *sendCallBackParam)
93 struct match_time_type *instance = (struct match_time_type *)vinstance;
95 if (robot.start_state == POWER_ON || robot.start_state == START_PLUGGED_IN) {
98 instance->time = 90 - robot_current_time();
101 /* ----------------------------------------------------------------------
102 * SUBSCRIBER CALLBACKS - GENERIC
103 * ---------------------------------------------------------------------- */
104 void rcv_odo_data_cb(const ORTERecvInfo *info, void *vinstance,
105 void *recvCallBackParam)
107 struct odo_data_type *instance = (struct odo_data_type *)vinstance;
108 double dleft, dright, dtang, dphi;
109 static bool first_run = true;
110 /* spocitat prevodovy pomer */
111 const double n = (double)(1.0 / 1.0);
113 /* vzdalenost na pulz IRC */
114 const double c = (M_PI*2*ODOMETRY_WHEEL_RADIUS_M) / (n * 4*4096.0);
116 switch (info->status) {
119 ROBOT_LOCK(odo_data);
120 robot.odo_data = *instance;
121 ROBOT_UNLOCK(odo_data);
126 dleft = ((robot.odo_data.left - instance->left) >> 8) * c * robot.odo_cal_a; // TODO >> 8 ?
127 dright = ((instance->right - robot.odo_data.right) >> 8) * c * robot.odo_cal_b;
129 dtang = (dleft + dright) / 2.0;
130 dphi = (dright - dleft) / (2.0*ODOMETRY_ROTATION_RADIUS_M);
132 ROBOT_LOCK(est_pos_indep_odo);
133 robot.odo_distance_a +=dleft;
134 robot.odo_distance_b +=dright;
135 double a = robot.est_pos_indep_odo.phi;
136 robot.est_pos_indep_odo.x += dtang*cos(a);
137 robot.est_pos_indep_odo.y += dtang*sin(a);
138 robot.est_pos_indep_odo.phi += dphi;
139 ROBOT_UNLOCK(est_pos_indep_odo);
141 ROBOT_LOCK(odo_data);
142 robot.odo_data = *instance;
143 ROBOT_UNLOCK(odo_data);
145 robot.indep_odometry_works = true;
147 /* wake up motion-control/thread_trajectory_follower */
148 sem_post(&measurement_received);
150 //robot.hw_status[COMPONENT_ODO] = STATUS_OK;
153 robot.indep_odometry_works = false;
154 //robot.hw_status[COMPONENT_ODO] = STATUS_FAILED;
155 DBG("ORTE deadline occurred - odo_data receive\n");
160 void rcv_motion_irc_cb(const ORTERecvInfo *info, void *vinstance,
161 void *recvCallBackParam)
163 struct motion_irc_type *instance = (struct motion_irc_type *)vinstance;
164 double dleft, dright, dtang, dphi;
165 static bool first_run = true;
166 /* spocitat prevodovy pomer */
167 const double n = (double)(ROBOT_MOTOR_GEARBOX_RATIO / 1.0);
169 /* vzdalenost na pulz IRC */
170 const double c = (M_PI*2*ROBOT_WHEEL_RADIUS_M) / (n * 4*ROBOT_MOTOR_IRC_RESOLUTION);
171 switch (info->status) {
174 ROBOT_LOCK(motion_irc);
175 robot.motion_irc = *instance;
176 ROBOT_UNLOCK(motion_irc);
182 /* FIXME maybe it is not correct to do this nasty hack here (switch dleft and dright),
183 what is the right solution?
184 This was neccessary to view motor odometry correctly in robomon. */
185 dright = ((robot.motion_irc.left - instance->left) >> 8) * c * robot.odo_cal_b;
186 dleft = ((instance->right - robot.motion_irc.right) >> 8) * c * robot.odo_cal_a;
188 dtang = (dleft + dright) / 2.0;
189 dphi = (dright - dleft) / (2.0*ROBOT_ROTATION_RADIUS_M);
191 ROBOT_LOCK(est_pos_odo);
192 robot.odo_distance_a +=dleft;
193 robot.odo_distance_b +=dright;
194 double a = robot.est_pos_odo.phi;
195 robot.est_pos_odo.x += dtang*cos(a);
196 robot.est_pos_odo.y += dtang*sin(a);
197 robot.est_pos_odo.phi += dphi;
198 ROBOT_UNLOCK(est_pos_odo);
200 /* locking should not be needed, but... */
201 ROBOT_LOCK(motion_irc);
202 robot.motion_irc = *instance;
203 robot.motion_irc_received = 1;
204 ROBOT_UNLOCK(motion_irc);
206 robot.odometry_works = true;
208 robot.status[COMPONENT_MOTOR] = STATUS_OK;
211 robot.odometry_works = false;
212 robot.status[COMPONENT_MOTOR] = STATUS_FAILED;
213 DBG("ORTE deadline occurred - motion_irc receive\n");
218 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
219 void *recvCallBackParam)
221 switch (info->status) {
225 DBG("ORTE deadline occurred - motion_speed receive\n");
230 void rcv_motion_status_cb(const ORTERecvInfo *info, void *vinstance,
231 void *recvCallBackParam)
233 switch (info->status) {
237 DBG("ORTE deadline occurred - motion_status receive\n");
242 void rcv_pwr_voltage_cb(const ORTERecvInfo *info, void *vinstance,
243 void *recvCallBackParam)
245 switch (info->status) {
247 robot.status[COMPONENT_POWER]=STATUS_OK;
250 robot.status[COMPONENT_POWER]=STATUS_FAILED;
251 DBG("ORTE deadline occurred - pwr_voltage receive\n");
256 void rcv_pwr_ctrl_cb(const ORTERecvInfo *info, void *vinstance,
257 void *recvCallBackParam)
259 switch (info->status) {
263 DBG("ORTE deadline occurred - pwr_ctrl receive\n");
268 void rcv_robot_cmd_cb(const ORTERecvInfo *info, void *vinstance,
269 void *recvCallBackParam)
271 struct robot_cmd_type *instance = (struct robot_cmd_type *)vinstance;
272 static struct robot_cmd_type last_instance;
274 switch (info->status) {
276 /* Stupid way of controlling the robot by
277 * pluggin in and out start connector. */
278 switch (robot.start_state) {
280 if (!instance->start_condition) {
281 robot.status[COMPONENT_START] = STATUS_WARNING;
282 robot.start_state = START_PLUGGED_IN;
283 ul_logmsg("START_PLUGGED_IN\n");
287 case START_PLUGGED_IN:
288 robot.status[COMPONENT_START] = STATUS_OK;
289 /* Competition starts when plugged out */
290 if (instance->start_condition) {
291 FSM_SIGNAL(MAIN, EV_START, NULL);
292 robot.start_state = COMPETITION_STARTED;
293 ul_logmsg("STARTED\n");
297 case COMPETITION_STARTED: {
298 /* Subsequent plug-in stops the robot */
300 if (!instance->start_condition) {
301 robot.status[COMPONENT_START] = STATUS_WARNING;
308 last_instance = *instance;
311 robot.status[COMPONENT_START] = STATUS_FAILED;
312 DBG("ORTE deadline occurred - robot_cmd receive\n");
317 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
318 void *recvCallBackParam)
320 struct hokuyo_scan_type *instance = (struct hokuyo_scan_type *)vinstance;
322 switch (info->status) {
325 robot.hokuyo = *instance;
326 robot.status[COMPONENT_HOKUYO] = STATUS_OK;
327 ROBOT_UNLOCK(hokuyo);
328 if(!robot.ignore_hokuyo)
330 update_map_hokuyo(instance);
335 robot.status[COMPONENT_HOKUYO] = STATUS_FAILED;
336 //system("killall -9 hokuyo");
337 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
342 // FIXME: this is not up to date (Filip, 2010)
343 void rcv_camera_result_cb(const ORTERecvInfo *info, void *vinstance,
344 void *recvCallBackParam)
346 struct camera_result_type *instance = (struct camera_result_type *)vinstance;
348 switch (info->status) {
350 ROBOT_LOCK(camera_result);
351 robot.corns_conf_side = instance->side;
352 robot.corns_conf_center = instance->center;
353 ROBOT_UNLOCK(camera_result);
354 robot.status[COMPONENT_CAMERA] = STATUS_OK;
358 if (robot.orte.camera_control.on) {
359 robot.status[COMPONENT_CAMERA] = STATUS_FAILED;
360 //system("killall -9 rozpuk");
363 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
367 /* ----------------------------------------------------------------------
368 * SUBSCRIBER CALLBACKS - EB2008
369 * ---------------------------------------------------------------------- */
371 void rcv_jaws_status_cb(const ORTERecvInfo *info, void *vinstance,
372 void *recvCallBackParam)
374 struct jaws_status_type *instance = (struct jaws_status_type *)vinstance;
375 static int last_response_left = 0;
376 static int last_response_right = 0;
377 switch (info->status) {
379 // new data arrived and requested position equals actual position
380 if (instance->flags.left == 0 &&
381 instance->flags.right == 0)
382 robot.status[COMPONENT_JAWS] = STATUS_OK;
384 robot.status[COMPONENT_JAWS] = STATUS_WARNING;
386 if (instance->response.left != last_response_left &&
387 instance->response.right != last_response_right &&
388 instance->response.left == act_jaw_left_get_last_reqest() &&
389 instance->response.left == act_jaw_right_get_last_reqest())
390 FSM_SIGNAL(MAIN, EV_JAWS_DONE, NULL);
392 last_response_left = instance->response.left;
393 last_response_right = instance->response.right;
396 robot.status[COMPONENT_JAWS] = STATUS_FAILED;
397 DBG("ORTE deadline occurred - actuator_status receive\n");
402 void rcv_lift_status_cb(const ORTERecvInfo *info, void *vinstance,
403 void *recvCallBackParam)
405 struct lift_status_type *instance = (struct lift_status_type *)vinstance;
406 static int last_response = 0;
407 switch (info->status) {
409 // new data arrived and requested position equals actual position
410 if (instance->flags == 0)
411 robot.status[COMPONENT_LIFT] = STATUS_OK;
413 robot.status[COMPONENT_LIFT] = STATUS_WARNING;
415 if (instance->response != last_response &&
416 instance->response == act_lift_get_last_reqest())
417 FSM_SIGNAL(MAIN, EV_LIFT_DONE, NULL);
418 last_response = instance->response;
421 robot.status[COMPONENT_LIFT] = STATUS_FAILED;
422 DBG("ORTE deadline occurred - actuator_status receive\n");
427 void rcv_robot_switches_cb(const ORTERecvInfo *info, void *vinstance,
428 void *recvCallBackParam)
430 struct robot_switches_type *instance = (struct robot_switches_type *)vinstance;
431 static bool last_strategy;
432 switch (info->status) {
434 robot.team_color = instance->team_color;
436 if (!last_strategy && instance->strategy) {
437 /* strategy switching */
438 FSM_SIGNAL(MAIN, EV_SWITCH_STRATEGY, NULL);
440 last_strategy = instance->strategy;
447 void rcv_robot_bumpers_cb(const ORTERecvInfo *info, void *vinstance,
448 void *recvCallBackParam)
450 struct robot_bumpers_type *instance = (struct robot_bumpers_type *)vinstance;
451 static bool last_left, last_right;
452 switch (info->status) {
454 if (instance->bumper_right_across || instance->bumper_left_across || instance->bumper_rear_left || instance->bumper_rear_right)
455 FSM_SIGNAL(MOTION, EV_OBSTACLE_BEHIND, NULL);
457 if (instance->bumper_left || instance->bumper_right) {
458 FSM_SIGNAL(MOTION, EV_OBSTACLE_SIDE, NULL);
468 static int cmp_double(const void *v1, const void *v2)
470 const double *d1 = v1, *const d2 = v2;
480 int robot_init_orte()
484 robot.orte.strength = 20;
486 rv = robottype_roboorte_init(&robot.orte);
490 /* creating publishers */
491 robottype_publisher_motion_speed_create(&robot.orte, NULL, &robot.orte);
492 robottype_publisher_ref_pos_create(&robot.orte, send_ref_pos_cb, &robot.orte);
493 robottype_publisher_est_pos_odo_create(&robot.orte, send_est_pos_odo_cb, &robot.orte);
494 robottype_publisher_est_pos_indep_odo_create(&robot.orte, send_est_pos_indep_odo_cb, &robot.orte);
495 robottype_publisher_est_pos_best_create(&robot.orte, send_est_pos_best_cb, &robot.orte);
496 robottype_publisher_match_time_create(&robot.orte, send_match_time_cb, &robot.orte);
497 //???robottype_publisher_pwr_ctrl_create(&robot.orte, NULL, &robot.orte);
499 // I didn't know what was the difference between the callback function pointer
500 // being NULL and being set to pointer to empty send_dummy_cb function. The DIFFERENCE
502 // - NULL: message is published only when OrtePublicationSend called
503 // - pointer to empty function: message is published periodically
504 robottype_publisher_fsm_main_create(&robot.orte, send_dummy_cb, &robot.orte);
505 robottype_publisher_fsm_act_create(&robot.orte, send_dummy_cb, &robot.orte);
506 robottype_publisher_fsm_motion_create(&robot.orte, send_dummy_cb, &robot.orte);
507 robottype_publisher_camera_control_create(&robot.orte, send_dummy_cb, &robot.orte);
508 robottype_publisher_jaws_cmd_create(&robot.orte, send_dummy_cb, &robot.orte);
509 robottype_publisher_lift_cmd_create(&robot.orte, send_dummy_cb, &robot.orte);
511 /* create generic subscribers */
512 robottype_subscriber_odo_data_create(&robot.orte, rcv_odo_data_cb, &robot.orte);
513 robottype_subscriber_motion_irc_create(&robot.orte, rcv_motion_irc_cb, &robot.orte);
514 robottype_subscriber_motion_speed_create(&robot.orte, rcv_motion_speed_cb, &robot.orte);
515 robottype_subscriber_motion_status_create(&robot.orte, rcv_motion_status_cb, &robot.orte);
516 robottype_subscriber_pwr_voltage_create(&robot.orte, rcv_pwr_voltage_cb, &robot.orte);
517 //robottype_subscriber_pwr_ctrl_create(&robot.orte, rcv_pwr_ctrl_cb, &robot.orte);
518 robottype_subscriber_robot_cmd_create(&robot.orte, rcv_robot_cmd_cb, &robot.orte);
519 robottype_subscriber_hokuyo_scan_create(&robot.orte, rcv_hokuyo_scan_cb, &robot.orte);
520 robottype_subscriber_jaws_status_create(&robot.orte, rcv_jaws_status_cb, &robot.orte);
521 robottype_subscriber_lift_status_create(&robot.orte, rcv_lift_status_cb, &robot.orte);
522 robottype_subscriber_robot_switches_create(&robot.orte, rcv_robot_switches_cb, &robot.orte);
523 robottype_subscriber_robot_bumpers_create(&robot.orte, rcv_robot_bumpers_cb, &robot.orte);
524 robottype_subscriber_camera_result_create(&robot.orte, rcv_camera_result_cb, &robot.orte);