/**
 * Makes the robot attempt to follow a line, halting should it lose it.
 */
void follow_line()
{
    LineInfo line;
    int movement = 0;
    int integral = 0;
    int previous_error = 0;
    timeval prev_time;
    // Initialize prev_time with the current time
    gettimeofday(&prev_time, nullptr);

    set_speed(SPEED_DEF);

    for (int i = 0; true; i++)
    {
        int error = sample_image(line);

        // Check if we have reached the end of the curvy maze
        if (!line.north && line.east && line.south && line.west)
        {
            printf("ATTEMPT stop\n");
            break;
        }

        // Try reverse if line is lost
        if (line.white_count < STOP_COUNT)
        {
            if (line.east)
            {
                printf("ATTEMPT save right\n");
                set_speed(0);
                turn(75);
                while (!line.north)
                {
                    sample_image(line);
                }
            }
            else if (line.west)
            {
                printf("ATTEMPT save left\n");
                set_speed(0);
                turn(-75);
                while (!line.north)
                {
                    sample_image(line);
                }
            }
            else
            {
                printf("ATTEMPT reverse %i : %i\n", line.white_count, STOP_COUNT);
                set_speed(-SPEED_DEF);
                reset_turn();
                //turn(sign(previous_error) * SPEED_DEF * 1);
                move();
            }
            // We need to get time here as to not mess with the next
            // iteration's derivative
            gettimeofday(&prev_time, nullptr);
            Sleep(0, REVERSE_DELAY);
            i--;
            continue;
        }
        else
        {
            set_speed(SPEED_DEF);
        }

        // Calculate how much to turn by
        int pixels_x = IMAGE_SIZE_X / SAMPLE_STEPS;
        int pixels_y = IMAGE_SIZE_Y / SAMPLE_STEPS;
        // Doing Proportional
        int proportional_error = error / (pow(pixels_x, SCALE_POW) * pixels_y);
        // Doing Integral
        int proportional_integral = i == 0 ? 0 : integral / i;

        // Doing Derivative
        // We need the time in seconds, but not rounded to a second as we'll
        // never spend that long and a time rounded to 0 is worthless. To
        // fix this we get the time in microseconds and add that to the seconds
        double d_time = get_seconds(prev_time);
        int derivative = (proportional_error - previous_error) / d_time;

        // Now to compile all the calculations
        // Start with the proportional component;
        movement = proportional_error * K_P;
        // Add the integral component
        movement += proportional_integral * K_I;
        // Add the derivative component
        movement += derivative * K_D;
        // Update integral component
        integral += proportional_error;
        // Store previous error for the derivative
        previous_error = proportional_error;

        // Turn
        turn(movement);
    }
    halt();
}
Example #2
0
void tduel::pre_show(CVideo& /*video*/, twindow& window)
{
	// Override the user value, to make sure it's set properly.
	window.set_click_dismiss(false);

	// ***** ***** ***** ***** Set up the widgets ***** ***** ***** *****
	window.canvas(1).set_variable("left_image", variant(left_.image(true)));
	window.canvas(1).set_variable("right_image", variant(right_.image(true)));
	window.canvas(1).set_variable("center_image", variant(""));
	
	window.canvas(1).set_variable("hp_left", variant("misc/hp-blue.png"));
	window.canvas(1).set_variable("hp_right", variant("misc/hp-red.png"));
	window.canvas(1).set_variable("percentage", variant((hp_ * 100) / TOTAL_HP));

	std::stringstream str;

	tbutton* b = find_widget<tbutton>(&window, "endturn", false, false);
	for (int i = 0; i < 4; i ++) {
		b->canvas()[i].set_variable("image", variant("misc/ok.png"));
	}

	find_widget<tcontrol>(&window, "lname", false, false)->set_label(left_.name());
	find_widget<tcontrol>(&window, "rname", false, false)->set_label(right_.name());

	tcontrol* control = find_widget<tcontrol>(&window, "lforce", false, false);
	str.str("");
	str << setting_[0].force_ << "(" << hero::adaptability_str2(left_.skill_[hero_skill_hero]).c_str() << ")";
	control->set_label(str.str());

	control = find_widget<tcontrol>(&window, "rforce", false, false);
	str.str("");
	str << setting_[1].force_ << "(" << hero::adaptability_str2(right_.skill_[hero_skill_hero]).c_str() << ")";;
	control->set_label(str.str());

	endturn_ = find_widget<tbutton>(&window, "endturn", false, false);
	connect_signal_mouse_left_click(
		*endturn_
		, boost::bind(
			&tduel::end_turn
			, this
			, boost::ref(window)));
	endturn_->set_sound_button_click("hatchet.wav");
	
	lskill0_ = find_widget<ttoggle_button>(&window, "lskill0", false, false);
	connect_signal_mouse_left_click(
		 *lskill0_
		, boost::bind(
		  &tduel::on_deadfight
		, this
		, boost::ref(window)));

	lskill1_ = find_widget<ttoggle_button>(&window, "lskill1", false, false);
	connect_signal_mouse_left_click(
		 *lskill1_
		, boost::bind(
		  &tduel::on_fightback
		, this
		, boost::ref(window)));
	
	find_widget<ttoggle_button>(&window, "lturn0", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn0_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<tlabel>(&window, "turn0", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn0", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn0_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn1", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn1_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<tlabel>(&window, "turn1", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn1", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn1_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn2", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn2_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<tlabel>(&window, "turn2", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn2", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn2_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn3", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn3_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<tlabel>(&window, "turn3", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn3", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn3_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn4", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "lturn4_skill", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<tlabel>(&window, "turn4", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn4", false, false)->set_visible(twidget::INVISIBLE);
	find_widget<ttoggle_button>(&window, "rturn4_skill", false, false)->set_visible(twidget::INVISIBLE);

	reset_turn(window);
}
void follow_square_line()
{
    LineInfo line;
    int movement = 0;
    int previous_error = 0;
    timeval prev_time;
    // Initialize prev_time with the current time
    gettimeofday(&prev_time, nullptr);

    set_speed(SPEED_DEF);

    while (true)
    {
        int error = sample_image(line);

        // Check left
        if (line.south && line.west)
        {
            printf("ATTEMPT Going square left");
            printf(line.north ? " : line N" : " : line  ");
            printf(line.east ? "E" : " ");
            printf(line.south ? "S" : " ");
            printf(line.west ? "W\n" : "\n");
            Sleep(0, REVERSE_DELAY);
            set_speed(0);
            turn(-TURN_90_SPEED);
            //Sleep(0, TURN_90_DELAY);
            square_line_rotate(line.north);
            set_speed(SPEED_DEF);
            turn(0);
            Sleep(0, TURN_90_DELAY);
        }
        // Check right
        else if (!line.north && line.east && line.south && !line.west)
        {
            printf("ATTEMPT Going square right");
            printf(line.north ? " : line N" : " : line  ");
            printf(line.east ? "E" : " ");
            printf(line.south ? "S" : " ");
            printf(line.west ? "W\n" : "\n");
            Sleep(0, REVERSE_DELAY);
            set_speed(0);
            turn(TURN_90_SPEED);
            // Sleep(0, TURN_90_DELAY);
            square_line_rotate(line.north);
            set_speed(SPEED_DEF);
            turn(0);
            Sleep(0, TURN_90_DELAY);
        }
        // Check center line stop
        else if (!line.north && !line.east && line.south && !line.west)
        {
            printf("ATTEMPT Dead end! Do a barrel roll!");
            printf(line.north ? " : line N" : " : line  ");
            printf(line.east ? "E" : " ");
            printf(line.south ? "S" : " ");
            printf(line.west ? "W\n" : "\n");
            set_speed(0);
            turn(2*TURN_90_SPEED);
            // Sleep(0, TURN_90_DELAY * 2);
            square_line_rotate(false);
            set_speed(SPEED_DEF);
            turn(0);
        }

        // Try reverse if line is lost
        else if (line.white_count < STOP_COUNT)
        {
            printf("ATTEMPT reversing\n");
            set_speed(-SPEED_DEF);
            reset_turn();
            //turn(sign(previous_error) * SPEED_DEF * 1);
            move();
            // We need to get time here as to not mess with the next
            // iteration's derivative
            gettimeofday(&prev_time, nullptr);
            Sleep(0, REVERSE_DELAY / 2);
            continue;
        }
        else {
            // This is here to make the robot go forward after reversing
            set_speed(SPEED_DEF);
        }

        // Calculate how much to turn by
        int pixels_x = IMAGE_SIZE_X / SAMPLE_STEPS;
        int pixels_y = IMAGE_SIZE_Y / SAMPLE_STEPS;
        // Doing Proportional
        int proportional_error = error / (pow(pixels_x, SCALE_POW) * pixels_y);

        // No integral here; with sharp corners it is more likely to throw us
        // off than actually help

        // Doing Derivative
        // We need the time in seconds, but not rounded to a second as we'll
        // never spend that long and a time rounded to 0 is worthless. To
        // fix this we get the time in microseconds and add that to the seconds
        double d_time = get_seconds(prev_time);
        int derivative = (proportional_error - previous_error) / d_time;

        // Now to compile all the calculations
        // Start with the proportional component;
        movement = proportional_error * K_P;
        // Add the derivative component
        movement += derivative * K_D;
        // Store previous error for the derivative
        previous_error = proportional_error;

        // Turn
        turn(movement);
    }
    halt();
}