Psi Swarm Code V0.41 [With Beautiful Meme program]
Dependencies: PsiSwarmLibrary mbed
Fork of BeautifulMemeProjectBT by
Diff: programs.cpp
- Revision:
- 30:513457c1ad12
- Parent:
- 29:9756004e8499
--- a/programs.cpp Thu Mar 03 23:22:01 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,869 +0,0 @@ -/// PsiSwarm Beautiful Meme Project Source Code -/// Version 0.4 -/// James Hilder, Alan Millard, Homero Elizondo, Jon Timmis -/// University of York - -// programs.cpp - Various PsiSwarm Programs for Beautiful Meme Project - -#include "main.h" - -int obstacle_avoidance_threshold = 300; -int robot_avoidance_threshold = 2000; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// head_to_bearing_program -char was_turning = 0; - -///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 -void head_to_bearing_program(int target_bearing) -{ - if(step_cycle == 0 || was_turning == 0) { - // Check if we are heading in the right bearing (+- 25 degrees) - int current_bearing = (360 - beacon_heading) % 360; - // Current bearing should range from 0 to 359; target_bearing likewise; check the are within 25 degrees of each other - char bearing_ok = 0; - int lower_bound = target_bearing - 25; - int upper_bound = target_bearing + 25; - if(lower_bound < 0) { - if(current_bearing > (lower_bound + 360) || current_bearing < upper_bound) bearing_ok = 1; - } else if(upper_bound > 359) { - if(current_bearing > lower_bound || current_bearing < (upper_bound - 360)) bearing_ok = 1; - } else if(current_bearing > lower_bound && current_bearing < upper_bound) bearing_ok = 1; - // Check if there is an obstacle in front of us - if((reflected_sensor_data[7] > 1000 || reflected_sensor_data[0] > 1000) && bearing_ok == 1) target_reached = 1; - else { - // Now move forward if we are facing correct bearing, otherwise turn - if(bearing_ok == 1) { - //Check if anything is in front of us to determine speed - if it is, move slowly - int t_time = 6 * BEACON_PERIOD; - float t_speed = 1.0; - if(reflected_sensor_data[7] > 150 || reflected_sensor_data[0] > 150) { - t_time = 4 * BEACON_PERIOD; - t_speed = 0.6; - } - if(reflected_sensor_data[7] > 300 || reflected_sensor_data[0] > 300) { - t_time = 3 * BEACON_PERIOD; - t_speed = 0.4; - } - if(reflected_sensor_data[7] > 500 || reflected_sensor_data[0] > 500) { - t_time = 2 * BEACON_PERIOD; - t_speed = 0.2; - } - time_based_forward(t_speed,t_time,0); - was_turning = 0; - } else { - turn_to_bearing(target_bearing); - was_turning = 1; - } - } - } -} - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// recharging_program - -char recharge_power_check_count = 0; -char battery_low_count = 0; - -void recharging_program() -{ - switch(recharging_state) { - case 0: - // We are not currently recharging, check the battery state - if(get_battery_voltage() < battery_low_threshold) { - // Battery is below low threshold - battery_low_count ++; - // 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 - if(battery_low_count > 3) { - // Set recharging state to 'looking for charger' - recharging_state = 1; - strcpy(prog_name,"CHARGING PROGRAM"); - set_program_info("HEAD TO BEACON"); - } - } else battery_low_count = 0; - break; - // State 1: Head to beacon [as this is where battery charger is] - case 1: - target_reached = 0; - head_to_bearing_program(0); - if(target_reached == 1) { - recharging_state = 2; - set_program_info("TURN 90 DEGREES"); - } - break; - // Stage 2: Turn 90 degrees to align with charging pads - case 2: - disable_ir_emitters = 1; - time_based_turn_degrees(0.8, 70.0, 1); - recharge_power_check_count = 0; - recharging_state = 3; - break; - // Stage 3: Wait for turn to complete - case 3: - if (time_based_motor_action != 1) { - recharging_state = 4; - set_program_info("CHECK FOR POWER"); - } - break; - // Stage 4: Check if charging - case 4: - recharge_power_check_count++; - if(get_dc_status() == 1) { - recharging_state = 5; - } else { - if(recharge_power_check_count < 10)recharging_state = 6; - else { - recharging_state = 7; - set_program_info("NO POWER - RETRY"); - } - } - break; - // Stage 5: Charging. Wait until threshold voltage exceeded - case 5: - if(get_battery_voltage() > battery_high_threshold) { - set_program_info("LEAVE CHARGER"); - recharging_state = 7; - } else { - char b_voltage[16]; - sprintf(b_voltage,"CHARGE: %1.3fV",get_battery_voltage()); - set_program_info(b_voltage); - } - break; - // Stage 6: We didn't find power, keep turning a couple of degrees at a time a recheck - case 6: - time_based_turn_degrees(0.5,4,1); - recharging_state = 4; - break; - // Stage 7: Charge may be finished. Turn 90 degrees then move away and resume previous program - case 7: - time_based_turn_degrees(0.8, 90.0, 1); - recharging_state = 8; - break; - - // Stage 8: Wait for turn to complete - case 8: - if (time_based_motor_action != 1) recharging_state = 9; - break; - // Stage 9: Move away - case 9: - time_based_forward(0.5, 1000000, 1); - recharging_state = 10; - break; - // Stage 10: Wait for move to complete - case 10: - if (time_based_motor_action != 1) recharging_state = 11; - break; - // Stage 11: Check if battery is below low threshold; if it is, start over, else end charge cycle - case 11: - disable_ir_emitters = 0; - if (get_battery_voltage() < battery_low_threshold) { - recharging_state = 1; - } else { - recharging_state = 0; - //Restore name of old program on display - set_program(main_program_state); - } - break; - } -} - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// curved_walk_with_interaction_program (Alan's Random Walk\Obstacle Avoid and Robot Interaction Program) - -enum random_walk_state {random_walk, turn_towards, interact, turn_away, avoid_obstacle}; -enum random_walk_state internal_state = random_walk; -char action_timeout = 0; -char interaction_timeout = 0; -char random_walk_timeout = 0; -float previous_left_motor_speed = 0.5; -float previous_right_motor_speed = 0.5; - -void curved_random_walk_with_interaction_program() -{ - if(internal_state == random_walk) { - if(interaction_timeout < 4) - interaction_timeout++; - - int closest_robot = -1; - unsigned short shortest_distance = 0; - - // Check whether there are any other robots within range - for(int i = 0; i < 8; i++) { - if(robots_found[i]) { - if(robots_distance[i] > shortest_distance) { - shortest_distance = robots_distance[i]; - closest_robot = i; - } - } - } - - // Turn towards the closest robot - if(closest_robot >= 0 && shortest_distance > 300 && interaction_timeout >= 4) { - time_based_turn_degrees(1, robots_heading[closest_robot], 1); - - action_timeout = 0; - internal_state = turn_towards; - char temp_message[17]; - sprintf(temp_message,"FACE ROBOT %d",closest_robot); - set_program_info(temp_message); - } else { // Otherwise, do a random walk - // Check the front sensors for obstacles - if(reflected_sensor_data[0] > obstacle_avoidance_threshold || - reflected_sensor_data[1] > obstacle_avoidance_threshold || - reflected_sensor_data[6] > obstacle_avoidance_threshold || - reflected_sensor_data[7] > obstacle_avoidance_threshold) { - // Ignore the rear sensors when calculating the heading - reflected_sensor_data[2] = 0; - reflected_sensor_data[3] = 0; - reflected_sensor_data[4] = 0; - reflected_sensor_data[5] = 0; - - // Turn 180 degrees away from the sensed obstacle - int heading = get_bearing_from_ir_array (reflected_sensor_data) + 180; - - // Normalise - heading %= 360; - - if(heading < -180) - heading += 360; - - if(heading > 180) - heading -= 360; - set_program_info("AVOID OBSTACLE"); - time_based_turn_degrees(1, heading, 1); - - action_timeout = 0; - internal_state = turn_away; - } else { - // Change motor speeds every 1s - if(random_walk_timeout >= 2) { - float random_offset = (((float) rand() / (float) RAND_MAX) - 0.5) * 0.5; - - float left_motor_speed = previous_left_motor_speed - random_offset; - float right_motor_speed = previous_right_motor_speed + random_offset; - - float threshold = 0.25; - - if(left_motor_speed < threshold) - left_motor_speed = threshold; - - if(right_motor_speed < threshold) - right_motor_speed = threshold; - - set_left_motor_speed(left_motor_speed); - set_right_motor_speed(right_motor_speed); - - random_walk_timeout = 0; - } - - random_walk_timeout++; - } - } - } else if(internal_state == turn_towards) { - if(action_timeout < 4) - action_timeout++; - else { - set_program_info("SAY HELLO"); - vibrate(); - - action_timeout = 0; - internal_state = interact; - } - } else if(internal_state == interact) { - if(action_timeout < 4) - action_timeout++; - else { - set_program_info("TURN AROUND"); - time_based_turn_degrees(1, 180, 1); - - action_timeout = 0; - internal_state = turn_away; - } - - } else if(internal_state == turn_away) { - if(action_timeout < 4) - action_timeout++; - else { - set_program_info("RANDOM WALK"); - interaction_timeout = 0; - internal_state = random_walk; - } - } else if(internal_state == avoid_obstacle) { - if(action_timeout < 4) - action_timeout++; - else - set_program_info("RANDOM WALK"); - internal_state = random_walk; - } -} - - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// straight_random_walk_with_interaction_program - -void straight_random_walk_with_interaction_program() -{ - -} - - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// find_space_program - -char prog_debug = 1 ; -float target_wheel_speed; -int random_walk_bearing; - -void find_space_program(char bidirectional) -{ - // The find_space_program is a continuous turn-move vector program - - if(program_run_init == 1) { - // Setup the LEDs to red - set_leds(0x00,0xFF); - set_center_led(1,1); - program_run_init = 0; - random_walk_bearing = rand() % 360; - } - - // When step_cycle = 0 we calculate a vector to move to and a target distance - if(step_cycle == 0) { - struct FloatVector target_vector; - target_vector.angle = 0; - target_vector.distance = 0; - // Check for near robots within range - for(int i = 1; i < 8; i++) { - if(robots_found[i]) { - int res_bearing = robots_heading[i]; - res_bearing += 180; - if(res_bearing > 180) res_bearing -= 360; - target_vector = addVector(target_vector,res_bearing,robots_distance[i]); - 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); - } - } - if(target_vector.angle!=0){ - set_leds(0xFF,0xFF); - set_center_led(3,1); - } - // Check for obstacles - char obstacle = 0; - int peak_strength = 0; - for(int i=0; i<8; i++){ - if(reflected_sensor_data[i] > peak_strength) peak_strength = reflected_sensor_data[i]; - if(peak_strength > obstacle_avoidance_threshold) obstacle = 1; - } - if(obstacle){ - //Choose new random walk bearing - set_leds(0x00,0xFF); - set_center_led(1,1); - random_walk_bearing = rand() % 360; - int obstacle_bearing = get_bearing_from_ir_array (reflected_sensor_data); - int obs_bearing = obstacle_bearing + 180; - if(obs_bearing > 180) obs_bearing -= 360; - target_vector = addVector(target_vector,obs_bearing,peak_strength); - 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); - } - - if(target_vector.angle == 0 && target_vector.distance == 0){ - set_leds(0xFF,0x00); - set_center_led(2,1); - random_walk_bearing += 180; - if(random_walk_bearing > 360) random_walk_bearing -= 360; - target_vector.distance = 100; - int current_bearing = 360 - beacon_heading; - //Now work out turn needed to face intended heading - int target_turn = (random_walk_bearing - current_bearing) % 360; - if(target_turn > 180) target_turn -= 360; - if(target_turn < -180) target_turn += 360; - target_vector.angle = target_turn; - if(prog_debug) out("Random walk bearing:%d Current:%d Target:%f\n",random_walk_bearing,current_bearing,target_vector.angle); - } - char wheel_direction = 1; - if(bidirectional){ - // Allow reverse wheel direction - if(target_vector.angle < -90) {target_vector.angle += 180; wheel_direction = 0;} - else if(target_vector.angle > 90) {target_vector.angle -= 180; wheel_direction = 0;} - } - //Now turn to angle - float maximum_turn_angle = get_maximum_turn_angle(BEACON_PERIOD*10); - if(target_vector.angle < 0){ - if(target_vector.angle < -maximum_turn_angle){ - target_vector.angle = -maximum_turn_angle; - target_vector.distance = 100; - } - }else{ - if(target_vector.angle > maximum_turn_angle){ - target_vector.angle = maximum_turn_angle; - target_vector.distance = 100; - } - } - //Set the wheel speed for next action - if(target_vector.distance < 120) target_wheel_speed = 0.25; - else if(target_vector.distance < 240) target_wheel_speed = 0.35; - else if(target_vector.distance < 480) target_wheel_speed = 0.45; - else if(target_vector.distance < 960) target_wheel_speed = 0.55; - else target_wheel_speed = 0.65; - if(wheel_direction == 0) target_wheel_speed = 0-target_wheel_speed; - - //Now turn... - time_based_turn_degrees(1, (int) target_vector.angle, 1); - } else time_based_forward(target_wheel_speed,BEACON_PERIOD*6,0); -} - - - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// clustering_program - - -void clustering_program(char invert, char bidirectional) -{ - // The clustering program is a continuous turn-move vector program - // In normal mode (invert = 0) it is attracted to same-group robots and repels opposite-group, walls and very close same-group robots - // In invert mode (invert = 1) it avoids same-group and is attracted to opposite group - - // Store the robot group: even robots (0) are green, odd robots (1) are red - char group = robot_id % 2; - - if(program_run_init == 1) { - // Setup the LEDs based on robot_id - if(group == 0) { - set_leds(0xFF,0x00); - set_center_led(2,1); - } else { - set_leds(0x00,0xFF); - set_center_led(1,1); - } - program_run_init = 0; - random_walk_bearing = rand() % 360; - } - - // When step_cycle = 0 we calculate a vector to move to and a target distance - if(step_cycle == 0) { - char avoiding_friend = 0; - struct FloatVector target_vector; - target_vector.angle = 0; - target_vector.distance = 0; - // Check for near robots within range - for(int i = 1; i < 8; i++) { - if(robots_found[i]) { - // Determine if the robot is an attractor or a repellor - char attract = 0; - if((invert==0 && ((i%2) == group)) || (invert==1 && ((i%2) != group))) attract = 1; - // Avoid very close attractors to stop collisions - if(attract==1 && robots_distance[i] > robot_avoidance_threshold) {attract = 0; avoiding_friend = 1;} - int res_bearing = robots_heading[i]; - if(attract==0){ - res_bearing += 180; - if(res_bearing > 180) res_bearing -= 360; - } - target_vector = addVector(target_vector,res_bearing,robots_distance[i]); - if(prog_debug) { - if(attract) { - 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); - } else { - 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); - } - } - } - } - - // Check for obstacles - char obstacle = 0; - int peak_strength = 0; - for(int i=0; i<8; i++){ - if(reflected_sensor_data[i] > peak_strength) peak_strength = reflected_sensor_data[i]; - if(peak_strength > obstacle_avoidance_threshold) obstacle = 1; - } - if(obstacle){ - //Choose new random walk bearing - random_walk_bearing = rand() % 360; - int obstacle_bearing = get_bearing_from_ir_array (reflected_sensor_data); - int obs_bearing = obstacle_bearing + 180; - if(obs_bearing > 180) obs_bearing -= 360; - target_vector = addVector(target_vector,obs_bearing,peak_strength); - 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); - } - if(target_vector.angle == 0 && target_vector.distance == 0){ - //I have nothing attracting me so persist with random walk: with a 2% chance pick new bearing - if(rand() % 100 > 97) random_walk_bearing = rand() % 360; - target_vector.distance = 100; - int current_bearing = 360 - beacon_heading; - //Now work out turn needed to face intended heading - int target_turn = (random_walk_bearing - current_bearing) % 360; - if(target_turn > 180) target_turn -= 360; - if(target_turn < -180) target_turn += 360; - target_vector.angle = target_turn; - if(prog_debug) out("Random walk bearing:%d Current:%d Target:%f\n",random_walk_bearing,current_bearing,target_vector.angle); - } - char wheel_direction = 1; - if(bidirectional){ - // Allow reverse wheel direction - if(target_vector.angle < -90) {target_vector.angle += 180; wheel_direction = 0;} - else if(target_vector.angle > 90) {target_vector.angle -= 180; wheel_direction = 0;} - } - //Now turn to angle - float maximum_turn_angle = get_maximum_turn_angle(BEACON_PERIOD*10); - if(target_vector.angle < 0){ - if(target_vector.angle < -maximum_turn_angle){ - target_vector.angle = -maximum_turn_angle; - target_vector.distance = 100; - } - }else{ - if(target_vector.angle > maximum_turn_angle){ - target_vector.angle = maximum_turn_angle; - target_vector.distance = 100; - } - } - if(avoiding_friend) target_vector.distance = 100; - //Set the wheel speed for next action - if(target_vector.distance < 120) target_wheel_speed = 0.25; - else if(target_vector.distance < 240) target_wheel_speed = 0.35; - else if(target_vector.distance < 480) target_wheel_speed = 0.5; - else if(target_vector.distance < 960) target_wheel_speed = 0.65; - else target_wheel_speed = 0.85; - if(wheel_direction == 0) target_wheel_speed = 0-target_wheel_speed; - - //Now turn... - time_based_turn_degrees(1, (int) target_vector.angle, 1); - } else time_based_forward(target_wheel_speed,BEACON_PERIOD*7,0); -} - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// stop_program - Pauses robot - -void stop_program() -{ - if(program_run_init == 1) { - save_led_states(); - set_leds(0,0); - set_center_led(0,0); - stop(); - program_run_init = 0; - } -} - - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// tag_game_program - -enum tag_game_role {hunter, hunted}; -enum tag_game_role role; -int tag_distance = 500; -char hunters[8]; // Memory of which robots have come within tag distance - assumed to be hunters -Timeout hunter_timeout; // Timeout before robots switch back to being hunted -char initial_hunter = 2; // Robot with this ID is permanently a hunter - -// Resets hunter robots to hunted after timeout -void role_reset() -{ - role = hunted; - set_program_info("HUNTED"); - // Clear memory of hunters - for(int i = 0; i < 8; i++) - hunters[i] = 0; -} - -void tag_game_program() -{ - // Initialisation - if(program_run_init == 1) { - - // Set robot roles - if(robot_id == initial_hunter){ - role = hunter; - set_program_info("FIRST HUNTER"); - } - else { - role = hunted; - set_program_info("HUNTED"); - } - // Clear memory of hunters - for(int i = 0; i < 8; i++) - hunters[i] = 0; - - program_run_init = 0; - } - - // Bias forward movement - float left_motor_speed = 0.5; - float right_motor_speed = 0.5; - - // Check the front sensors for obstacles - if(reflected_sensor_data[0] > obstacle_avoidance_threshold || - reflected_sensor_data[1] > obstacle_avoidance_threshold || - reflected_sensor_data[6] > obstacle_avoidance_threshold || - reflected_sensor_data[7] > obstacle_avoidance_threshold) - { - // Ignore the rear sensors when calculating the heading - reflected_sensor_data[2] = 0; - reflected_sensor_data[3] = 0; - reflected_sensor_data[4] = 0; - reflected_sensor_data[5] = 0; - - // Get heading of sensed obstacle - int heading = get_bearing_from_ir_array(reflected_sensor_data); - - // Turn in opposite direction - if(heading > 0 && heading < 90) - { - left_motor_speed -= 0.75; - right_motor_speed += 0.5; - } - else if(heading < 0 && heading > -90) - { - left_motor_speed += 0.5; - right_motor_speed -= 0.75; - } - - set_left_motor_speed(left_motor_speed); - set_right_motor_speed(right_motor_speed); - - // Return early - obstacle avoidance is the top priority - return; - } - - int closest_robot = -1; - unsigned short shortest_distance = 0; - - // Check whether there are any other robots within range - for(int i = 0; i < 8; i++) - { - if(robots_found[i]) - { - if(robots_distance[i] > shortest_distance) - { - shortest_distance = robots_distance[i]; - closest_robot = i; - } - } - } - - // If the closest robot is within tag distance, this robot has been tagged - if(shortest_distance > tag_distance) - { - // Switch role to hunter - if(role == hunted) - { - role = hunter; - set_program_info("NEW HUNTER"); - // Reset to hunted after 10 seconds - hunter_timeout.attach(&role_reset, 10); - } - - // Keep a record of which robot tagged them, so hunters do not chase hunters - // Unless they are the initial hunter, who is aggresive towards everyone - if(robot_id != initial_hunter) - hunters[closest_robot] = 1; - } - - if(role == hunter) - { - // Set LEDS to red - set_leds(0x00, 0xFF); - set_center_led(1, 1); - - if(closest_robot >= 0 && !hunters[closest_robot]) // Ignore other hunters - { - // Turn towards closest hunted robot (unless it is straight ahead, or behind) - if(robots_heading[closest_robot] > 22.5 && robots_heading[closest_robot] < 90) - { - left_motor_speed += 0.5; - right_motor_speed -= 0.5; - } - else if(robots_heading[closest_robot] < -22.5 && robots_heading[closest_robot] > -90) - { - left_motor_speed -= 0.5; - right_motor_speed += 0.5; - } - } - - set_left_motor_speed(left_motor_speed); - set_right_motor_speed(right_motor_speed); - } - else // role == hunted - { - // Set LEDs to green - set_leds(0xFF, 0x00); - set_center_led(2, 1); - - // Avoid everyone - if(closest_robot >= 0) - { - // Turn away from closest robot - if(robots_heading[closest_robot] >= 0 && robots_heading[closest_robot] < 90) - { - left_motor_speed -= 0.5; - right_motor_speed += 0.5; - } - else if(robots_heading[closest_robot] < 0 && robots_heading[closest_robot] > -90) - { - left_motor_speed += 0.5; - right_motor_speed -= 0.5; - } - } - - set_left_motor_speed(left_motor_speed); - set_right_motor_speed(right_motor_speed); - } -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// flocking_program - -void flocking_program() -{ - char display_line[16] = " "; - int average_heading = 0; - int number_of_neighbours = 0; - int number_of_flocking_headings = 0; - int target_heading = 0; - int angles = 0; - int ir_sensor_threshold = 600; - int sensors_activated = 0; - - struct FloatVector obstacle_vector; - obstacle_vector.angle = 0; - obstacle_vector.distance = 0; - - struct FloatVector cohesion_vector; - cohesion_vector.angle = 0; - cohesion_vector.distance = 0; - - for(int i = 0; i < 8; i++) - { - if(reflected_sensor_data[i] > ir_sensor_threshold) - { - obstacle_vector = addVector(obstacle_vector, get_bearing_from_ir_array(reflected_sensor_data), reflected_sensor_data[i]); - sensors_activated++; - } - - if(robots_found[i]) - { - // -180 degrees is reserved for "no byte received" - if(flocking_headings[i] != -180) - { - average_heading += flocking_headings[i]; - number_of_flocking_headings++; - } - - cohesion_vector = addVector(cohesion_vector, robots_heading[i], robots_distance[i]); - number_of_neighbours++; - } - } - - cohesion_vector.distance /= number_of_neighbours; // Normalise - obstacle_vector.distance /= sensors_activated; // Normalise - - int obstacle_avoidance_angle; - - if(sensors_activated > 0) - { - obstacle_avoidance_angle = obstacle_vector.angle + 180; - - if(obstacle_avoidance_angle > 180) - obstacle_avoidance_angle -= 360; - if(obstacle_avoidance_angle < -180) - obstacle_avoidance_angle += 360; - - target_heading += obstacle_avoidance_angle; - angles++; - } - - int cohesion_angle; - - // Don't bother performing cohesion if robots are already close enough - if(number_of_neighbours > 0 && cohesion_vector.distance < 200) - { - cohesion_angle = cohesion_vector.angle; - - if(cohesion_angle > 180) - cohesion_angle -= 360; - if(cohesion_angle < -180) - cohesion_angle += 360; - - target_heading += cohesion_angle; - angles++; - } - - int relative_flocking_heading; - - if(number_of_flocking_headings > 0) - { - average_heading /= number_of_flocking_headings; - - relative_flocking_heading = beacon_heading - average_heading; - - if(relative_flocking_heading > 180) - relative_flocking_heading -= 360; - if(relative_flocking_heading < -180) - relative_flocking_heading += 360; - - target_heading += relative_flocking_heading; - angles++; - } - - if(angles > 0) - target_heading /= angles; // Calculate average - - float left_motor_speed = 0.25; - float right_motor_speed = 0.25; - - if(target_heading > 22.5) - right_motor_speed *= -1; - else if(target_heading < -22.5) - left_motor_speed *= -1; - - set_left_motor_speed(left_motor_speed); - set_right_motor_speed(right_motor_speed); - - // Only transmit beacon heading if the beacon is visible - if(beacon_found) - { - float degrees_per_value = 256.0f / 360.0f; - char beacon_heading_byte = (beacon_heading + 180) * degrees_per_value; // Convert beacon heading from +/-180 degrees into a single byte value - - bt.putc(beacon_heading_byte); - } - - sprintf(display_line, "%d %d %d %d", target_heading, obstacle_avoidance_angle, cohesion_angle, relative_flocking_heading); - - set_program_info(display_line); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -/// generic_program - Framework for building typical programs - -void generic_program() -{ - // Do something on the first run of a program - if(program_run_init == 1) { - // Initialisation code goes here... - - program_run_init = 0; - } - - // 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) - if(step_cycle == 0) { - // Do something based on sensor data (eg turn) - } else { - // Do something ignoring sensor data (eg move, or nothing!) - } - -} \ No newline at end of file