mirror of
https://github.com/Team4388/auto_planner.git
synced 2026-06-08 16:28:08 -06:00
179 lines
4.0 KiB
C
179 lines
4.0 KiB
C
#include "motion.h"
|
|
#include "math/mathutils.h"
|
|
#include "planner.h"
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static bool add_point(MotionPath *path, double input[4], uint32_t time) {
|
|
if (path->len >= path->cap) {
|
|
path->cap *= 2;
|
|
printf("new cap %d\n", path->cap);
|
|
|
|
MotionPoint *tmp = path->points;
|
|
const size_t psize = sizeof(MotionPoint) * path->cap;
|
|
path->points = malloc(psize);
|
|
memset(path->points, 0, psize);
|
|
|
|
memcpy(path->points, tmp, sizeof(MotionPoint) * (path->len));
|
|
free(tmp);
|
|
|
|
if (path->points == NULL) {
|
|
printf("reallocation failed in add_point\n");
|
|
free(path->points);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
path->points[path->len++] = (MotionPoint) {
|
|
.leftx = input[0],
|
|
.lefty = input[1],
|
|
.rightx = input[2],
|
|
.righty = input[3],
|
|
.time = time,
|
|
};
|
|
|
|
return true;
|
|
}
|
|
|
|
MotionPath load_path(const char *filename, Field *field) {
|
|
FILE *file;
|
|
fopen_s(&file, filename, "r");
|
|
|
|
const int filename_len = strlen(filename) + 1;
|
|
const size_t psize = sizeof(MotionPoint) * PATH_INIT_SIZE;
|
|
|
|
MotionPath path = {
|
|
.name = malloc(sizeof(char) * filename_len),
|
|
.points = malloc(psize),
|
|
.cap = PATH_INIT_SIZE,
|
|
.len = 0,
|
|
.odo_path = NULL,
|
|
.bounding_box = { 0, 0, 0, 0 },
|
|
};
|
|
|
|
strcpy_s(path.name, filename_len, filename);
|
|
memset(path.points, 0, psize);
|
|
|
|
char num_buf[200];
|
|
int num_top = 0;
|
|
|
|
double point_data[4];
|
|
int point_top = 0;
|
|
|
|
char ch;
|
|
while ((ch = fgetc(file)) != EOF) {
|
|
switch (ch) {
|
|
case '-':
|
|
case '.':
|
|
case '0' ... '9':
|
|
num_buf[num_top++] = ch;
|
|
break;
|
|
case ',':
|
|
num_buf[num_top++] = '\0';
|
|
point_data[point_top++] = atof(num_buf);
|
|
num_top = 0;
|
|
break;
|
|
case '\n':
|
|
num_buf[num_top++] = '\0';
|
|
add_point(&path, point_data, atoi(num_buf));
|
|
|
|
num_top = 0;
|
|
point_top = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
fclose(file);
|
|
|
|
build_odo_mpath(&path, field);
|
|
return path;
|
|
}
|
|
|
|
// PERF: you know your data is well structured
|
|
// when serialization is this easy
|
|
void save_path(MotionPath *path) {
|
|
FILE *file;
|
|
fopen_s(&file, path->name, "w+");
|
|
|
|
for (int i = 0; i < path->len; i++) {
|
|
fprintf(file, "%f,%f,%f,%f,%d\n",
|
|
path->points[i].leftx,
|
|
path->points[i].lefty,
|
|
path->points[i].rightx,
|
|
path->points[i].righty,
|
|
path->points[i].time);
|
|
}
|
|
|
|
fclose(file);
|
|
printf("saved motion path %s\n", path->name);
|
|
}
|
|
|
|
bool free_path(MotionPath *path) {
|
|
if (path == NULL) return false;
|
|
free(path->name);
|
|
free(path->points);
|
|
path->name = NULL;
|
|
path->points = NULL;
|
|
return true;
|
|
}
|
|
|
|
static inline double motion_curve(double i) {
|
|
return i;
|
|
}
|
|
|
|
void build_odo_mpath(MotionPath *path, Field *field) {
|
|
if (path->odo_path != NULL) return;
|
|
|
|
const size_t path_size = sizeof(point) * path->len;
|
|
path->odo_path = malloc(path_size);
|
|
memset(path->odo_path, 0, path_size);
|
|
|
|
printf("building odo mpath\n");
|
|
|
|
double x = field->startx;
|
|
double y = field->starty;
|
|
|
|
path->odo_path[0] = (point) {
|
|
.x = field->startx,
|
|
.y = field->starty,
|
|
};
|
|
|
|
for (int i = 1; i < path->len; i++) {
|
|
// get the inputs (should represent the derivative of our auto)
|
|
|
|
double ix = path->points[i].leftx;
|
|
double iy = path->points[i].lefty;
|
|
|
|
// multiply by speed
|
|
|
|
double dx = iy * field->xy_speed;
|
|
double dy = ix * field->xy_speed;
|
|
|
|
// take the time difference (in seconds) and multiply the derivative by it
|
|
|
|
dx *= (path->points[i].time - path->points[i-1].time) / 1000.f;
|
|
dy *= (path->points[i].time - path->points[i-1].time) / 1000.f;
|
|
|
|
/* overall, for the x axis the full equation should look like this:
|
|
* (leftx_input * speed) * ((time_ms1 - time_ms0) / 1000)
|
|
*
|
|
* a few other useful facts:
|
|
* input * speed = distance
|
|
* */
|
|
|
|
path->odo_path[i] = (point) {x, y};
|
|
|
|
// change x & y by the derivative
|
|
|
|
x += dx;
|
|
y += dy;
|
|
}
|
|
|
|
printf("built odo mpath\n");
|
|
}
|