-
Notifications
You must be signed in to change notification settings - Fork 1
/
ProfileGenerator.cpp
145 lines (123 loc) · 4.35 KB
/
ProfileGenerator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include<bits/stdc++.h>
using namespace std;
namespace wpi {
/**
* Implements a table of key-value pairs with linear interpolation between
* values.
*
* If there's no matching key, the value returned will be a linear interpolation
* between the keys before and after the provided one.
*
* @tparam Key The key type.
* @tparam Value The value type.
*/
template <typename Key, typename Value>
class InterpolatingMap {
public:
/**
* Inserts a key-value pair.
*
* @param key The key.
* @param value The value.
*/
void insert(const Key& key, const Value& value) {
m_container.insert(std::make_pair(key, value));
}
/**
* Inserts a key-value pair.
*
* @param key The key.
* @param value The value.
*/
void insert(Key&& key, Value&& value) {
m_container.insert(std::make_pair(key, value));
}
/**
* Returns the value associated with a given key.
*
* If there's no matching key, the value returned will be a linear
* interpolation between the keys before and after the provided one.
*
* @param key The key.
*/
Value operator[](const Key& key) const {
using const_iterator = typename std::map<Key, Value>::const_iterator;
// Get iterator to upper bound key-value pair for the given key
const_iterator upper = m_container.upper_bound(key);
// If key > largest key in table, return value for largest table key
if (upper == m_container.end()) {
return (--upper)->second;
}
// If key <= smallest key in table, return value for smallest table key
if (upper == m_container.begin()) {
return upper->second;
}
// Get iterator to lower bound key-value pair
const_iterator lower = upper;
--lower;
// Perform linear interpolation between lower and upper bound
const double delta = (key - lower->first) / (upper->first - lower->first);
return delta * upper->second + (1.0 - delta) * lower->second;
}
/**
* Clears the contents.
*/
void clear() { m_container.clear(); }
private:
std::map<Key, Value> m_container;
};
} // namespace wpi
wpi::InterpolatingMap<double, double> velMap;
struct TrajectoryPoint{
double position, velocity, acceleration, time;
};
struct VelocityLimit{
double dStart, dEnd, velocity;
};
const double MAX_VELOCITY = 4.5;
const double MAX_ACCELERATION = 9;
const double MAX_DECELERATION = 4.5;
wpi::InterpolatingMap<double, double> generateProfile(double distance, double startVel = 0, double endVel = 0, std::vector<VelocityLimit> limit = {}){
std::vector<TrajectoryPoint> profile;
for(double i = 0; i <= distance; i += 0.01){
profile.push_back(TrajectoryPoint{.position = i, .velocity = MAX_VELOCITY});
}
for(int i = 0; i < limit.size(); i++){
for(double p = limit[i].dStart; p <= limit[i].dEnd; p += 0.01){
profile[p/0.01].velocity = limit[i].velocity;
}
}
profile[0].velocity = startVel;
profile[profile.size()-1].velocity = endVel;
for(int i = 1; i < profile.size(); i++){
profile[i].velocity = min(profile[i].velocity, sqrt(profile[i-1].velocity * profile[i-1].velocity + 2 * MAX_ACCELERATION * 0.01));
}
for(int i = profile.size()-2; i >= 0; i--){
profile[i].velocity = min(profile[i].velocity, sqrt(profile[i+1].velocity * profile[i+1].velocity + 2 * MAX_DECELERATION * 0.01));
}
for(int i = 0; i < profile.size()-1; i++){
profile[i].acceleration = (profile[i+1].velocity * profile[i+1].velocity - profile[i].velocity * profile[i].velocity) / (2 * 0.01);
}
for(int i = 1; i < profile.size(); i++){
if(profile[i-1].acceleration != 0){
profile[i].time = profile[i-1].time + (profile[i].velocity - profile[i-1].velocity) / profile[i-1].acceleration;
}
else{
profile[i].time = profile[i-1].time + 0.01 / profile[i].velocity;
}
}
wpi::InterpolatingMap<double, double> ret;
for(int i = 0; i < profile.size(); i++){
ret.insert(profile[i].time, profile[i].velocity);
}
return ret;
}
int main(){
auto profile = generateProfile(8, 0, 0, {{1, 3, 2}, {6, 7, 1}});
ofstream os;
os.open("Output.txt");
for(double i = 0; i < 4.3; i += 0.01){
os << profile[i] << endl;
}
os.close();
}