#include "include/controller.h" void print_point(gbVec2 *point) { printf("position x: %.4f, y: %.4f\n", point->x, point->y); } int controller_init(controller_t *control) { gpio_init(BTN0_PIN,BTN0_MODE); controller_home(control); control->flags = control->stepper_a->flags | control->stepper_b->flags; return 0; } int controller_loop(controller_t *control){ path_node_t *setpoint = (path_node_t*)control->path->current.next; //printf("start controller loop\n"); while(setpoint->list.next != 0x0){ if ((setpoint->point.x > 127) | (setpoint->point.x < 0) | (setpoint->point.y > 127) | (setpoint->point.y < 0 ) ) { printf("Controller Error, x and y value are out of range x: %i, y: %i\n", setpoint->point.x, setpoint->point.y); return CONTROLLER_ERR; } //printf("Controller: look up x: %i, y: %i\n", setpoint->point.x, setpoint->point.y); int16_t angle1 = lookup_table_angle1[setpoint->point.y][setpoint->point.x]; int16_t angle2 = lookup_table_angle2[setpoint->point.y][setpoint->point.x]; //printf("Controller: next setpoint A: %i, B: %i\n",angle1, angle2); stepper_set_setpoint(control->stepper_a, angle1, control->time_step); stepper_set_setpoint(control->stepper_b, angle2, control->time_step); xtimer_usleep(10000); thread_flags_wait_all(control->flags); setpoint = path_next(setpoint); } printf("controller loop done\n"); return CONTROLLER_OK; } /*void controller_update(event_t *event) { controller_t *control = container_of(event, controller_t, event); controller_calculate_velocity(control); event_timeout_set(&(control->event_timeout), control->time_step); } int controller_setpoint(controller_t *control, gbVec2 *point) { control->setpoint = *point; controller_inverse_kinematics(control, point, &control->angle1_setpoint , &control->angle2_setpoint); return 0; } void controller_inverse_kinematics(controller_t *control, gbVec2 *point, float *angle1, float *angle2) { float phi = gb_arctan2(point->y, point->x); float length_a2 = gb_square(control->arm_a); float length_b2 = gb_square(control->arm_b); float length_c2 = gb_vec2_mag2(*point); float length_c = gb_sqrt(length_c2); float b = gb_arccos((length_a2 + length_c2 - length_b2) / (2 * control->arm_a * length_c)); float c = gb_arccos((length_a2 + length_b2 - length_c2) / (2 * control->arm_a * control->arm_b)); *angle1 = b + phi; *angle2 = *angle1 - GB_MATH_PI + c; } void controller_current_position(controller_t *control, gbVec2 *point) { float angle_a; stepper_get_angle(control->stepper_a, &angle_a); float angle_b; stepper_get_angle(control->stepper_b, &angle_b); gbVec2 joint1 = { .x = control->arm_a * gb_cos(angle_a), .y = control->arm_a * gb_sin(angle_a) }; gbVec2 joint2 = { .x = control->arm_b * gb_cos(angle_b), .y = control->arm_b * gb_sin(angle_b) }; gb_vec2_add(point, joint1, joint2); } int controller_calculate_velocity(controller_t *control) { uint32_t setpoint_time; uint32_t ik_time; uint32_t angle_time; uint32_t velocity_time; uint32_t start = xtimer_now_usec(); gbVec2 next_setpoint; int status = controller_sub_setpoint(control, &next_setpoint, 0.005); setpoint_time = xtimer_now_usec(); float angle1; float angle2; controller_inverse_kinematics(control, &next_setpoint, &angle1, &angle2); ik_time = xtimer_now_usec(); float angle_a; stepper_get_angle(control->stepper_a, &angle_a); float angle_b; stepper_get_angle(control->stepper_b, &angle_b); angle_time = xtimer_now_usec(); //printf("angle1: %f, angle2 %f\n", angle1, angle2); //printf("anglea: %f, angleb %f\n", angle_a, angle_b); float omega1 = (angle1-angle_a)*25; float omega2 = (angle2-angle_b)*25; if (status == CONTROLLER_STATISFIED) { omega1 = 0.0; omega2 = 0.0; } // printf("omega1: %f, omega2 %f\n", omega1, omega2); stepper_set_velocity(control->stepper_a, omega1); stepper_set_velocity(control->stepper_b, omega2); velocity_time = xtimer_now_usec(); printf("Setpoint: %lu\n", setpoint_time - start); printf("IK-time: %lu\n", ik_time - setpoint_time); printf("Angles: %lu\n", angle_time - ik_time); printf("velocity: %lu\n", velocity_time - angle_time); return 0; } int controller_sub_setpoint(controller_t *control, gbVec2 *setpoint, float distance) { // TODO: if the length is shorten than the distance, do not scale it up // TODO: if the length is zero. Do nothing. // get current position. gbVec2 current_position; controller_current_position(control, ¤t_position); // print_point(¤t_position); // compare current position with setpoint. // while(1){ gbVec2 position_error; path_node_t *next_point = path_next_point(control->path); //gb_vec2_sub(&position_error, next_point->point, current_position); float error_magnitude = gb_vec2_mag(position_error); gbVec2 scaled_position_error; //printf("Magnitude: %f Error ", error_magnitude); //print_point(&position_error); if (error_magnitude > distance) { gb_vec2_div(&scaled_position_error, position_error, error_magnitude/distance); gb_vec2_add(setpoint, current_position, scaled_position_error); //printf("Next "); //print_point(setpoint); return CONTROLLER_OK; } else if (next_point->list.next == NULL) { scaled_position_error = current_position; gb_vec2_add(setpoint, current_position, scaled_position_error); //printf("No new point\n"); if (error_magnitude < distance/8) { return CONTROLLER_STATISFIED; } return CONTROLLER_NO_PATH; } else { path_increment(control->path); printf("Increment Path\n"); } } gbVec2 position_error; gb_vec2_sub(&position_error, control->setpoint, current_position); // scale the length of the error. // to limit the length. control->error = gb_vec2_mag(position_error); gbVec2 scaled_position_error; if (control->error > distance) { gb_vec2_div(&scaled_position_error, position_error, control->error/distance); } else { scaled_position_error = position_error; } gb_vec2_add(setpoint, current_position, scaled_position_error); return 0; } */ int controller_home(controller_t *control){ stepper_disable(control->stepper_b); stepper_disable(control->stepper_a); while(gpio_read(BTN0_PIN)!=0) { } xtimer_usleep(1000000); stepper_enable(control->stepper_b); stepper_set_direction(control->stepper_b,STEPPER_FORWARD); while(gpio_read(BTN0_PIN)!=0){ stepper_step(control->stepper_b); xtimer_usleep(3000); } stepper_enable(control->stepper_a); stepper_set_direction(control->stepper_a,STEPPER_REVERSE); stepper_set_direction(control->stepper_b,STEPPER_REVERSE); uint32_t homing_b_steps = stepper_get_count(control->stepper_a,1.92); uint32_t homing_a_steps= stepper_get_count(control->stepper_b,0.75); uint32_t homing_combined = homing_b_steps - homing_a_steps; for(uint32_t i = 0; i < homing_combined; i++) { stepper_step(control->stepper_b); xtimer_usleep(1000); } stepper_enable(control->stepper_b); for(uint32_t i = 0; i < homing_a_steps; i++) { stepper_step(control->stepper_b); stepper_step(control->stepper_a); xtimer_usleep(1000); } control->stepper_a->step_count = stepper_get_count(control->stepper_a,GB_MATH_PI/2.0); control->stepper_b->step_count = 0; float angle_a; float angle_b; stepper_get_angle(control->stepper_a, &angle_a); stepper_get_angle(control->stepper_b, &angle_b); //printf("angle1: %f, angle2 %f\n", angle1, angle2); printf("Angle A: %f, B: %f\n", angle_a, angle_b); while(gpio_read(BTN0_PIN)!=0) { } xtimer_usleep(500000); return 0; } int controller_lift_marker(controller_t *control, bool lift){ (void)lift; (void)control; return 0; }