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>
31 UL_LOG_CUST(ulogd_robot_orte); /* Log domain name = ulogd + name of the file */
34 #define DBG(format, ...) ul_logdeb(format, ##__VA_ARGS__)
36 #define DBG(format, ...)
40 extern sem_t measurement_received;
42 /* ----------------------------------------------------------------------
43 * PUBLISHER CALLBACKS - GENERIC
44 * ---------------------------------------------------------------------- */
46 void send_ref_pos_cb(const ORTESendInfo *info, void *vinstance,
47 void *sendCallBackParam)
49 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
52 *instance = robot.ref_pos;
53 ROBOT_UNLOCK(ref_pos);
56 void send_est_pos_odo_cb(const ORTESendInfo *info, void *vinstance,
57 void *sendCallBackParam)
59 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
61 ROBOT_LOCK(est_pos_odo);
62 *instance = robot.est_pos_odo;
63 ROBOT_UNLOCK(est_pos_odo);
66 void send_est_pos_indep_odo_cb(const ORTESendInfo *info, void *vinstance,
67 void *sendCallBackParam)
69 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
71 ROBOT_LOCK(est_pos_indep_odo);
72 *instance = robot.est_pos_indep_odo;
73 ROBOT_UNLOCK(est_pos_indep_odo);
76 static void send_est_pos_best_cb(const ORTESendInfo *info, void *vinstance,
77 void *sendCallBackParam)
79 struct robot_pos_type *instance = (struct robot_pos_type *)vinstance;
81 robot_get_est_pos(&instance->x, &instance->y, &instance->phi);
84 void send_dummy_cb(const ORTESendInfo *info, void *vinstance,
85 void *sendCallBackParam)
89 /* ----------------------------------------------------------------------
90 * SUBSCRIBER CALLBACKS - GENERIC
91 * ---------------------------------------------------------------------- */
92 void rcv_odo_data_cb(const ORTERecvInfo *info, void *vinstance,
93 void *recvCallBackParam)
95 struct odo_data_type *instance = (struct odo_data_type *)vinstance;
96 double dleft, dright, dtang, dphi;
97 static bool first_run = true;
98 /* spocitat prevodovy pomer */
99 const double n = (double)(1.0 / 1.0);
101 /* vzdalenost na pulz IRC */
102 const double c = (M_PI*2*ODOMETRY_WHEEL_RADIUS_M) / (n * 4*4096.0);
104 switch (info->status) {
107 ROBOT_LOCK(odo_data);
108 robot.odo_data = *instance;
109 ROBOT_UNLOCK(odo_data);
114 dleft = ((robot.odo_data.left - instance->left) >> 8) * c; // TODO >> 8 ?
115 dright = ((instance->right - robot.odo_data.right) >> 8) * c;
117 dtang = (dleft + dright) / 2.0;
118 dphi = (dright - dleft) / (2.0*ODOMETRY_ROTATION_RADIUS_M);
120 ROBOT_LOCK(est_pos_indep_odo);
121 double a = robot.est_pos_indep_odo.phi;
122 robot.est_pos_indep_odo.x += dtang*cos(a);
123 robot.est_pos_indep_odo.y += dtang*sin(a);
124 robot.est_pos_indep_odo.phi += dphi;
125 ROBOT_UNLOCK(est_pos_indep_odo);
127 ROBOT_LOCK(odo_data);
128 robot.odo_data = *instance;
129 ROBOT_UNLOCK(odo_data);
131 robot.indep_odometry_works = true;
133 /* wake up motion-control/thread_trajectory_follower */
134 sem_post(&measurement_received);
136 //robot.hw_status[COMPONENT_ODO] = STATUS_OK;
139 robot.indep_odometry_works = false;
140 //robot.hw_status[COMPONENT_ODO] = STATUS_FAILED;
141 DBG("ORTE deadline occurred - odo_data receive\n");
146 void rcv_motion_irc_cb(const ORTERecvInfo *info, void *vinstance,
147 void *recvCallBackParam)
149 struct motion_irc_type *instance = (struct motion_irc_type *)vinstance;
150 double dleft, dright, dtang, dphi;
151 static bool first_run = true;
152 /* spocitat prevodovy pomer */
153 const double n = (double)(28.0 / 1.0);
155 /* vzdalenost na pulz IRC */
156 const double c = (M_PI*2*ROBOT_WHEEL_RADIUS_M) / (n * 4*500.0);
158 switch (info->status) {
161 ROBOT_LOCK(motion_irc);
162 robot.motion_irc = *instance;
163 ROBOT_UNLOCK(motion_irc);
168 dleft = ((robot.motion_irc.left - instance->left) >> 8) * c;
169 dright = ((instance->right - robot.motion_irc.right) >> 8) * c;
171 dtang = (dleft + dright) / 2.0;
172 dphi = (dright - dleft) / (2.0*ROBOT_ROTATION_RADIUS_M);
174 ROBOT_LOCK(est_pos_odo);
175 double a = robot.est_pos_odo.phi;
176 robot.est_pos_odo.x += dtang*cos(a);
177 robot.est_pos_odo.y += dtang*sin(a);
178 robot.est_pos_odo.phi += dphi;
179 ROBOT_UNLOCK(est_pos_odo);
181 /* locking should not be needed, but... */
182 ROBOT_LOCK(motion_irc);
183 robot.motion_irc = *instance;
184 robot.motion_irc_received = 1;
185 ROBOT_UNLOCK(motion_irc);
187 robot.odometry_works = true;
189 robot.status[COMPONENT_MOTOR] = STATUS_OK;
192 robot.odometry_works = false;
193 robot.status[COMPONENT_MOTOR] = STATUS_FAILED;
194 DBG("ORTE deadline occurred - motion_irc receive\n");
199 void rcv_motion_speed_cb(const ORTERecvInfo *info, void *vinstance,
200 void *recvCallBackParam)
202 switch (info->status) {
206 DBG("ORTE deadline occurred - motion_speed receive\n");
211 void rcv_motion_status_cb(const ORTERecvInfo *info, void *vinstance,
212 void *recvCallBackParam)
214 switch (info->status) {
218 DBG("ORTE deadline occurred - motion_status receive\n");
223 void rcv_pwr_voltage_cb(const ORTERecvInfo *info, void *vinstance,
224 void *recvCallBackParam)
226 switch (info->status) {
228 robot.status[COMPONENT_POWER]=STATUS_OK;
231 robot.status[COMPONENT_POWER]=STATUS_FAILED;
232 DBG("ORTE deadline occurred - pwr_voltage receive\n");
237 void rcv_pwr_ctrl_cb(const ORTERecvInfo *info, void *vinstance,
238 void *recvCallBackParam)
240 switch (info->status) {
244 DBG("ORTE deadline occurred - pwr_ctrl receive\n");
249 void rcv_robot_cmd_cb(const ORTERecvInfo *info, void *vinstance,
250 void *recvCallBackParam)
252 struct robot_cmd_type *instance = (struct robot_cmd_type *)vinstance;
253 static struct robot_cmd_type last_instance;
255 switch (info->status) {
257 /* Stupid way of controlling the robot by
258 * pluggin in and out start connector. */
259 switch (robot.start_state) {
261 if (!instance->start_condition) {
262 robot.status[COMPONENT_START] = STATUS_WARNING;
263 robot.start_state = START_PLUGGED_IN;
264 ul_logmsg("START_PLUGGED_IN\n");
268 case START_PLUGGED_IN:
269 robot.status[COMPONENT_START] = STATUS_OK;
270 /* Competition starts when plugged out */
271 if (instance->start_condition) {
272 FSM_SIGNAL(MAIN, EV_START, NULL);
273 robot.start_state = COMPETITION_STARTED;
274 ul_logmsg("STARTED\n");
278 case COMPETITION_STARTED: {
279 /* Subsequent plug-in stops the robot */
281 if (!instance->start_condition) {
282 robot.status[COMPONENT_START] = STATUS_WARNING;
289 last_instance = *instance;
292 robot.status[COMPONENT_START] = STATUS_FAILED;
293 DBG("ORTE deadline occurred - robot_cmd receive\n");
298 void rcv_hokuyo_scan_cb(const ORTERecvInfo *info, void *vinstance,
299 void *recvCallBackParam)
301 struct hokuyo_scan_type *instance = (struct hokuyo_scan_type *)vinstance;
303 switch (info->status) {
306 robot.hokuyo = *instance;
307 robot.status[COMPONENT_HOKUYO] = STATUS_OK;
308 ROBOT_UNLOCK(hokuyo);
309 if(!robot.ignore_hokuyo)
311 update_map_hokuyo(instance);
316 robot.status[COMPONENT_HOKUYO] = STATUS_FAILED;
317 //system("killall -9 hokuyo");
318 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
323 // FIXME: this is not up to date (Filip, 2010)
324 void rcv_camera_result_cb(const ORTERecvInfo *info, void *vinstance,
325 void *recvCallBackParam)
327 struct camera_result_type *instance = (struct camera_result_type *)vinstance;
329 switch (info->status) {
331 ROBOT_LOCK(camera_result);
332 robot.corns_conf_side = instance->side;
333 robot.corns_conf_center = instance->center;
334 ROBOT_UNLOCK(camera_result);
335 robot.status[COMPONENT_CAMERA] = STATUS_OK;
339 if (robot.orte.camera_control.on) {
340 robot.status[COMPONENT_CAMERA] = STATUS_FAILED;
341 //system("killall -9 rozpuk");
344 DBG("%s: ORTE deadline occurred\n", __FUNCTION__);
348 /* ----------------------------------------------------------------------
349 * SUBSCRIBER CALLBACKS - EB2008
350 * ---------------------------------------------------------------------- */
352 void rcv_jaws_status_cb(const ORTERecvInfo *info, void *vinstance,
353 void *recvCallBackParam)
355 struct jaws_status_type *instance = (struct jaws_status_type *)vinstance;
356 static int last_response_left = 0;
357 static int last_response_right = 0;
358 switch (info->status) {
360 // new data arrived and requested position equals actual position
361 if (instance->flags.left == 0 &&
362 instance->flags.right == 0)
363 robot.status[COMPONENT_JAWS] = STATUS_OK;
365 robot.status[COMPONENT_JAWS] = STATUS_WARNING;
367 if (instance->response.left != last_response_left &&
368 instance->response.right != last_response_right &&
369 instance->response.left == act_jaw_left_get_last_reqest() &&
370 instance->response.left == act_jaw_right_get_last_reqest())
371 FSM_SIGNAL(MAIN, EV_JAWS_DONE, NULL);
373 last_response_left = instance->response.left;
374 last_response_right = instance->response.right;
377 robot.status[COMPONENT_JAWS] = STATUS_FAILED;
378 DBG("ORTE deadline occurred - actuator_status receive\n");
383 void rcv_lift_status_cb(const ORTERecvInfo *info, void *vinstance,
384 void *recvCallBackParam)
386 struct lift_status_type *instance = (struct lift_status_type *)vinstance;
387 static int last_response = 0;
388 switch (info->status) {
390 // new data arrived and requested position equals actual position
391 if (instance->flags == 0)
392 robot.status[COMPONENT_LIFT] = STATUS_OK;
394 robot.status[COMPONENT_LIFT] = STATUS_WARNING;
396 if (instance->response != last_response &&
397 instance->response == act_lift_get_last_reqest())
398 FSM_SIGNAL(MAIN, EV_LIFT_DONE, NULL);
399 last_response = instance->response;
402 robot.status[COMPONENT_LIFT] = STATUS_FAILED;
403 DBG("ORTE deadline occurred - actuator_status receive\n");
408 void rcv_robot_switches_cb(const ORTERecvInfo *info, void *vinstance,
409 void *recvCallBackParam)
411 struct robot_switches_type *instance = (struct robot_switches_type *)vinstance;
412 static bool last_strategy;
413 switch (info->status) {
415 robot.team_color = instance->team_color;
417 if (!last_strategy && instance->strategy && (robot.start_state == POWER_ON)) {
418 /* strategy switching */
419 FSM_SIGNAL(MAIN, EV_SWITCH_STRATEGY, NULL);
421 last_strategy = instance->strategy;
428 void rcv_robot_bumpers_cb(const ORTERecvInfo *info, void *vinstance,
429 void *recvCallBackParam)
431 struct robot_bumpers_type *instance = (struct robot_bumpers_type *)vinstance;
432 static bool last_left, last_right;
433 switch (info->status) {
435 if (instance->bumper_right_across || instance->bumper_left_across)
436 FSM_SIGNAL(MOTION, EV_OBSTACLE_BEHIND, NULL);
438 if (instance->bumper_left || instance->bumper_right) {
439 FSM_SIGNAL(MOTION, EV_OBSTACLE_SIDE, NULL);
449 static int cmp_double(const void *v1, const void *v2)
451 const double *d1 = v1, *const d2 = v2;
461 int robot_init_orte()
465 robot.orte.strength = 20;
467 rv = robottype_roboorte_init(&robot.orte);
471 /* creating publishers */
472 robottype_publisher_motion_speed_create(&robot.orte, NULL, &robot.orte);
473 robottype_publisher_ref_pos_create(&robot.orte, send_ref_pos_cb, &robot.orte);
474 robottype_publisher_est_pos_odo_create(&robot.orte, send_est_pos_odo_cb, &robot.orte);
475 robottype_publisher_est_pos_indep_odo_create(&robot.orte, send_est_pos_indep_odo_cb, &robot.orte);
476 robottype_publisher_est_pos_best_create(&robot.orte, send_est_pos_best_cb, &robot.orte);
477 //???robottype_publisher_pwr_ctrl_create(&robot.orte, NULL, &robot.orte);
479 // I didn't know what was the difference between the callback function pointer
480 // being NULL and being set to pointer to empty send_dummy_cb function. The DIFFERENCE
482 // - NULL: message is published only when OrtePublicationSend called
483 // - pointer to empty function: message is published periodically
484 robottype_publisher_fsm_main_create(&robot.orte, send_dummy_cb, &robot.orte);
485 robottype_publisher_fsm_act_create(&robot.orte, send_dummy_cb, &robot.orte);
486 robottype_publisher_fsm_motion_create(&robot.orte, send_dummy_cb, &robot.orte);
487 robottype_publisher_camera_control_create(&robot.orte, send_dummy_cb, &robot.orte);
488 robottype_publisher_jaws_cmd_create(&robot.orte, send_dummy_cb, &robot.orte);
489 robottype_publisher_lift_cmd_create(&robot.orte, send_dummy_cb, &robot.orte);
491 /* create generic subscribers */
492 robottype_subscriber_odo_data_create(&robot.orte, rcv_odo_data_cb, &robot.orte);
493 robottype_subscriber_motion_irc_create(&robot.orte, rcv_motion_irc_cb, &robot.orte);
494 robottype_subscriber_motion_speed_create(&robot.orte, rcv_motion_speed_cb, &robot.orte);
495 robottype_subscriber_motion_status_create(&robot.orte, rcv_motion_status_cb, &robot.orte);
496 robottype_subscriber_pwr_voltage_create(&robot.orte, rcv_pwr_voltage_cb, &robot.orte);
497 //robottype_subscriber_pwr_ctrl_create(&robot.orte, rcv_pwr_ctrl_cb, &robot.orte);
498 robottype_subscriber_robot_cmd_create(&robot.orte, rcv_robot_cmd_cb, &robot.orte);
499 robottype_subscriber_hokuyo_scan_create(&robot.orte, rcv_hokuyo_scan_cb, &robot.orte);
500 robottype_subscriber_jaws_status_create(&robot.orte, rcv_jaws_status_cb, &robot.orte);
501 robottype_subscriber_lift_status_create(&robot.orte, rcv_lift_status_cb, &robot.orte);
502 robottype_subscriber_robot_switches_create(&robot.orte, rcv_robot_switches_cb, &robot.orte);
503 robottype_subscriber_robot_bumpers_create(&robot.orte, rcv_robot_bumpers_cb, &robot.orte);
504 robottype_subscriber_camera_result_create(&robot.orte, rcv_camera_result_cb, &robot.orte);