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"
27 #include <can_msg_def.h>
28 #include <actuators.h>
33 UL_LOG_CUST(ulogd_robot_orte); /* Log domain name = ulogd + name of the file */
36 #define DBG(format, ...) ul_logdeb(format, ##__VA_ARGS__)
38 #define DBG(format, ...)
42 extern sem_t measurement_received;
45 * Check rrobot component status
46 * @return zero if system OK, else 1
48 int check_prestart_status()
50 if ((robot.status[COMPONENT_MOTOR] == STATUS_FAILED) || (robot.status[COMPONENT_MOTOR] == STATUS_WARNING)) {
52 } else if (robot.status[COMPONENT_ODOMETRY] == STATUS_FAILED) {
54 } else if ((robot.status[COMPONENT_CAMERA] == STATUS_FAILED) || (robot.status[COMPONENT_CAMERA] == STATUS_WARNING)) {
56 } else if (robot.status[COMPONENT_POWER] == STATUS_FAILED) {
58 } else if (robot.status[COMPONENT_HOKUYO] == STATUS_FAILED) {
60 } else if (robot.status[COMPONENT_CRANE] == STATUS_FAILED) {
62 } else if (robot.status[COMPONENT_START] == STATUS_FAILED || robot.status[COMPONENT_START] == STATUS_WARNING) {
68 /* ----------------------------------------------------------------------
69 * PUBLISHER CALLBACKS - GENERIC
70 * ---------------------------------------------------------------------- */
72 void send_ref_pos_cb(const ORTESendInfo *info, void *vinstance,
73 void *sendCallBackParam)
75 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
77 Guard g(robot.lock_ref_pos);
78 *instance = robot.ref_pos;
81 void send_est_pos_odo_cb(const ORTESendInfo *info, void *vinstance,
82 void *sendCallBackParam)
84 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
86 Guard g(robot.lock_est_pos_odo);
87 *instance = robot.est_pos_odo;
90 void send_est_pos_indep_odo_cb(const ORTESendInfo *info, void *vinstance,
91 void *sendCallBackParam)
93 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
95 Guard g(robot.lock_est_pos_indep_odo);
96 *instance = robot.est_pos_indep_odo;
99 static void send_est_pos_best_cb(const ORTESendInfo *info, void *vinstance,
100 void *sendCallBackParam)
102 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
104 robot.get_est_pos(instance->x, instance->y, instance->phi);
107 static void send_system_status_cb(const ORTESendInfo *info, void *vinstance,
108 void *sendCallBackParam)
110 system_status *instance = (system_status *)vinstance;
112 /* if any component not ready, send warning for display to show APP yellow */
113 if (check_prestart_status()) {
114 instance->system_condition = 1; // system warning
116 instance->system_condition = 0; // system OK
120 void send_dummy_cb(const ORTESendInfo *info, void *vinstance,
121 void *sendCallBackParam)
125 /* ----------------------------------------------------------------------
126 * SUBSCRIBER CALLBACKS - GENERIC
127 * ---------------------------------------------------------------------- */
128 void rcv_odo_data_cb(const ORTERecvInfo *info, void *vinstance,
129 void *recvCallBackParam)
131 struct odo_data_type *instance = (struct odo_data_type *)vinstance;
132 double dleft, dright, dtang, dphi;
133 static bool first_run = true;
134 /* spocitat prevodovy pomer */
135 const double n = (double)(1.0 / 1.0);
137 /* vzdalenost na pulz IRC */
138 const double c = (M_PI*2*ODOMETRY_WHEEL_RADIUS_M) / (n * 4*4096.0);
140 switch (info->status) {
145 robot.odo_data = *instance;
151 dleft = ((robot.odo_data.left - instance->left) >> 8) * c; // TODO >> 8 ?
152 dright = ((instance->right - robot.odo_data.right) >> 8) * c;
154 dtang = (dleft + dright) / 2.0;
155 dphi = (dright - dleft) / (2.0*ODOMETRY_ROTATION_RADIUS_M);
157 Guard g(robot.lock_est_pos_indep_odo);
158 double a = robot.est_pos_indep_odo.phi;
159 robot.est_pos_indep_odo.x += dtang*cos(a);
160 robot.est_pos_indep_odo.y += dtang*sin(a);
161 robot.est_pos_indep_odo.phi += dphi;
165 robot.odo_data = *instance;
168 robot.indep_odometry_works = true;
170 /* wake up motion-control/thread_trajectory_follower */
171 sem_post(&measurement_received);
173 robot.status[COMPONENT_ODOMETRY] = STATUS_OK;
176 robot.indep_odometry_works = false;
177 robot.status[COMPONENT_ODOMETRY] = STATUS_FAILED;
178 DBG("ORTE deadline occurred - odo_data receive\n");
183 void rcv_motion_irc_cb(const ORTERecvInfo *info, void *vinstance,
184 void *recvCallBackParam)
186 struct motion_irc_type *instance = (struct motion_irc_type *)vinstance;
187 double dleft, dright, dtang, dphi;
188 static bool first_run = true;
189 /* spocitat prevodovy pomer */
190 const double n = (double)(28.0 / 1.0);
192 /* vzdalenost na pulz IRC */
193 const double c = (M_PI*2*ROBOT_WHEEL_RADIUS_M) / (n * 4*500.0);
195 switch (info->status) {
200 robot.motion_irc = *instance;
206 dleft = ((robot.motion_irc.left - instance->left) >> 8) * c;
207 dright = ((instance->right - robot.motion_irc.right) >> 8) * c;
209 dtang = (dleft + dright) / 2.0;
210 dphi = (dright - dleft) / (2.0*ROBOT_ROTATION_RADIUS_M);
213 Guard g(robot.lock_est_pos_odo);
214 double a = robot.est_pos_odo.phi;
215 robot.est_pos_odo.x += dtang*cos(a);
216 robot.est_pos_odo.y += dtang*sin(a);
217 robot.est_pos_odo.phi += dphi;
220 /* locking should not be needed, but... */
223 robot.motion_irc = *instance;
224 robot.motion_irc_received = 1;
227 robot.odometry_works = true;
229 //robot.status[COMPONENT_MOTOR] = STATUS_OK;
232 robot.odometry_works = false;
233 robot.status[COMPONENT_MOTOR] = STATUS_FAILED;
234 DBG("ORTE deadline occurred - motion_irc receive\n");
239 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
240 void *recvCallBackParam)
242 switch (info->status) {
246 DBG("ORTE deadline occurred - motion_speed receive\n");
251 void rcv_motion_status_cb(const ORTERecvInfo *info, void *vinstance,
252 void *recvCallBackParam)
254 struct motion_status_type *m = (struct motion_status_type *)vinstance;
256 switch (info->status) {
258 if (m->err_left == 0 && m->err_right == 0)
259 robot.status[COMPONENT_MOTOR] = STATUS_OK;
261 robot.status[COMPONENT_MOTOR] = STATUS_WARNING;
264 DBG("ORTE deadline occurred - motion_status receive\n");
269 void rcv_pwr_voltage_cb(const ORTERecvInfo *info, void *vinstance,
270 void *recvCallBackParam)
272 switch (info->status) {
274 robot.status[COMPONENT_POWER]=STATUS_OK;
277 robot.status[COMPONENT_POWER]=STATUS_FAILED;
278 DBG("ORTE deadline occurred - pwr_voltage receive\n");
283 void rcv_pwr_ctrl_cb(const ORTERecvInfo *info, void *vinstance,
284 void *recvCallBackParam)
286 switch (info->status) {
290 DBG("ORTE deadline occurred - pwr_ctrl receive\n");
295 void rcv_robot_cmd_cb(const ORTERecvInfo *info, void *vinstance,
296 void *recvCallBackParam)
298 struct robot_cmd_type *instance = (struct robot_cmd_type *)vinstance;
299 static struct robot_cmd_type last_instance;
301 switch (info->status) {
303 /* Stupid way of controlling the robot by
304 * pluggin in and out start connector. */
305 switch (robot.start_state) {
307 robot.status[COMPONENT_START] = STATUS_WARNING;
308 if (instance->start_condition == START_PLUGGED_IN) {
309 robot.start_state = START_PLUGGED_IN;
310 ul_logmsg("START_PLUGGED_IN\n");
314 case START_PLUGGED_IN:
315 robot.status[COMPONENT_START] = STATUS_OK;
316 /* Competition starts when plugged out, check component status before start */
317 if ((instance->start_condition == COMPETITION_STARTED) && !check_prestart_status()) {
318 robot.sched.queue_event(robot.MAIN, new evStart());
319 robot.start_state = COMPETITION_STARTED;
320 ul_logmsg("STARTED\n");
324 case COMPETITION_STARTED: {
325 robot.status[COMPONENT_START] = STATUS_WARNING;
326 /* Subsequent plug-in stops the robot */
328 if (instance->start_condition == START_PLUGGED_IN) {
335 last_instance = *instance;
338 robot.status[COMPONENT_START] = STATUS_FAILED;
339 DBG("ORTE deadline occurred - robot_cmd receive\n");
344 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
345 void *recvCallBackParam)
347 struct hokuyo_scan_type *instance = (struct hokuyo_scan_type *)vinstance;
349 switch (info->status) {
353 robot.hokuyo = *instance;
354 robot.status[COMPONENT_HOKUYO] = STATUS_OK;
356 if(!robot.ignore_hokuyo)
358 update_map_hokuyo(instance);
363 robot.status[COMPONENT_HOKUYO] = STATUS_FAILED;
364 //system("killall -9 hokuyo");
365 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
370 void rcv_camera_result_cb(const ORTERecvInfo *info, void *vinstance,
371 void *recvCallBackParam)
373 struct camera_result_type *instance = (struct camera_result_type *)vinstance;
374 static bool last_response = false;
376 switch (info->status) {
378 if (instance->error) {
379 robot.status[COMPONENT_CAMERA] = STATUS_FAILED;
380 } else if (instance->data_valid && instance->data_valid != last_response) {
382 Guard g(robot.lock_camera);
383 robot.target_valid = instance->target_valid;
385 robot.sched.queue_event(robot.MAIN, new evCameraDone());
386 printf("robot_orte: valid: %d\n", instance->target_valid);
388 robot.status[COMPONENT_CAMERA] = STATUS_OK;
390 last_response = instance->data_valid;
394 if (robot.orte.camera_control.on) {
395 robot.status[COMPONENT_CAMERA] = STATUS_FAILED;
396 //system("killall -9 rozpuk");
399 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
404 void rcv_crane_status_cb(const ORTERecvInfo *info, void *vinstance,
405 void *recvCallBackParam)
407 struct crane_status_type *instance = (struct crane_status_type *)vinstance;
408 static int last_response = 0;
409 switch (info->status) {
411 // new data arrived and requested position equals actual position
412 if (instance->flags == 0)
413 robot.status[COMPONENT_CRANE]=STATUS_OK;
415 robot.status[COMPONENT_CRANE]=STATUS_WARNING;
417 if (instance->response != last_response &&
418 instance->response == act_crane_get_last_reqest())
419 robot.sched.queue_event(robot.MAIN, new evCraneDone);
420 last_response = instance->response;
423 robot.status[COMPONENT_CRANE]=STATUS_FAILED;
424 DBG("ORTE deadline occurred - actuator_status receive\n");
429 void rcv_robot_switches_cb(const ORTERecvInfo *info, void *vinstance,
430 void *recvCallBackParam)
432 struct robot_switches_type *instance = (struct robot_switches_type *)vinstance;
433 static bool last_strategy;
434 switch (info->status) {
436 if ((!last_strategy && instance->strategy) && (robot.start_state == POWER_ON)) {
437 robot.sched.queue_event(robot.MAIN, new evSwitchStrategy());
439 last_strategy = instance->strategy;
446 void rcv_robot_bumpers_cb(const ORTERecvInfo *info, void *vinstance,
447 void *recvCallBackParam)
449 struct robot_bumpers_type *instance = (struct robot_bumpers_type *)vinstance;
450 switch (info->status) {
452 if (!instance->bumper_rear) {
453 robot.sched.queue_event(robot.MOTION, new evObstacleBehind());
455 if ((!instance->bumper_left) ||
456 (!instance->bumper_right)) {
457 robot.sched.queue_event(robot.MOTION, new evObstacleSide());
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_system_status_create(&robot.orte, send_system_status_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_crane_cmd_create(&robot.orte, send_dummy_cb, &robot.orte);
509 robottype_publisher_magnet_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_crane_status_create(&robot.orte, rcv_crane_status_cb, &robot.orte);
521 robottype_subscriber_robot_switches_create(&robot.orte, rcv_robot_switches_cb, &robot.orte);
522 robottype_subscriber_robot_bumpers_create(&robot.orte, rcv_robot_bumpers_cb, &robot.orte);
523 robottype_subscriber_camera_result_create(&robot.orte, rcv_camera_result_cb, &robot.orte);