Files
2024-01-06 13:43:22 -07:00

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");
}