Vehicle Control Unit 0.01
This is the c library for controlling the car.
Loading...
Searching...
No Matches
LUT.c
Go to the documentation of this file.
1#include <stdint.h>
2#include <stdlib.h>
3
4#include "../Inc/Utils/LUT.h"
5
6int point_compare(const void *a, const void *b) {
7 const point *pa = a;
8 const point *pb = b;
9 if (pa->input < pb->input)
10 return -1;
11 if (pa->input > pb->input)
12 return 1;
13 return 0;
14}
15
16bool point_is_between(const point *min, const point *max, float in) {
17 return min->input <= in && in <= max->input;
18}
19
20/* Returns true if the input can interpolate between the min and max. */
21bool can_interpolate(const point *min, const point *max, float in) {
22 // Either point is not defined, so can't interpolate
23 if (min == NULL || max == NULL) {
24 return false;
25 }
26
27 // The input can interpolate if it is between the min and max
28 return point_is_between(min, max, in);
29}
30
31bool table_init(table *table, uint16_t count) {
32 if (table == NULL) {
33 return false;
34 }
35
36 // Table must contain at least two reference points
37 if (count < 2 || count > TABLE_CAPACITY) {
38 return false;
39 }
40
41 // Set up table values to expected values
42 table->count_ = count;
43 table->added_ = 0;
44 table->initialized_ = false;
45 for (uint16_t n = 0; n < count; ++n) {
46 table->points_[n].input = 0;
47 table->points_[n].output = 0;
48 }
49
50 return true;
51}
52
54 // Nothing has invalidated the initialized state of the table
55 if (table->initialized_) {
56 return true;
57 }
58
59 bool all_reference_points = table->added_ == table->count_;
60
61 if (!all_reference_points) {
62 table->initialized_ = false;
63 return table->initialized_;
64 }
65
66 bool sorted = true;
67 const point *previous_point = &table->points_[0];
68 for (uint16_t n = 1; n < table->count_; ++n) {
69 const point *point = &table->points_[n];
70 // Found a decrease, which violates table being sorted
71 if (point->input < previous_point->input) {
72 sorted = false;
73 }
74 }
75 table->initialized_ = sorted;
76 return table->initialized_;
77}
78
79bool table_add_reference_point(table *table, float in, float out) {
81 return false;
82 }
83
84 // NOTE This may should not actually be necessary; the only way to get here is
85 // if the table is not initialized already; there may be a lurking logic error
86 table->initialized_ = false;
87
90 table->added_++;
91
92 return true;
93}
94
97 return NULL;
98 return &table->points_[0];
99}
100
103 return NULL;
104 return &table->points_[table->count_ - 1];
105}
106
107bool table_can_sample(table *table, float in) {
108 const point *min = table_min_point(table);
109 const point *max = table_max_point(table);
110 return can_interpolate(min, max, in);
111}
112
114 qsort(table->points_, table->count_, sizeof(point), point_compare);
115}
116
117/* Search for the index of the first reference point in the table that has a
118 * greater input. */
119uint16_t table_search(const table *table, double in) {
120 // TODO Implement a more efficient search algorithm; should not be necessary
121 // for small tables
122
123 uint16_t n;
124 for (n = 0; n < table->count_; n++) {
125 if (table->points_[n].input > in) {
126 break;
127 }
128 }
129
130 // Assert that the value is in range.
131 // assert(n >= 1);
132 // assert(n < table->count);
133
134 return n;
135}
136
137bool table_sample(table *table, float in, float *out) {
138 // This is where the constraint that the table contains at least two elements
139 // is derived from
140 const point *min = table_min_point(table);
141 const point *max = table_max_point(table);
142
143 // If can't interpolate between the endpoints, can't interpolate between
144 // intermediate points
145 if (!can_interpolate(min, max, in)) {
146 return false;
147 }
148
149 if (in == min->input) {
150 *out = min->output;
151 return true;
152 }
153
154 if (in == max->input) {
155 *out = max->output;
156 return true;
157 }
158
159 // Search for the first point in the table that has a greater input
160 uint16_t n = table_search(table, in);
161 point low = table->points_[n - 1];
162 point high = table->points_[n];
163
164 // Map the input value to a t-value [0, 1]
165 float t = (in - low.input) / (high.input - low.input);
166
167 *out = low.output + t * (high.output - low.output);
168 return true;
169}
#define TABLE_CAPACITY
Definition: LUT.h:36
int point_compare(const void *a, const void *b)
Compares two points by input.
Definition: LUT.c:6
uint16_t table_search(const table *table, double in)
Definition: LUT.c:119
bool table_is_initialized(table *table)
Checks if the table has been fully initialized, with all reference points added.
Definition: LUT.c:53
bool table_sample(table *table, float in, float *out)
Samples a output value from the table for an input value.
Definition: LUT.c:137
bool table_init(table *table, uint16_t count)
Initializes the table.
Definition: LUT.c:31
const point * table_min_point(table *table)
Retrieves the point in the table with the least input value.
Definition: LUT.c:95
bool can_interpolate(const point *min, const point *max, float in)
Definition: LUT.c:21
bool table_can_sample(table *table, float in)
Checks if the input input is valid for the table.
Definition: LUT.c:107
bool point_is_between(const point *min, const point *max, float in)
Determines if the input value is between the input of two points.
Definition: LUT.c:16
const point * table_max_point(table *table)
Retrieves the point in the table with the greatest input value.
Definition: LUT.c:101
bool table_add_reference_point(table *table, float in, float out)
Adds a reference point to the table.
Definition: LUT.c:79
void table_sort(table *table)
Definition: LUT.c:113
Definition: LUT.h:7
float input
Definition: LUT.h:9
float output
Definition: LUT.h:11
Definition: LUT.h:40
point points_[TABLE_CAPACITY]
Definition: LUT.h:48
uint16_t count_
Definition: LUT.h:42
bool initialized_
Definition: LUT.h:46
uint16_t added_
Definition: LUT.h:44