Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Fork of PsiSwarm-BeaconDemo_Bluetooth by
programs.cpp
00001 /// PsiSwarm Beautiful Meme Project Source Code 00002 /// Version 0.2 00003 /// James Hilder, Alan Millard, Homero Elizondo, Jon Timmis 00004 /// University of York 00005 00006 // programs.cpp - Various PsiSwarm Programs for Beautiful Meme Project 00007 00008 #include "main.h" 00009 #include "psiswarm.h" 00010 00011 int obstacle_avoidance_threshold = 300; 00012 int robot_avoidance_threshold = 2000; 00013 00014 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00015 /// head_to_bearing_program 00016 char was_turning = 0; 00017 00018 ///The head to bearing program moves towards a given bearing (eg 0 for the beacon or 180 for the opposite wall) and keeps going until an obstacle is detected in front of it 00019 void head_to_bearing_program(int target_bearing) 00020 { 00021 if(step_cycle == 0 || was_turning == 0) { 00022 // Check if we are heading in the right bearing (+- 25 degrees) 00023 int current_bearing = (360 - beacon_heading) % 360; 00024 // Current bearing should range from 0 to 359; target_bearing likewise; check the are within 25 degrees of each other 00025 char bearing_ok = 0; 00026 int lower_bound = target_bearing - 25; 00027 int upper_bound = target_bearing + 25; 00028 if(lower_bound < 0) { 00029 if(current_bearing > (lower_bound + 360) || current_bearing < upper_bound) bearing_ok = 1; 00030 } else if(upper_bound > 359) { 00031 if(current_bearing > lower_bound || current_bearing < (upper_bound - 360)) bearing_ok = 1; 00032 } else if(current_bearing > lower_bound && current_bearing < upper_bound) bearing_ok = 1; 00033 // Check if there is an obstacle in front of us 00034 if((reflected_sensor_data[7] > 1000 || reflected_sensor_data[0] > 1000) && bearing_ok == 1) target_reached = 1; 00035 else { 00036 // Now move forward if we are facing correct bearing, otherwise turn 00037 if(bearing_ok == 1) { 00038 //Check if anything is in front of us to determine speed - if it is, move slowly 00039 int t_time = 6 * BEACON_PERIOD; 00040 float t_speed = 1.0; 00041 if(reflected_sensor_data[7] > 150 || reflected_sensor_data[0] > 150) { 00042 t_time = 4 * BEACON_PERIOD; 00043 t_speed = 0.6; 00044 } 00045 if(reflected_sensor_data[7] > 300 || reflected_sensor_data[0] > 300) { 00046 t_time = 3 * BEACON_PERIOD; 00047 t_speed = 0.4; 00048 } 00049 if(reflected_sensor_data[7] > 500 || reflected_sensor_data[0] > 500) { 00050 t_time = 2 * BEACON_PERIOD; 00051 t_speed = 0.2; 00052 } 00053 time_based_forward(t_speed,t_time,0); 00054 was_turning = 0; 00055 } else { 00056 turn_to_bearing(target_bearing); 00057 was_turning = 1; 00058 } 00059 } 00060 } 00061 } 00062 00063 int ticks = 0; 00064 float c = 0.25; 00065 float avoidRange = 400; 00066 float roboSpeed = 0.5; 00067 int lightNum = 0; 00068 float side_factor = 0.5; //side ir sensor weight factor 00069 00070 00071 void obs_avoid() 00072 { 00073 float left_motor_speed = 0.5; 00074 float right_motor_speed = 0.5; 00075 00076 if (reflected_sensor_data[0] > 600){ //adjust because of high reading from robot 3 00077 left_motor_speed = -0.5; 00078 set_left_motor_speed(left_motor_speed); 00079 set_right_motor_speed(right_motor_speed); 00080 //display.write_string("Walking R"); 00081 } 00082 else if (reflected_sensor_data[7] > 600){ 00083 right_motor_speed = -0.5; 00084 set_left_motor_speed(left_motor_speed); 00085 set_right_motor_speed(right_motor_speed); 00086 //display.write_string("Walking L"); 00087 } 00088 else { 00089 display.clear_display(); 00090 display.set_position(0,0); 00091 float left_motor_speed = 0.5; 00092 float right_motor_speed = 0.5; 00093 int turnChance = rand() %100; 00094 if (turnChance < 20) { 00095 left_motor_speed = 0; 00096 } else if (turnChance > 80) { 00097 right_motor_speed = 0; 00098 } 00099 00100 set_left_motor_speed(left_motor_speed); 00101 set_right_motor_speed(right_motor_speed); 00102 } 00103 } 00104 00105 00106 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00107 /// recharging_program 00108 00109 char recharge_power_check_count = 0; 00110 char battery_low_count = 0; 00111 00112 void recharging_program() 00113 { 00114 switch(recharging_state) { 00115 case 0: 00116 // We are not currently recharging, check the battery state 00117 if(get_battery_voltage() < battery_low_threshold) { 00118 // Battery is below low threshold 00119 battery_low_count ++; 00120 // We don't immediately start recharging routine in case as battery level can fluctuate a little due to load; if we get a low value for 4 continuous timesteps we start recharging routine 00121 if(battery_low_count > 3) { 00122 // Set recharging state to 'looking for charger' 00123 recharging_state = 1; 00124 strcpy(prog_name,"CHARGING PROGRAM"); 00125 set_program_info("HEAD TO BEACON"); 00126 } 00127 } else battery_low_count = 0; 00128 break; 00129 // State 1: Head to beacon [as this is where battery charger is] 00130 case 1: 00131 target_reached = 0; 00132 head_to_bearing_program(0); 00133 if(target_reached == 1) { 00134 recharging_state = 2; 00135 set_program_info("TURN 90 DEGREES"); 00136 } 00137 break; 00138 // Stage 2: Turn 90 degrees to align with charging pads 00139 case 2: 00140 disable_ir_emitters = 1; 00141 time_based_turn_degrees(0.8, 70.0, 1); 00142 recharge_power_check_count = 0; 00143 recharging_state = 3; 00144 break; 00145 // Stage 3: Wait for turn to complete 00146 case 3: 00147 if (time_based_motor_action != 1) { 00148 recharging_state = 4; 00149 set_program_info("CHECK FOR POWER"); 00150 } 00151 break; 00152 // Stage 4: Check if charging 00153 case 4: 00154 recharge_power_check_count++; 00155 if(get_dc_status() == 1) { 00156 recharging_state = 5; 00157 } else { 00158 if(recharge_power_check_count < 10)recharging_state = 6; 00159 else { 00160 recharging_state = 7; 00161 set_program_info("NO POWER - RETRY"); 00162 } 00163 } 00164 break; 00165 // Stage 5: Charging. Wait until threshold voltage exceeded 00166 case 5: 00167 if(get_battery_voltage() > battery_high_threshold) { 00168 set_program_info("LEAVE CHARGER"); 00169 recharging_state = 7; 00170 } else { 00171 char b_voltage[16]; 00172 sprintf(b_voltage,"CHARGE: %1.3fV",get_battery_voltage()); 00173 set_program_info(b_voltage); 00174 } 00175 break; 00176 // Stage 6: We didn't find power, keep turning a couple of degrees at a time a recheck 00177 case 6: 00178 time_based_turn_degrees(0.5,4,1); 00179 recharging_state = 4; 00180 break; 00181 // Stage 7: Charge may be finished. Turn 90 degrees then move away and resume previous program 00182 case 7: 00183 time_based_turn_degrees(0.8, 90.0, 1); 00184 recharging_state = 8; 00185 break; 00186 00187 // Stage 8: Wait for turn to complete 00188 case 8: 00189 if (time_based_motor_action != 1) recharging_state = 9; 00190 break; 00191 // Stage 9: Move away 00192 case 9: 00193 time_based_forward(0.5, 1000000, 1); 00194 recharging_state = 10; 00195 break; 00196 // Stage 10: Wait for move to complete 00197 case 10: 00198 if (time_based_motor_action != 1) recharging_state = 11; 00199 break; 00200 // Stage 11: Check if battery is below low threshold; if it is, start over, else end charge cycle 00201 case 11: 00202 disable_ir_emitters = 0; 00203 if (get_battery_voltage() < battery_low_threshold) { 00204 recharging_state = 1; 00205 } else { 00206 recharging_state = 0; 00207 //Restore name of old program on display 00208 set_program(main_program_state); 00209 } 00210 break; 00211 } 00212 } 00213 00214 00215 00216 00217 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00218 /// curved_walk_with_interaction_program (Alan's Random Walk\Obstacle Avoid and Robot Interaction Program) 00219 00220 enum random_walk_state {random_walk, turn_towards, interact, turn_away, avoid_obstacle}; 00221 enum random_walk_state internal_state = random_walk; 00222 char action_timeout = 0; 00223 char interaction_timeout = 0; 00224 char random_walk_timeout = 0; 00225 float previous_left_motor_speed = 0.5; 00226 float previous_right_motor_speed = 0.5; 00227 00228 void curved_random_walk_with_interaction_program() 00229 { 00230 if(internal_state == random_walk) { 00231 if(interaction_timeout < 4) 00232 interaction_timeout++; 00233 00234 int closest_robot = -1; 00235 unsigned short shortest_distance = 0; 00236 00237 // Check whether there are any other robots within range 00238 for(int i = 0; i < 8; i++) { 00239 if(robots_found[i]) { 00240 if(robots_distance[i] > shortest_distance) { 00241 shortest_distance = robots_distance[i]; 00242 closest_robot = i; 00243 } 00244 } 00245 } 00246 00247 // Turn towards the closest robot 00248 if(closest_robot >= 0 && shortest_distance > 300 && interaction_timeout >= 4) { 00249 time_based_turn_degrees(1, robots_heading[closest_robot], 1); 00250 00251 action_timeout = 0; 00252 internal_state = turn_towards; 00253 char temp_message[17]; 00254 sprintf(temp_message,"FACE ROBOT %d",closest_robot); 00255 set_program_info(temp_message); 00256 } else { // Otherwise, do a random walk 00257 // Check the front sensors for obstacles 00258 if(reflected_sensor_data[0] > obstacle_avoidance_threshold || 00259 reflected_sensor_data[1] > obstacle_avoidance_threshold || 00260 reflected_sensor_data[6] > obstacle_avoidance_threshold || 00261 reflected_sensor_data[7] > obstacle_avoidance_threshold) { 00262 // Ignore the rear sensors when calculating the heading 00263 reflected_sensor_data[2] = 0; 00264 reflected_sensor_data[3] = 0; 00265 reflected_sensor_data[4] = 0; 00266 reflected_sensor_data[5] = 0; 00267 00268 // Turn 180 degrees away from the sensed obstacle 00269 int heading = get_bearing_from_ir_array (reflected_sensor_data) + 180; 00270 00271 // Normalise 00272 heading %= 360; 00273 00274 if(heading < -180) 00275 heading += 360; 00276 00277 if(heading > 180) 00278 heading -= 360; 00279 set_program_info("AVOID OBSTACLE"); 00280 time_based_turn_degrees(1, heading, 1); 00281 00282 action_timeout = 0; 00283 internal_state = turn_away; 00284 } else { 00285 // Change motor speeds every 1s 00286 if(random_walk_timeout >= 2) { 00287 float random_offset = (((float) rand() / (float) RAND_MAX) - 0.5) * 0.5; 00288 00289 float left_motor_speed = previous_left_motor_speed - random_offset; 00290 float right_motor_speed = previous_right_motor_speed + random_offset; 00291 00292 float threshold = 0.25; 00293 00294 if(left_motor_speed < threshold) 00295 left_motor_speed = threshold; 00296 00297 if(right_motor_speed < threshold) 00298 right_motor_speed = threshold; 00299 00300 set_left_motor_speed(left_motor_speed); 00301 set_right_motor_speed(right_motor_speed); 00302 00303 random_walk_timeout = 0; 00304 } 00305 00306 random_walk_timeout++; 00307 } 00308 } 00309 } else if(internal_state == turn_towards) { 00310 if(action_timeout < 4) 00311 action_timeout++; 00312 else { 00313 set_program_info("SAY HELLO"); 00314 vibrate(); 00315 00316 action_timeout = 0; 00317 internal_state = interact; 00318 } 00319 } else if(internal_state == interact) { 00320 if(action_timeout < 4) 00321 action_timeout++; 00322 else { 00323 set_program_info("TURN AROUND"); 00324 time_based_turn_degrees(1, 180, 1); 00325 00326 action_timeout = 0; 00327 internal_state = turn_away; 00328 } 00329 00330 } else if(internal_state == turn_away) { 00331 if(action_timeout < 4) 00332 action_timeout++; 00333 else { 00334 set_program_info("RANDOM WALK"); 00335 interaction_timeout = 0; 00336 internal_state = random_walk; 00337 } 00338 } else if(internal_state == avoid_obstacle) { 00339 if(action_timeout < 4) 00340 action_timeout++; 00341 else 00342 set_program_info("RANDOM WALK"); 00343 internal_state = random_walk; 00344 } 00345 } 00346 00347 00348 00349 00350 00351 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00352 /// straight_random_walk_with_interaction_program 00353 00354 void straight_random_walk_with_interaction_program() 00355 { 00356 00357 } 00358 00359 00360 00361 00362 00363 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00364 /// find_space_program 00365 00366 char prog_debug = 1 ; 00367 float target_wheel_speed; 00368 int random_walk_bearing; 00369 00370 void find_space_program(char bidirectional) 00371 { 00372 // The find_space_program is a continuous turn-move vector program 00373 00374 if(program_run_init == 1) { 00375 // Setup the LEDs to red 00376 set_leds(0x00,0xFF); 00377 set_center_led(1,1); 00378 program_run_init = 0; 00379 random_walk_bearing = rand() % 360; 00380 } 00381 00382 // When step_cycle = 0 we calculate a vector to move to and a target distance 00383 if(step_cycle == 0) { 00384 struct FloatVector target_vector; 00385 target_vector.angle = 0; 00386 target_vector.distance = 0; 00387 // Check for near robots within range 00388 for(int i = 1; i < 8; i++) { 00389 if(robots_found[i]) { 00390 int res_bearing = robots_heading[i]; 00391 res_bearing += 180; 00392 if(res_bearing > 180) res_bearing -= 360; 00393 target_vector = addVector(target_vector,res_bearing,robots_distance[i]); 00394 if(prog_debug) out("Repelled from robot %d at bearing %d, strength %d, resultant b:%f, d:%f\n",i,robots_heading[i],robots_distance[i],target_vector.angle,target_vector.distance); 00395 } 00396 } 00397 if(target_vector.angle!=0){ 00398 set_leds(0xFF,0xFF); 00399 set_center_led(3,1); 00400 } 00401 // Check for obstacles 00402 char obstacle = 0; 00403 int peak_strength = 0; 00404 for(int i=0; i<8; i++){ 00405 if(reflected_sensor_data[i] > peak_strength) peak_strength = reflected_sensor_data[i]; 00406 if(peak_strength > obstacle_avoidance_threshold) obstacle = 1; 00407 } 00408 if(obstacle){ 00409 //Choose new random walk bearing 00410 set_leds(0x00,0xFF); 00411 set_center_led(1,1); 00412 random_walk_bearing = rand() % 360; 00413 int obstacle_bearing = get_bearing_from_ir_array (reflected_sensor_data); 00414 int obs_bearing = obstacle_bearing + 180; 00415 if(obs_bearing > 180) obs_bearing -= 360; 00416 target_vector = addVector(target_vector,obs_bearing,peak_strength); 00417 if(prog_debug) out("Repelled from obstacle at bearing %d, strength %d, resultant b:%f, d:%f\n",obstacle_bearing,peak_strength,target_vector.angle,target_vector.distance); 00418 } 00419 00420 if(target_vector.angle == 0 && target_vector.distance == 0){ 00421 set_leds(0xFF,0x00); 00422 set_center_led(2,1); 00423 random_walk_bearing += 180; 00424 if(random_walk_bearing > 360) random_walk_bearing -= 360; 00425 target_vector.distance = 100; 00426 int current_bearing = 360 - beacon_heading; 00427 //Now work out turn needed to face intended heading 00428 int target_turn = (random_walk_bearing - current_bearing) % 360; 00429 if(target_turn > 180) target_turn -= 360; 00430 if(target_turn < -180) target_turn += 360; 00431 target_vector.angle = target_turn; 00432 if(prog_debug) out("Random walk bearing:%d Current:%d Target:%f\n",random_walk_bearing,current_bearing,target_vector.angle); 00433 } 00434 char wheel_direction = 1; 00435 if(bidirectional){ 00436 // Allow reverse wheel direction 00437 if(target_vector.angle < -90) {target_vector.angle += 180; wheel_direction = 0;} 00438 else if(target_vector.angle > 90) {target_vector.angle -= 180; wheel_direction = 0;} 00439 } 00440 //Now turn to angle 00441 float maximum_turn_angle = get_maximum_turn_angle(BEACON_PERIOD*10); 00442 if(target_vector.angle < 0){ 00443 if(target_vector.angle < -maximum_turn_angle){ 00444 target_vector.angle = -maximum_turn_angle; 00445 target_vector.distance = 100; 00446 } 00447 }else{ 00448 if(target_vector.angle > maximum_turn_angle){ 00449 target_vector.angle = maximum_turn_angle; 00450 target_vector.distance = 100; 00451 } 00452 } 00453 //Set the wheel speed for next action 00454 if(target_vector.distance < 120) target_wheel_speed = 0.25; 00455 else if(target_vector.distance < 240) target_wheel_speed = 0.35; 00456 else if(target_vector.distance < 480) target_wheel_speed = 0.45; 00457 else if(target_vector.distance < 960) target_wheel_speed = 0.55; 00458 else target_wheel_speed = 0.65; 00459 if(wheel_direction == 0) target_wheel_speed = 0-target_wheel_speed; 00460 00461 //Now turn... 00462 time_based_turn_degrees(1, (int) target_vector.angle, 1); 00463 } else time_based_forward(target_wheel_speed,BEACON_PERIOD*6,0); 00464 } 00465 00466 00467 00468 00469 00470 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00471 /// clustering_program 00472 00473 00474 void clustering_program(char invert, char bidirectional) 00475 { 00476 // The clustering program is a continuous turn-move vector program 00477 // In normal mode (invert = 0) it is attracted to same-group robots and repels opposite-group, walls and very close same-group robots 00478 // In invert mode (invert = 1) it avoids same-group and is attracted to opposite group 00479 00480 // Store the robot group: even robots (0) are green, odd robots (1) are red 00481 char group = robot_id % 2; 00482 00483 if(program_run_init == 1) { 00484 // Setup the LEDs based on robot_id 00485 if(group == 0) { 00486 set_leds(0xFF,0x00); 00487 set_center_led(2,1); 00488 } else { 00489 set_leds(0x00,0xFF); 00490 set_center_led(1,1); 00491 } 00492 program_run_init = 0; 00493 random_walk_bearing = rand() % 360; 00494 } 00495 00496 // When step_cycle = 0 we calculate a vector to move to and a target distance 00497 if(step_cycle == 0) { 00498 char avoiding_friend = 0; 00499 struct FloatVector target_vector; 00500 target_vector.angle = 0; 00501 target_vector.distance = 0; 00502 // Check for near robots within range 00503 for(int i = 1; i < 8; i++) { 00504 if(robots_found[i]) { 00505 // Determine if the robot is an attractor or a repellor 00506 char attract = 0; 00507 if((invert==0 && ((i%2) == group)) || (invert==1 && ((i%2) != group))) attract = 1; 00508 // Avoid very close attractors to stop collisions 00509 if(attract==1 && robots_distance[i] > robot_avoidance_threshold) {attract = 0; avoiding_friend = 1;} 00510 int res_bearing = robots_heading[i]; 00511 if(attract==0){ 00512 res_bearing += 180; 00513 if(res_bearing > 180) res_bearing -= 360; 00514 } 00515 target_vector = addVector(target_vector,res_bearing,robots_distance[i]); 00516 if(prog_debug) { 00517 if(attract) { 00518 out("Attracted to robot %d at bearing %d, strength %d, resultant b:%f, d:%f\n",i,robots_heading[i],robots_distance[i],target_vector.angle,target_vector.distance); 00519 } else { 00520 out("Repelled from robot %d at bearing %d, strength %d, resultant b:%f, d:%f\n",i,robots_heading[i],robots_distance[i],target_vector.angle,target_vector.distance); 00521 } 00522 } 00523 } 00524 } 00525 00526 // Check for obstacles 00527 char obstacle = 0; 00528 int peak_strength = 0; 00529 for(int i=0; i<8; i++){ 00530 if(reflected_sensor_data[i] > peak_strength) peak_strength = reflected_sensor_data[i]; 00531 if(peak_strength > obstacle_avoidance_threshold) obstacle = 1; 00532 } 00533 if(obstacle){ 00534 //Choose new random walk bearing 00535 random_walk_bearing = rand() % 360; 00536 int obstacle_bearing = get_bearing_from_ir_array (reflected_sensor_data); 00537 int obs_bearing = obstacle_bearing + 180; 00538 if(obs_bearing > 180) obs_bearing -= 360; 00539 target_vector = addVector(target_vector,obs_bearing,peak_strength); 00540 if(prog_debug) out("Repelled from obstacle at bearing %d, strength %d, resultant b:%f, d:%f\n",obstacle_bearing,peak_strength,target_vector.angle,target_vector.distance); 00541 } 00542 if(target_vector.angle == 0 && target_vector.distance == 0){ 00543 //I have nothing attracting me so persist with random walk: with a 2% chance pick new bearing 00544 if(rand() % 100 > 97) random_walk_bearing = rand() % 360; 00545 target_vector.distance = 100; 00546 int current_bearing = 360 - beacon_heading; 00547 //Now work out turn needed to face intended heading 00548 int target_turn = (random_walk_bearing - current_bearing) % 360; 00549 if(target_turn > 180) target_turn -= 360; 00550 if(target_turn < -180) target_turn += 360; 00551 target_vector.angle = target_turn; 00552 if(prog_debug) out("Random walk bearing:%d Current:%d Target:%f\n",random_walk_bearing,current_bearing,target_vector.angle); 00553 } 00554 char wheel_direction = 1; 00555 if(bidirectional){ 00556 // Allow reverse wheel direction 00557 if(target_vector.angle < -90) {target_vector.angle += 180; wheel_direction = 0;} 00558 else if(target_vector.angle > 90) {target_vector.angle -= 180; wheel_direction = 0;} 00559 } 00560 //Now turn to angle 00561 float maximum_turn_angle = get_maximum_turn_angle(BEACON_PERIOD*10); 00562 if(target_vector.angle < 0){ 00563 if(target_vector.angle < -maximum_turn_angle){ 00564 target_vector.angle = -maximum_turn_angle; 00565 target_vector.distance = 100; 00566 } 00567 }else{ 00568 if(target_vector.angle > maximum_turn_angle){ 00569 target_vector.angle = maximum_turn_angle; 00570 target_vector.distance = 100; 00571 } 00572 } 00573 if(avoiding_friend) target_vector.distance = 100; 00574 //Set the wheel speed for next action 00575 if(target_vector.distance < 120) target_wheel_speed = 0.25; 00576 else if(target_vector.distance < 240) target_wheel_speed = 0.35; 00577 else if(target_vector.distance < 480) target_wheel_speed = 0.5; 00578 else if(target_vector.distance < 960) target_wheel_speed = 0.65; 00579 else target_wheel_speed = 0.85; 00580 if(wheel_direction == 0) target_wheel_speed = 0-target_wheel_speed; 00581 00582 //Now turn... 00583 time_based_turn_degrees(1, (int) target_vector.angle, 1); 00584 } else time_based_forward(target_wheel_speed,BEACON_PERIOD*7,0); 00585 } 00586 00587 00588 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00589 /// stop_program - Pauses robot 00590 00591 void stop_program() 00592 { 00593 if(program_run_init == 1) { 00594 save_led_states(); 00595 set_leds(0,0); 00596 set_center_led(0,0); 00597 stop(); 00598 program_run_init = 0; 00599 } 00600 } 00601 00602 00603 00604 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00605 /// tag_game_program 00606 00607 enum tag_game_role {hunter, hunted}; 00608 enum tag_game_role role; 00609 int tag_distance = 500; 00610 char hunters[8]; // Memory of which robots have come within tag distance - assumed to be hunters 00611 Timeout hunter_timeout; // Timeout before robots switch back to being hunted 00612 char initial_hunter = 2; // Robot with this ID is permanently a hunter 00613 00614 // Resets hunter robots to hunted after timeout 00615 void role_reset() 00616 { 00617 role = hunted; 00618 set_program_info("HUNTED"); 00619 // Clear memory of hunters 00620 for(int i = 0; i < 8; i++) 00621 hunters[i] = 0; 00622 } 00623 00624 void tag_game_program() 00625 { 00626 // Initialisation 00627 if(program_run_init == 1) { 00628 00629 // Set robot roles 00630 if(robot_id == initial_hunter){ 00631 role = hunter; 00632 set_program_info("FIRST HUNTER"); 00633 } 00634 else { 00635 role = hunted; 00636 set_program_info("HUNTED"); 00637 } 00638 // Clear memory of hunters 00639 for(int i = 0; i < 8; i++) 00640 hunters[i] = 0; 00641 00642 program_run_init = 0; 00643 } 00644 00645 // Bias forward movement 00646 float left_motor_speed = 0.5; 00647 float right_motor_speed = 0.5; 00648 00649 // Check the front sensors for obstacles 00650 if(reflected_sensor_data[0] > obstacle_avoidance_threshold || 00651 reflected_sensor_data[1] > obstacle_avoidance_threshold || 00652 reflected_sensor_data[6] > obstacle_avoidance_threshold || 00653 reflected_sensor_data[7] > obstacle_avoidance_threshold) 00654 { 00655 // Ignore the rear sensors when calculating the heading 00656 reflected_sensor_data[2] = 0; 00657 reflected_sensor_data[3] = 0; 00658 reflected_sensor_data[4] = 0; 00659 reflected_sensor_data[5] = 0; 00660 00661 // Get heading of sensed obstacle 00662 int heading = get_bearing_from_ir_array(reflected_sensor_data); 00663 00664 // Turn in opposite direction 00665 if(heading > 0 && heading < 90) 00666 { 00667 left_motor_speed -= 0.75; 00668 right_motor_speed += 0.5; 00669 } 00670 else if(heading < 0 && heading > -90) 00671 { 00672 left_motor_speed += 0.5; 00673 right_motor_speed -= 0.75; 00674 } 00675 00676 set_left_motor_speed(left_motor_speed); 00677 set_right_motor_speed(right_motor_speed); 00678 00679 // Return early - obstacle avoidance is the top priority 00680 return; 00681 } 00682 00683 int closest_robot = -1; 00684 unsigned short shortest_distance = 0; 00685 00686 // Check whether there are any other robots within range 00687 for(int i = 0; i < 8; i++) 00688 { 00689 if(robots_found[i]) 00690 { 00691 if(robots_distance[i] > shortest_distance) 00692 { 00693 shortest_distance = robots_distance[i]; 00694 closest_robot = i; 00695 } 00696 } 00697 } 00698 00699 // If the closest robot is within tag distance, this robot has been tagged 00700 if(shortest_distance > tag_distance) 00701 { 00702 // Switch role to hunter 00703 if(role == hunted) 00704 { 00705 role = hunter; 00706 set_program_info("NEW HUNTER"); 00707 // Reset to hunted after 10 seconds 00708 hunter_timeout.attach(&role_reset, 10); 00709 } 00710 00711 // Keep a record of which robot tagged them, so hunters do not chase hunters 00712 // Unless they are the initial hunter, who is aggresive towards everyone 00713 if(robot_id != initial_hunter) 00714 hunters[closest_robot] = 1; 00715 } 00716 00717 if(role == hunter) 00718 { 00719 // Set LEDS to red 00720 set_leds(0x00, 0xFF); 00721 set_center_led(1, 1); 00722 00723 if(closest_robot >= 0 && !hunters[closest_robot]) // Ignore other hunters 00724 { 00725 // Turn towards closest hunted robot (unless it is straight ahead, or behind) 00726 if(robots_heading[closest_robot] > 22.5 && robots_heading[closest_robot] < 90) 00727 { 00728 left_motor_speed += 0.5; 00729 right_motor_speed -= 0.5; 00730 } 00731 else if(robots_heading[closest_robot] < -22.5 && robots_heading[closest_robot] > -90) 00732 { 00733 left_motor_speed -= 0.5; 00734 right_motor_speed += 0.5; 00735 } 00736 } 00737 00738 set_left_motor_speed(left_motor_speed); 00739 set_right_motor_speed(right_motor_speed); 00740 } 00741 else // role == hunted 00742 { 00743 // Set LEDs to green 00744 set_leds(0xFF, 0x00); 00745 set_center_led(2, 1); 00746 00747 // Avoid everyone 00748 if(closest_robot >= 0) 00749 { 00750 // Turn away from closest robot 00751 if(robots_heading[closest_robot] >= 0 && robots_heading[closest_robot] < 90) 00752 { 00753 left_motor_speed -= 0.5; 00754 right_motor_speed += 0.5; 00755 } 00756 else if(robots_heading[closest_robot] < 0 && robots_heading[closest_robot] > -90) 00757 { 00758 left_motor_speed += 0.5; 00759 right_motor_speed -= 0.5; 00760 } 00761 } 00762 00763 set_left_motor_speed(left_motor_speed); 00764 set_right_motor_speed(right_motor_speed); 00765 } 00766 } 00767 00768 00769 // mock flocking program 00770 00771 void mockFlocking() 00772 { 00773 float left_motor_speed = 0.5; 00774 float right_motor_speed = 0.5; 00775 char buffer[255]; 00776 00777 00778 if (reflected_sensor_data[0] > 600){ //adjust because of high reading from robot 3 00779 left_motor_speed = -0.5; 00780 set_left_motor_speed(left_motor_speed); 00781 set_right_motor_speed(right_motor_speed); 00782 //display.write_string("Walking R"); 00783 } 00784 else if (reflected_sensor_data[7] > 600){ 00785 right_motor_speed = -0.5; 00786 set_left_motor_speed(left_motor_speed); 00787 set_right_motor_speed(right_motor_speed); 00788 //display.write_string("Walking L"); 00789 } 00790 else if (robot_id == 1) { 00791 display.clear_display(); 00792 display.set_position(0,0); 00793 display.write_string("my Id is 1!"); 00794 float left_motor_speed = 0.3; 00795 float right_motor_speed = 0.3; 00796 int turnChance = rand() %100; 00797 if (turnChance < 20) { 00798 left_motor_speed = 0; 00799 } else if (turnChance > 80) { 00800 right_motor_speed = 0; 00801 } 00802 00803 set_left_motor_speed(left_motor_speed); 00804 set_right_motor_speed(right_motor_speed); 00805 } 00806 else { 00807 00808 if (abs(robots_heading[1]) > 40 && robots_found[1] == 1) { 00809 time_based_turn_degrees(1, robots_heading[1], 1); 00810 sprintf(buffer,"%d > 40", robots_heading[1]); 00811 display.clear_display(); 00812 display.set_position(0,0); 00813 display.write_string(buffer); 00814 } 00815 else { 00816 //used for time based turn instead of location based 00817 set_left_motor_speed(0.5); 00818 set_right_motor_speed(0.5); 00819 } 00820 } 00821 00822 } 00823 00824 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 00825 /// generic_program - Framework for building typical programs 00826 00827 void generic_program() 00828 { 00829 // Do something on the first run of a program 00830 if(program_run_init == 1) { 00831 // Initialisation code goes here... 00832 00833 program_run_init = 0; 00834 } 00835 00836 // step_cycle is either zero or one; use this avoid estimating bearings on the cycle after a turn (as the results will be skewed by the turn) 00837 if(step_cycle == 0) { 00838 // Do something based on sensor data (eg turn) 00839 } else { 00840 // Do something ignoring sensor data (eg move, or nothing!) 00841 } 00842 00843 }
Generated on Thu Jul 14 2022 08:02:39 by
1.7.2
