Roomba Controller Dashboard 1
A GUI and TCP client application that is used to control a Roomba for Computer Engineering 2880 @ Iowa State
Loading...
Searching...
No Matches
Field.cpp
Go to the documentation of this file.
1//
2// Created by caleb on 10/25/2024
3//
4
5#include "Field.hpp"
6
7Field::Field(const std::vector<Pillar>& pillars, const Pose2D& desiredDestination, const Pillar& botPose) {
8 this->pillars = std::make_unique<std::vector<Pillar>>(pillars);
9 this->desiredDestination = desiredDestination;
10 this->holeManager = HoleManager();
11 this->botPose = botPose;
12 this->graph = Graph<Pose2D>();
13 graph.addNode(new Node<Pose2D>(Pose2D(0, 0)));
14}
15
16Field::Field(const std::vector<Pillar>& pillars, const Pose2D& desiredDestination) {
17 this->pillars = std::make_unique<std::vector<Pillar>>(pillars);
18 this->holeManager = HoleManager();
19 this->desiredDestination = desiredDestination;
20 this->botPose = Pillar(0, 0, 0, BOT_RADIUS);
21 graph.addNode(new Node<Pose2D>(Pose2D(0, 0)));
22}
23
25 this-> pillars = std::make_unique<std::vector<Pillar>>();
26 this->desiredDestination = Pose2D(0, 0, 0);
27 this->botPose = Pillar(0, 0, 0, BOT_RADIUS);
28 this->holeManager = HoleManager();
29 graph.addNode(new Node<Pose2D>(Pose2D(0, 0)));
30}
31
33 if (graph.getNodes().empty()) {
35 }
36
37 // std::vector<Node<Pillar>*> nodes;
38 for (Pillar & pillar : newPillars) {
39 std::vector<Node<Pose2D>*> nodes = graph.getNodes();
40 for (uint32_t i = 1; i < nodes.size(); i++) {
41 if (i != desiredIndex) {
42 if (nodes[i]->getData().distanceTo(pillar.getPose()) < pillar.getRadius() + BOT_RADIUS) {
43 // remove node
45 // nodes = graph.getNodes();
46 }
47 }
48 }
49
50 double magnitude = pillar.getRadius() + BOT_RADIUS;
51 for (double i = 1.0; i < 5.0; i += 0.75) {
52 for (uint16_t angle = 0; angle < 361; angle += 25) {
53 const double radian = angle * M_PI / 180.0;
54 Pose2D attemptAdd = Pose2D::fromPolar(magnitude * i, radian);
55
56 attemptAdd.plus(pillar.getPose());
57
58 if (validLocationForNode(attemptAdd)) {
59 // add to list
60 Node<Pose2D>* toAdd = new Node<Pose2D>(attemptAdd);
61
62 graph.addNode(toAdd);
63 // nodes = graph.getNodes();
64 }
65 }
66 }
67 this->pillars->push_back(pillar);
68 }
69 this->newPillars.clear();
70
72 desiredIndex = graph.getNodes().size() - 1;
73}
74
76 std::vector<Node<Pose2D>*> nodes = graph.getNodes();
77 // o(n^3) crying
78 for (uint16_t nodeIndex = 0; nodeIndex < nodes.size(); nodeIndex++) {
79 for (uint16_t nodeIndexTwo = 0; nodeIndexTwo < nodes.size(); nodeIndexTwo++) {
80 if (nodeIndex != nodeIndexTwo) {
81 Pose2D positionOne = nodes[nodeIndex]->getData();
82 Pose2D positionTwo = nodes[nodeIndexTwo]->getData();
83 double length = positionOne.distanceTo(positionTwo);
84 double dy = (positionTwo.getY() - positionOne.getY());
85 double dx = (positionTwo.getX() - positionTwo.getY());
86 bool gotThrough = true;
87
88 for (uint8_t pillarIndex = 0; pillarIndex < pillars->size(); pillarIndex++) {
89 if (lineIntersectsCircle(pillars->at(pillarIndex), positionOne, positionTwo)) {
90 // uh oh we hit the circle
91 gotThrough = false;
92 }
93 }
94
95 if (holeManager.lineIntersectsAnyHoleMeasurement(positionOne, positionTwo)) {
96 gotThrough = false;
97 }
98
99 if (gotThrough) {
100 // add a weight between nodes[nodeIndex] and nodes[nodeIndexTwo]
101 graph.addConnection(nodes[nodeIndex], nodes[nodeIndexTwo], length);
102 // print out attempt to add
103 }
104 }
105 }
106 }
107}
108
109std::vector<Pose2D> Field::makePath() {
110 std::vector<Node<Pose2D>*> path = graph.Dijkstra(graph.getNodes()[0], graph.getNodes()[desiredIndex]);
111 std::vector<Pose2D> toReturn;
112 for (uint16_t i = 0; i < path.size(); i++) {
113 toReturn.push_back(path[i]->getData());
114 }
115 return toReturn;
116}
117
118bool Field::validLocationForNode(const Pose2D& location) {
119 if (outOfBounds(location)) {
120 return false;
121 }
122 for (auto & i : *pillars) {
123 if (i.getPose().distanceTo(location) < i.getRadius() + BOT_RADIUS) {
124 return false;
125 }
126 }
127 if (holeManager.nodeCollides(location)) {
128 return false;
129 }
130
131 return true;
132}
133
137
139 this->pillars->clear();
140}
141
142std::unique_ptr<std::vector<Pillar>> Field::getPillars() {
143 return std::move(pillars);
144}
145
146void Field::setDesiredIndex(int32_t index) {
147 this->desiredIndex = index;
148}
149
150
151void Field::setPillars(std::unique_ptr<std::vector<Pillar>> pillars) {
152 this->pillars = std::move(pillars);
153}
154
156 return botPose;
157}
158
159void Field::addPillar(Pillar& newPillar) {
160 newPillar.setRadius(roundRadius(newPillar.getRadius()));
161
162 for (uint32_t i = 0; i < this->pillars->size(); i++) {
163 if (this->pillars->at(i).getPose().distanceTo(newPillar.getPose()) < newPillar.getRadius() + this->pillars->at(i).getRadius()) {
164 // these are the same pillars
165 Pose2D sum = this->pillars->at(i).getPose();
166 sum.plus(newPillar.getPose());
167 sum.multiply(0.5);
168
169 Pose2D error = Pose2D(sum);
170 error.minus(this->pillars->at(i).getPose());
171 return;
172 }
173 }
174
175 this->pillars->push_back(newPillar);
176 this->newPillars.push_back(newPillar);
177}
178
179void Field::updateBotPose(const Pose2D& updatedPosition) {
180 Pose2D position(updatedPosition);
181 position.wrapHeading();
182 this->botPose.setPosition(position);
183 if (!graph.getNodes().empty()) {
184 graph.getNodes()[0]->SetData(position);
185 }
186 else {
187 graph.addNode(new Node<Pose2D>(position));
188 }
189}
190
191std::vector<Pillar> Field::getCopyPillars() {
192 std::vector<Pillar> copy;
193 for (const auto & i : *pillars) {
194 copy.push_back(i);
195 }
196 return copy;
197}
198
199bool Field::outOfBounds(const Pose2D& location) {
200 return (location.getX() < 0 || location.getY() < 0 || location.getX() > MAX_X || location.getY() > MAX_Y);
201}
202
203void Field::addEdgeMeasurement(const double rawPosition, const Cardinality cardinality) {
204 switch (cardinality) {
205 case N:
206 {
207 offset.setY(rawPosition);
208 }
209 break;
210 case S:
211 {
212 offset.setY(-rawPosition);
213 }
214 break;
215 case E:
216 {
217 offset.setX(rawPosition);
218 }
219 break;
220 case W:
221 {
222 offset.setX(-rawPosition);
223 }
224 break;
225 }
226}
227
228void Field::applyOffsetToEdge(double x, double y) {
229 Pose2D offset = Pose2D(x, y);
230 for (uint16_t i = 0; i < this->pillars->size(); i++) {
231 this->pillars->at(i).getPose().plus(offset);
232 this->holeManager.offsetAll(offset);
233 }
234}
235
236bool Field::lineIntersectsCircle(double cx, double cy, double r, double x1, double y1, double x2, double y2) {
237 // Calculate the line direction vector
238 double dx = x2 - x1;
239 double dy = y2 - y1;
240
241 // Calculate the projection of the circle center onto the line
242 double t = ((cx - x1) * dx + (cy - y1) * dy) / (dx * dx + dy * dy);
243
244 // Find the closest point on the line to the circle center
245 double closestX = x1 + t * dx;
246 double closestY = y1 + t * dy;
247
248 // Calculate the distance from the circle center to the closest point
249 double distX = closestX - cx;
250 double distY = closestY - cy;
251 double distanceToLine = std::sqrt(distX * distX + distY * distY);
252
253 // Check if the distance is less than or equal to the radius
254 return distanceToLine <= r;
255}
256
257int32_t Field::getDesiredIndex() const {
258 return desiredIndex;
259}
260
262 return graph;
263}
264
265void Field::updateDesired(const Pose2D& other) {
266 if (desiredIndex != -1) {
268 }
269 graph.addNode(new Node<Pose2D>(other));
270 desiredIndex = graph.getNodes().size() - 1;
271 this->desiredDestination = other;
272}
273
Cardinality
Definition Field.hpp:30
@ N
Definition Field.hpp:31
@ E
Definition Field.hpp:33
@ W
Definition Field.hpp:34
@ S
Definition Field.hpp:32
#define MAX_X
Definition Field.hpp:20
#define MAX_Y
Definition Field.hpp:25
#define BOT_RADIUS
Definition Pose2D.hpp:17
std::unique_ptr< std::vector< Pillar > > pillars
Definition Field.hpp:46
int32_t getDesiredIndex() const
Definition Field.cpp:257
void updateBotPose(const Pose2D &updatedPosition)
Definition Field.cpp:179
int32_t desiredIndex
Definition Field.hpp:87
std::vector< Pillar > getCopyPillars()
Definition Field.cpp:191
std::unique_ptr< std::vector< Pillar > > getPillars()
Definition Field.cpp:142
Field()
Definition Field.cpp:24
void discretizeGraph()
Definition Field.cpp:32
bool validLocationForNode(const Pose2D &location)
Definition Field.cpp:118
std::vector< Pillar > newPillars
Definition Field.hpp:93
Pillar getBotPose()
Definition Field.cpp:155
Pose2D getDesiredDestination()
Definition Field.cpp:274
static bool lineIntersectsCircle(double cx, double cy, double r, double x1, double y1, double x2, double y2)
Definition Field.cpp:236
void clearField()
Definition Field.cpp:138
HoleManager & getManager()
Definition Field.cpp:134
void addPillar(Pillar &newPillar)
Definition Field.cpp:159
void setPillars(std::unique_ptr< std::vector< Pillar > > pillars)
Definition Field.cpp:151
void updateDesired(const Pose2D &other)
Definition Field.cpp:265
Pillar botPose
Definition Field.hpp:67
std::vector< Pose2D > makePath()
Definition Field.cpp:109
void weightGraph()
Definition Field.cpp:75
Graph< Pose2D > graph
Definition Field.hpp:82
void addEdgeMeasurement(double rawPosition, Cardinality cardinality)
Definition Field.cpp:203
HoleManager holeManager
Definition Field.hpp:51
void setDesiredIndex(int32_t index)
Definition Field.cpp:146
static bool outOfBounds(const Pose2D &location)
Definition Field.cpp:199
static double roundRadius(double radius)
Definition Field.hpp:258
Pose2D offset
Definition Field.hpp:57
Graph< Pose2D > & getGraph()
Definition Field.cpp:261
void applyOffsetToEdge(double x, double y)
Definition Field.cpp:228
Pose2D desiredDestination
Definition Field.hpp:62
void removeNode(size_t index)
Definition Graph.cpp:390
void addConnection(Node< V > *one, Node< V > *two, double weight)
Definition Graph.cpp:267
void addNode(Node< V > *newNode)
Definition Graph.cpp:102
std::vector< Node< V > * > Dijkstra(Node< V > *from, Node< V > *find)
Definition Graph.cpp:191
std::vector< Node< V > * > getNodes()
Definition Graph.cpp:97
void offsetAll(const Pose2D &offset) const
bool lineIntersectsAnyHoleMeasurement(const Pose2D &positionOne, const Pose2D &positionTwo)
bool nodeCollides(Pose2D position)
Definition Node.hpp:17
double getRadius() const
Definition Pillar.cpp:41
Pose2D & getPose()
Definition Pillar.cpp:29
void setPosition(const Pose2D &newPosition)
Definition Pillar.cpp:58
void setRadius(double newRadius)
Definition Pillar.cpp:45
void multiply(double d)
Definition Pose2D.cpp:267
void setY(double y)
Definition Pose2D.cpp:167
static Pose2D fromPolar(double magnitude, double angle)
Definition Pose2D.cpp:193
void wrapHeading()
Definition Pose2D.cpp:235
void plus(const Pose2D &other)
Definition Pose2D.cpp:100
double distanceTo(const Pose2D &other) const
Definition Pose2D.cpp:86
double getY() const
Definition Pose2D.cpp:151
double getX() const
Definition Pose2D.cpp:147
void minus(Pose2D other)
Definition Pose2D.cpp:187
void setX(double x)
Definition Pose2D.cpp:163