Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7930e2915 | ||
|
|
f0474027be | ||
|
|
12c338def1 | ||
|
|
e511afb2a5 | ||
|
|
f78804d836 | ||
|
|
682a99ffea | ||
|
|
d7a9e9cfd8 | ||
|
|
fd946f2aa3 | ||
|
|
4e2b5bd347 |
Vendored
+2
@@ -129,6 +129,7 @@
|
|||||||
"carr",
|
"carr",
|
||||||
"CIPO",
|
"CIPO",
|
||||||
"COPI",
|
"COPI",
|
||||||
|
"deadzone",
|
||||||
"Doxygen",
|
"Doxygen",
|
||||||
"Dutycycle",
|
"Dutycycle",
|
||||||
"gast",
|
"gast",
|
||||||
@@ -150,6 +151,7 @@
|
|||||||
"Punica",
|
"Punica",
|
||||||
"RHEDE",
|
"RHEDE",
|
||||||
"Rtcm",
|
"Rtcm",
|
||||||
|
"Sats",
|
||||||
"Schalke",
|
"Schalke",
|
||||||
"Soln",
|
"Soln",
|
||||||
"Systeminformation",
|
"Systeminformation",
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
import paho.mqtt.client as mqtt
|
|
||||||
|
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
|
||||||
print("Connected with result code "+str(rc))
|
|
||||||
|
|
||||||
# Subscribing in on_connect() means that if we lose the connection and
|
|
||||||
# reconnect then subscriptions will be renewed.
|
|
||||||
client.subscribe("Rover/Info")
|
|
||||||
client.subscribe("Rover/Warn")
|
|
||||||
client.subscribe("Rover/Error")
|
|
||||||
|
|
||||||
|
|
||||||
def on_message(client, userdata, msg):
|
|
||||||
print(msg.topic+" -> "+str(msg.payload)[2:-1])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
client = mqtt.Client()
|
|
||||||
client.on_connect = on_connect
|
|
||||||
client.on_message = on_message
|
|
||||||
|
|
||||||
client.connect("172.22.64.216", 1883, 60)
|
|
||||||
|
|
||||||
client.loop_forever()
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import paho.mqtt.client as mqtt
|
|
||||||
|
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
|
||||||
print("Connected with result code "+str(rc))
|
|
||||||
|
|
||||||
# Subscribing in on_connect() means that if we lose the connection and
|
|
||||||
# reconnect then subscriptions will be renewed.
|
|
||||||
client.subscribe("Rover/Debug")
|
|
||||||
|
|
||||||
|
|
||||||
def on_message(client, userdata, msg):
|
|
||||||
print(msg.topic+" -> "+str(msg.payload)[2:-1])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
client = mqtt.Client()
|
|
||||||
client.on_connect = on_connect
|
|
||||||
client.on_message = on_message
|
|
||||||
|
|
||||||
client.connect("172.22.64.216", 1883, 60)
|
|
||||||
|
|
||||||
client.loop_forever()
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import paho.mqtt.client as mqtt
|
|
||||||
|
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
|
||||||
print("Connected with result code "+str(rc))
|
|
||||||
|
|
||||||
# Subscribing in on_connect() means that if we lose the connection and
|
|
||||||
# reconnect then subscriptions will be renewed.
|
|
||||||
client.subscribe("Rover/Info")
|
|
||||||
client.subscribe("Rover/Warn")
|
|
||||||
client.subscribe("Rover/Error")
|
|
||||||
client.subscribe("Rover/Info")
|
|
||||||
|
|
||||||
|
|
||||||
def on_message(client, userdata, msg):
|
|
||||||
print(msg.topic+" -> "+str(msg.payload)[2:-1])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
client = mqtt.Client()
|
|
||||||
client.on_connect = on_connect
|
|
||||||
client.on_message = on_message
|
|
||||||
|
|
||||||
client.username_pw_set("kleiax", password="p?{$_~5%hBM7wrcFkr55KWr#")
|
|
||||||
client.connect("192.168.1.7", 1883, 60)
|
|
||||||
|
|
||||||
client.loop_forever()
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import paho.mqtt.client as mqtt
|
|
||||||
|
|
||||||
|
|
||||||
def on_connect(client, userdata, flags, rc):
|
|
||||||
print("Connected with result code "+str(rc))
|
|
||||||
|
|
||||||
# Subscribing in on_connect() means that if we lose the connection and
|
|
||||||
# reconnect then subscriptions will be renewed.
|
|
||||||
client.subscribe("Rover/Debug")
|
|
||||||
|
|
||||||
|
|
||||||
def on_message(client, userdata, msg):
|
|
||||||
print(msg.topic+" -> "+str(msg.payload)[2:-1])
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
client = mqtt.Client()
|
|
||||||
client.on_connect = on_connect
|
|
||||||
client.on_message = on_message
|
|
||||||
|
|
||||||
client.username_pw_set("kleiax", password="p?{$_~5%hBM7wrcFkr55KWr#")
|
|
||||||
client.connect("192.168.1.7", 1883, 60)
|
|
||||||
|
|
||||||
client.loop_forever()
|
|
||||||
@@ -1,157 +0,0 @@
|
|||||||
<diagram program="umletino" version="14.4.0-SNAPSHOT"><zoom_level>10</zoom_level><element><id>UMLClass</id><coordinates><x>750</x><y>10</y><w>220</w><h>650</h></coordinates><panel_attributes><<hardware>>
|
|
||||||
MotorControl
|
|
||||||
--
|
|
||||||
- target_power: int8_t
|
|
||||||
- power: int8_t
|
|
||||||
- direction: uint8_t
|
|
||||||
|
|
||||||
|
|
||||||
- pwm_pin: uint8_t
|
|
||||||
- pwm_channel: uint8_t
|
|
||||||
- pwm_res: uint8_t
|
|
||||||
- dutycycle_min: uint8_t
|
|
||||||
- dutycycle_max: uint8_t
|
|
||||||
- direction_1: uint8_t
|
|
||||||
- direction_2: uint8_t
|
|
||||||
- delay: uint8_t
|
|
||||||
- powersteps: uint8_t
|
|
||||||
|
|
||||||
- last_millis: uint32_t
|
|
||||||
--
|
|
||||||
+ MotorControl()
|
|
||||||
+ init(pwm_pin: uint8_t,
|
|
||||||
pwm_channel: uint8_t,
|
|
||||||
dir_1: uint8_t, dir_2: uint8_t)
|
|
||||||
+ loop(): uint16_t
|
|
||||||
+ runMotorControl()
|
|
||||||
|
|
||||||
+ setMinPwm(uint8_t)
|
|
||||||
+ setMaxPwm(uint8_t)
|
|
||||||
+ setPowerSteps(uint8_t): uint16_t
|
|
||||||
+ setTargetPower(uint8_t)
|
|
||||||
+ setDelay(uint8_t): uint16_t
|
|
||||||
|
|
||||||
+ stop()
|
|
||||||
+ emergencyStop()
|
|
||||||
+ toString()
|
|
||||||
+ getPower(): int8_t
|
|
||||||
+ getTargetPower(): int8_t
|
|
||||||
+ isTargetPowerReached(): bool
|
|
||||||
+ isAccelerationPositive(): bool
|
|
||||||
+ isAccelerationNegative(): bool
|
|
||||||
|
|
||||||
- setRealPower(power: int8_t)
|
|
||||||
- increasePower(power: int8_t)
|
|
||||||
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>80</x><y>380</y><w>220</w><h>330</h></coordinates><panel_attributes><<hardware>>
|
|
||||||
Speedometer
|
|
||||||
--
|
|
||||||
- encoder: ESP32Encoder
|
|
||||||
- debug: DebugMqtt*
|
|
||||||
- name: String
|
|
||||||
- speed: double = 0
|
|
||||||
- last_millis: uint64_t = 0;
|
|
||||||
- bufPos: uint8_t
|
|
||||||
- buf: int16_t[BUF_SIZE]
|
|
||||||
--
|
|
||||||
+ Speedometer()
|
|
||||||
+ init(pinA: uint8_t,
|
|
||||||
pinB: uint8_t,
|
|
||||||
name: String)
|
|
||||||
+ runSpeedometer()
|
|
||||||
+ setTargetPower(power: int8_t)
|
|
||||||
+ getSpeed(): double
|
|
||||||
+ getDirection(): uint8_t
|
|
||||||
- addValToBuf(val: int16_t)
|
|
||||||
- getAverage(): int16_t</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>70</x><y>0</y><w>270</w><h>370</h></coordinates><panel_attributes>MoveControl
|
|
||||||
--
|
|
||||||
- debug: DebugMqtt*
|
|
||||||
- left_motor: MotorControl*
|
|
||||||
- right_motor: MotorControl*
|
|
||||||
- left_speedometer: Speedometer*
|
|
||||||
- right_speedometer: Speedometer*
|
|
||||||
- driving_status: DrivingStatus = stop
|
|
||||||
- x_speed: double = 0
|
|
||||||
- rotation_speed: double = 0
|
|
||||||
- wheelspeed_left_target: double = 0
|
|
||||||
- wheelspeed_right_target: double = 0
|
|
||||||
--
|
|
||||||
+ MoveControl()
|
|
||||||
+ init(left_motor: MotorControl*,
|
|
||||||
right_motor: MotorControl*,
|
|
||||||
left_speedometer: Speedometer*,
|
|
||||||
right_speedometer: Speedometer*)
|
|
||||||
+ runMoveControl()
|
|
||||||
+ setDrivingStatus(status: DrivingStatus)
|
|
||||||
+ setSpeed(speed: double)
|
|
||||||
+ setRotationspeed(speed: double)
|
|
||||||
- calcWheelSpeed()
|
|
||||||
- regulateMotors()</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>370</x><y>10</y><w>220</w><h>330</h></coordinates><panel_attributes><<driveModi>>
|
|
||||||
ManualControl
|
|
||||||
--
|
|
||||||
- encoder: ESP32Encoder
|
|
||||||
- debug: DebugMqtt*
|
|
||||||
- name: String
|
|
||||||
- speed: double = 0
|
|
||||||
- last_millis: uint64_t = 0;
|
|
||||||
- bufPos: uint8_t
|
|
||||||
- buf: int16_t[BUF_SIZE]
|
|
||||||
--
|
|
||||||
+ Speedometer()
|
|
||||||
+ init(pinA: uint8_t,
|
|
||||||
pinB: uint8_t,
|
|
||||||
name: String)
|
|
||||||
+ runSpeedometer()
|
|
||||||
+ setTargetPower(power: int8_t)
|
|
||||||
+ getSpeed(): double
|
|
||||||
+ getDirection(): uint8_t
|
|
||||||
- addValToBuf(val: int16_t)
|
|
||||||
- getAverage(): int16_t</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1270</x><y>10</y><w>210</w><h>240</h></coordinates><panel_attributes>MenuControl
|
|
||||||
--
|
|
||||||
# parentMenu: MenuControl*
|
|
||||||
# lcd: LiquidCrystal_I2C*
|
|
||||||
--
|
|
||||||
/+down()/
|
|
||||||
/+up()/
|
|
||||||
/+right()/
|
|
||||||
/+left()/
|
|
||||||
/+yes()/
|
|
||||||
/+no()/
|
|
||||||
|
|
||||||
/+update()/
|
|
||||||
/+printMenu()/
|
|
||||||
|
|
||||||
+ setParentMenu(MenuControl*)
|
|
||||||
+ setLcd(LiquidCrystal_I2C*)</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>980</x><y>10</y><w>280</w><h>270</h></coordinates><panel_attributes>MenuAction
|
|
||||||
--
|
|
||||||
- name: char*
|
|
||||||
|
|
||||||
- *function: void
|
|
||||||
- *callback: void
|
|
||||||
|
|
||||||
- isMenu: bool
|
|
||||||
- menu: MenuControl
|
|
||||||
--
|
|
||||||
+ MenuAction(const char*, (*function), (*callback))
|
|
||||||
+ MenuAction(const char*, (*function))
|
|
||||||
+ MenuAction(const char*, MenuControl* menu)
|
|
||||||
|
|
||||||
+ runAction()
|
|
||||||
|
|
||||||
+ getName(): const char*
|
|
||||||
+ getIsMenu(): bool
|
|
||||||
+ getMenu(): MenuControl*
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>UMLClass</id><coordinates><x>1220</x><y>360</y><w>280</w><h>160</h></coordinates><panel_attributes>Menu
|
|
||||||
--
|
|
||||||
- inSubmenu: bool
|
|
||||||
|
|
||||||
- entrys: list<MenuAction*>
|
|
||||||
- selectedEntry: list<MenuAction*>::iterator
|
|
||||||
|
|
||||||
- isMenu: bool
|
|
||||||
- menu: MenuControl
|
|
||||||
--
|
|
||||||
+ addEntry(MenuAction* entry)
|
|
||||||
</panel_attributes><additional_attributes></additional_attributes></element><element><id>Relation</id><coordinates><x>1350</x><y>240</y><w>30</w><h>140</h></coordinates><panel_attributes>lt=<<-</panel_attributes><additional_attributes>10;10;10;120</additional_attributes></element><element><id>Relation</id><coordinates><x>1080</x><y>270</y><w>160</w><h>190</h></coordinates><panel_attributes>lt=-
|
|
||||||
m1=*
|
|
||||||
m2=0..1</panel_attributes><additional_attributes>10;10;10;160;140;160</additional_attributes></element></diagram>
|
|
||||||
@@ -1,390 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<diagram program="umlet" version="14.3.0">
|
|
||||||
<zoom_level>10</zoom_level>
|
|
||||||
<element>
|
|
||||||
<id>UMLSpecialState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>40</x>
|
|
||||||
<y>20</y>
|
|
||||||
<w>20</w>
|
|
||||||
<h>20</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>type=initial</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>40</x>
|
|
||||||
<y>20</y>
|
|
||||||
<w>130</w>
|
|
||||||
<h>30</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>110.0;10.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>150</x>
|
|
||||||
<y>10</y>
|
|
||||||
<w>100</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>search next point
|
|
||||||
bg=green</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLSpecialState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>180</x>
|
|
||||||
<y>90</y>
|
|
||||||
<w>40</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>bg=green
|
|
||||||
type=decision</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>190</x>
|
|
||||||
<y>40</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>70</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;50.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>150</x>
|
|
||||||
<y>180</y>
|
|
||||||
<w>100</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>detect alignment
|
|
||||||
bg=green</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>190</x>
|
|
||||||
<y>120</y>
|
|
||||||
<w>130</w>
|
|
||||||
<h>80</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-
|
|
||||||
[distance <= 5m]</panel_attributes>
|
|
||||||
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLObject</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>20</x>
|
|
||||||
<y>0</y>
|
|
||||||
<w>840</w>
|
|
||||||
<h>590</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>Autopilot
|
|
||||||
|
|
||||||
valign=top</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>210</x>
|
|
||||||
<y>90</y>
|
|
||||||
<w>140</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-
|
|
||||||
[distance > 5m]</panel_attributes>
|
|
||||||
<additional_attributes>120.0;20.0;10.0;20.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>330</x>
|
|
||||||
<y>90</y>
|
|
||||||
<w>100</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>Error
|
|
||||||
bg=red</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>150</x>
|
|
||||||
<y>270</y>
|
|
||||||
<w>100</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>correct alignment
|
|
||||||
bg=green</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>150</x>
|
|
||||||
<y>360</y>
|
|
||||||
<w>100</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>drive to point
|
|
||||||
bg=green</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>190</x>
|
|
||||||
<y>210</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>80</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>190</x>
|
|
||||||
<y>300</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>80</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>90</x>
|
|
||||||
<y>280</y>
|
|
||||||
<w>80</w>
|
|
||||||
<h>120</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>60.0;10.0;10.0;10.0;10.0;100.0;60.0;100.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>440</x>
|
|
||||||
<y>10</y>
|
|
||||||
<w>410</w>
|
|
||||||
<h>300</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>detect alignment
|
|
||||||
valign=top</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLSpecialState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>460</x>
|
|
||||||
<y>60</y>
|
|
||||||
<w>20</w>
|
|
||||||
<h>20</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>type=final</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>470</x>
|
|
||||||
<y>60</y>
|
|
||||||
<w>90</w>
|
|
||||||
<h>30</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=-></panel_attributes>
|
|
||||||
<additional_attributes>10.0;10.0;70.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>540</x>
|
|
||||||
<y>50</y>
|
|
||||||
<w>110</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>drive 1m forward</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>540</x>
|
|
||||||
<y>140</y>
|
|
||||||
<w>110</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>drive 2m backward</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>540</x>
|
|
||||||
<y>230</y>
|
|
||||||
<w>110</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>drive 1m forward</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>700</x>
|
|
||||||
<y>230</y>
|
|
||||||
<w>120</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>calculate straight line</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>580</x>
|
|
||||||
<y>80</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>80</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>580</x>
|
|
||||||
<y>170</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>80</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLSpecialState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>750</x>
|
|
||||||
<y>150</y>
|
|
||||||
<w>20</w>
|
|
||||||
<h>20</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>type=termination</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>750</x>
|
|
||||||
<y>160</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>90</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;10.0;10.0;70.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>440</x>
|
|
||||||
<y>320</y>
|
|
||||||
<w>410</w>
|
|
||||||
<h>260</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>correct alignment
|
|
||||||
valign=top</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>540</x>
|
|
||||||
<y>370</y>
|
|
||||||
<w>190</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>calculate relativ target position</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>470</x>
|
|
||||||
<y>380</y>
|
|
||||||
<w>90</w>
|
|
||||||
<h>30</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=-></panel_attributes>
|
|
||||||
<additional_attributes>10.0;10.0;70.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLSpecialState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>460</x>
|
|
||||||
<y>380</y>
|
|
||||||
<w>20</w>
|
|
||||||
<h>20</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>type=final</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>580</x>
|
|
||||||
<y>460</y>
|
|
||||||
<w>120</w>
|
|
||||||
<h>40</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>rotate x degree</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>630</x>
|
|
||||||
<y>400</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>80</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>Relation</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>630</x>
|
|
||||||
<y>490</y>
|
|
||||||
<w>30</w>
|
|
||||||
<h>80</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>lt=<-</panel_attributes>
|
|
||||||
<additional_attributes>10.0;60.0;10.0;10.0</additional_attributes>
|
|
||||||
</element>
|
|
||||||
<element>
|
|
||||||
<id>UMLSpecialState</id>
|
|
||||||
<coordinates>
|
|
||||||
<x>630</x>
|
|
||||||
<y>550</y>
|
|
||||||
<w>20</w>
|
|
||||||
<h>20</h>
|
|
||||||
</coordinates>
|
|
||||||
<panel_attributes>type=termination</panel_attributes>
|
|
||||||
<additional_attributes/>
|
|
||||||
</element>
|
|
||||||
</diagram>
|
|
||||||
@@ -1,45 +1,6 @@
|
|||||||
Maybe:
|
|
||||||
-> Time Measurement in component interface
|
|
||||||
-> Time warnings
|
|
||||||
|
|
||||||
Do later:
|
|
||||||
-> Program underfloorLighting
|
|
||||||
-> Add an beeper
|
|
||||||
-> Program the beeper
|
|
||||||
-> Engine slow down without curve in motorControl
|
|
||||||
-> Network clean up (Mqtt remove?)
|
|
||||||
-> Extra class for maneuver, autopilot should inherit from int16_t
|
|
||||||
-> Remote Control
|
|
||||||
- Leds for gnss rtk etc
|
|
||||||
- what happens exactly when no data is arriving
|
|
||||||
-> Test Menu for big curve driving
|
|
||||||
-> Api with Names and show on Maps in Browser
|
|
||||||
-> Menu structure mit add functions for each menu mit pointer return to config (additional not replace)
|
|
||||||
-> Menu Display from parent as run() to make Menu as Component
|
|
||||||
-> Racing Mode
|
|
||||||
-> ConsolControl
|
|
||||||
-> Menü für Einstellungen
|
|
||||||
- WiFi (save in Flash)
|
|
||||||
-> Battery
|
|
||||||
- tabelle mit eigenen Werten übergeben und nicht in header (wiederverwendbarkeit)
|
|
||||||
- kalibrierungsmethode mit Menü
|
|
||||||
- Daten in flash speichern können
|
|
||||||
-> Check speration between Ui and Route (RouteMenu)
|
|
||||||
-> update sparkfun gnss auf v3 für SPI korrekturdatenüvbetragung
|
|
||||||
-> Rover Objekt mit Error zustand freeze, damit das wenn möglich auch auf dem Display angezeigt wird.
|
|
||||||
-> ESP und Sensoren in den DeepSleep für Auschalten oder Akkuschutz
|
|
||||||
-> Doxygen comments
|
|
||||||
- navigation
|
|
||||||
- autopilot
|
|
||||||
|
|
||||||
|
|
||||||
Do now:
|
Do now:
|
||||||
Code:
|
Code:
|
||||||
Fernbedienung!
|
|
||||||
|
|
||||||
Latex:
|
Latex:
|
||||||
Anhang: Liste mit allen Komponenten und Kurzbeschreibung
|
|
||||||
Unterschied funktionale und nicht funktionale Anforderungen
|
|
||||||
Overfull H-Boxen
|
Overfull H-Boxen
|
||||||
Test Motor, Zeiten kontrolieren. Wenn einfach so dann bezug auf fehler bei Timing und freeRtos
|
Test Motor, Zeiten kontrolieren. Wenn einfach so dann bezug auf fehler bei Timing und freeRtos
|
||||||
Was mit den nicht erfüllten Anforderungen machen?
|
Was mit den nicht erfüllten Anforderungen machen?
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ public:
|
|||||||
* @param status
|
* @param status
|
||||||
*/
|
*/
|
||||||
void setDrivingStatus(Status status);
|
void setDrivingStatus(Status status);
|
||||||
|
Status getDrivingStatus() const { return this->driving_status; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Stops the engine immediately
|
* @brief Stops the engine immediately
|
||||||
|
|||||||
@@ -14,12 +14,12 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define HW1
|
#define HOTSPOT
|
||||||
|
|
||||||
#ifdef HOTSPOT
|
#ifdef HOTSPOT
|
||||||
namespace NetworkConfig
|
namespace NetworkConfig
|
||||||
{
|
{
|
||||||
const char ssid[] = "Kleiax Handy";
|
const char ssid[] = "KleiaxHandy";
|
||||||
const char password[] = "12345677";
|
const char password[] = "12345677";
|
||||||
const char ip[] = "192.168.43.4";
|
const char ip[] = "192.168.43.4";
|
||||||
const char subnet[] = "255.255.255.0";
|
const char subnet[] = "255.255.255.0";
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file calcAzimuth.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2023-09-03
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "calcAzimuth.h"
|
|
||||||
|
|
||||||
CalcAzimuth::CalcAzimuth(Point point)
|
|
||||||
: lastChangePoint{point}, currentPosition{point}
|
|
||||||
{
|
|
||||||
Component::loopDelay = CalcAzimuth::loopDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CalcAzimuth::drivingDirectionChange(Point point)
|
|
||||||
{
|
|
||||||
if (point.isInit() && point.isValid())
|
|
||||||
{
|
|
||||||
this->directionChangeMode = true;
|
|
||||||
this->lastChangePoint = point;
|
|
||||||
this->state = State::Invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CalcAzimuth::updateCurrentPosition(Point point)
|
|
||||||
{
|
|
||||||
this->currentPosition = point;
|
|
||||||
this->positionChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
String CalcAzimuth::stateToString(State state)
|
|
||||||
{
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case State::Invalid:
|
|
||||||
return "Invalid";
|
|
||||||
|
|
||||||
case State::Bad:
|
|
||||||
return "Bad";
|
|
||||||
|
|
||||||
case State::Ok:
|
|
||||||
return "Ok";
|
|
||||||
|
|
||||||
case State::Good:
|
|
||||||
return "Good";
|
|
||||||
|
|
||||||
case State::Super:
|
|
||||||
return "Super";
|
|
||||||
|
|
||||||
default:
|
|
||||||
return "UNKOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CalcAzimuth::run()
|
|
||||||
{
|
|
||||||
if (!this->positionChanged)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->positionChanged = false;
|
|
||||||
this->updateAzimuth();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CalcAzimuth::updateAzimuth()
|
|
||||||
{
|
|
||||||
if (!this->directionChangeMode || this->lastChangePoint.distanceTo(this->currentPosition) < 1.0)
|
|
||||||
{
|
|
||||||
this->state = State::Invalid;
|
|
||||||
this->calcAzimuth = INT16_MIN;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->calcAzimuth = this->lastChangePoint.courseTo(this->currentPosition);
|
|
||||||
|
|
||||||
// Map point accuracy to State
|
|
||||||
if (this->lastChangePoint.getAccuracy() == Point::Accuracy::oneDigOfCM || this->currentPosition.getAccuracy() == Point::Accuracy::oneDigOfCM)
|
|
||||||
{
|
|
||||||
this->state = State::Good;
|
|
||||||
}
|
|
||||||
else if (this->lastChangePoint.getAccuracy() == Point::Accuracy::twoDigOfCM || this->currentPosition.getAccuracy() == Point::Accuracy::twoDigOfCM)
|
|
||||||
{
|
|
||||||
this->state = State::Ok;
|
|
||||||
}
|
|
||||||
else if (this->lastChangePoint.getAccuracy() == Point::Accuracy::threeDigOfCM || this->currentPosition.getAccuracy() == Point::Accuracy::threeDigOfCM)
|
|
||||||
{
|
|
||||||
this->state = State::Bad;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->state = State::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upgrade quality if the range grows up
|
|
||||||
if (this->lastChangePoint.distanceTo(this->currentPosition) > this->minDistanceForBetterQuality)
|
|
||||||
{
|
|
||||||
switch (this->state)
|
|
||||||
{
|
|
||||||
case State::Bad:
|
|
||||||
this->state = State::Ok;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::Ok:
|
|
||||||
this->state = State::Good;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::Good:
|
|
||||||
this->state = State::Super;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file calcAzimuth.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a class that calculates the azimuth from a last and a current position
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2023-09-03
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CALC_AZIMUTH_H
|
|
||||||
#define CALC_AZIMUTH_H
|
|
||||||
|
|
||||||
#include "component.h"
|
|
||||||
#include "point.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A class to calculate an azimuth
|
|
||||||
*
|
|
||||||
* This class calculates the current Azimuth with the last position
|
|
||||||
* where the rover has been rotated and the current position
|
|
||||||
*/
|
|
||||||
class CalcAzimuth : public Component
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief States which represent the quality of the current calculated azimuth
|
|
||||||
*/
|
|
||||||
enum State
|
|
||||||
{
|
|
||||||
Invalid,
|
|
||||||
Bad,
|
|
||||||
Ok,
|
|
||||||
Good,
|
|
||||||
Super
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Calc Azimuth object
|
|
||||||
*
|
|
||||||
* @param point current position
|
|
||||||
*/
|
|
||||||
CalcAzimuth(Point point);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Have to be called if the rover rotates
|
|
||||||
*
|
|
||||||
* @param point current position
|
|
||||||
*/
|
|
||||||
void drivingDirectionChange(Point point);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief update the current position
|
|
||||||
*
|
|
||||||
* This function should be called if the rover has moved in
|
|
||||||
* a straight direction, to calculated the current Azimuth.
|
|
||||||
* More distance to the point given to drivingDirectionChange()
|
|
||||||
* increase the accuracy of the calculation.
|
|
||||||
*
|
|
||||||
* @param point current position
|
|
||||||
*/
|
|
||||||
void updateCurrentPosition(Point point);
|
|
||||||
void disableCalcAzimuth() { this->directionChangeMode = false; }
|
|
||||||
|
|
||||||
int16_t getAzimuth() const { return this->calcAzimuth; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the State struct
|
|
||||||
*
|
|
||||||
* @return State current quality of the calculation
|
|
||||||
*/
|
|
||||||
State getState() const { return this->state; }
|
|
||||||
|
|
||||||
static String stateToString(State state);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void run() override;
|
|
||||||
void updateAzimuth();
|
|
||||||
|
|
||||||
State state = State::Invalid;
|
|
||||||
Point lastChangePoint;
|
|
||||||
Point currentPosition;
|
|
||||||
|
|
||||||
bool positionChanged = false;
|
|
||||||
bool directionChangeMode = false;
|
|
||||||
int16_t calcAzimuth = INT16_MAX;
|
|
||||||
double minDistanceForBetterQuality = 2;
|
|
||||||
|
|
||||||
static constexpr uint8_t loopDelay = 50;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CALC_AZIMUTH_H
|
|
||||||
@@ -19,7 +19,7 @@ void Component::loop()
|
|||||||
(*it)->loop();
|
(*it)->loop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->runAsChild();F
|
this->runAsChild();
|
||||||
|
|
||||||
if (this->onlyChilds)
|
if (this->onlyChilds)
|
||||||
{
|
{
|
||||||
|
|||||||
Submodule
+1
Submodule lib/Menu added at 35b1478666
@@ -33,6 +33,7 @@ void MotorControl::init(uint8_t pwmPin, uint8_t pwmChannel, uint8_t dir_1, uint8
|
|||||||
ledcSetup(this->pwmChannel, MotorControl::pwmFreq, MotorControl::pwmRes);
|
ledcSetup(this->pwmChannel, MotorControl::pwmFreq, MotorControl::pwmRes);
|
||||||
ledcAttachPin(this->pwmPin, this->pwmChannel);
|
ledcAttachPin(this->pwmPin, this->pwmChannel);
|
||||||
ledcWrite(this->pwmChannel, 0);
|
ledcWrite(this->pwmChannel, 0);
|
||||||
|
std::cout << "Init pwm" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorControl::run()
|
void MotorControl::run()
|
||||||
@@ -56,7 +57,7 @@ void MotorControl::run()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Positive or negative tagret speed
|
// Positive or negative target speed
|
||||||
if (this->targetPower >= 0)
|
if (this->targetPower >= 0)
|
||||||
{
|
{
|
||||||
// Positive or negative speed
|
// Positive or negative speed
|
||||||
@@ -97,28 +98,6 @@ void MotorControl::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorControl::setMinPwm(uint8_t min)
|
|
||||||
{
|
|
||||||
if (min > MotorControl::maxPwmMin)
|
|
||||||
{
|
|
||||||
min = MotorControl::maxPwmMin;
|
|
||||||
}
|
|
||||||
// transform percentage to real pwm value
|
|
||||||
min = static_cast<uint8_t>(((static_cast<uint8_t>(1) << pwmRes) - 1) * (min / 100.0));
|
|
||||||
this->dutycycleMin = min;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MotorControl::setMaxPwm(uint8_t max)
|
|
||||||
{
|
|
||||||
if (max > 100)
|
|
||||||
{
|
|
||||||
max = 100;
|
|
||||||
}
|
|
||||||
// transform percentage to real pwm value
|
|
||||||
max = static_cast<uint8_t>(((static_cast<uint8_t>(1) << pwmRes) - 1) * (max / 100.0));
|
|
||||||
this->dutycycleMax = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MotorControl::setTargetPower(int8_t power)
|
void MotorControl::setTargetPower(int8_t power)
|
||||||
{
|
{
|
||||||
if (power <= 100 && power >= -100)
|
if (power <= 100 && power >= -100)
|
||||||
@@ -158,7 +137,6 @@ bool MotorControl::isAccelerationNegative() const
|
|||||||
|
|
||||||
void MotorControl::setRealPower(int8_t power)
|
void MotorControl::setRealPower(int8_t power)
|
||||||
{
|
{
|
||||||
// TODO: Exceptionhandling
|
|
||||||
if (power <= 100 && power >= -100)
|
if (power <= 100 && power >= -100)
|
||||||
{
|
{
|
||||||
this->power = power;
|
this->power = power;
|
||||||
@@ -175,10 +153,11 @@ void MotorControl::setRealPower(int8_t power)
|
|||||||
digitalWrite(this->dir_2, LOW);
|
digitalWrite(this->dir_2, LOW);
|
||||||
ledcWrite(this->pwmChannel, 0);
|
ledcWrite(this->pwmChannel, 0);
|
||||||
this->dutycycle = 0;
|
this->dutycycle = 0;
|
||||||
|
std::cout << "abort" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t pwm_val = map(abs(power), 0, 100, this->dutycycleMin, this->dutycycleMax);
|
const uint8_t pwm_val = map(abs(power), 0, 100, MotorControl::minPwmVal, MotorControl::maxPwmVal);
|
||||||
|
|
||||||
if ((this->direction == 1 || this->direction == 0) && power < 0)
|
if ((this->direction == 1 || this->direction == 0) && power < 0)
|
||||||
{ // new direction backward
|
{ // new direction backward
|
||||||
@@ -193,14 +172,13 @@ void MotorControl::setRealPower(int8_t power)
|
|||||||
digitalWrite(this->dir_2, LOW);
|
digitalWrite(this->dir_2, LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "MotorControl::setRealPower pwm_val: " << (int) pwm_val << " channel:" << (int) this->pwmChannel << std::endl;
|
||||||
ledcWrite(this->pwmChannel, pwm_val);
|
ledcWrite(this->pwmChannel, pwm_val);
|
||||||
this->dutycycle = pwm_val;
|
this->dutycycle = pwm_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorControl::increasePower(int8_t power)
|
void MotorControl::increasePower(int8_t power)
|
||||||
{
|
{
|
||||||
// TODO: Exceptionhandling
|
|
||||||
// TODO: make a stop befor a direction change
|
|
||||||
if (abs(power) > 2 * MotorControl::powerSteps)
|
if (abs(power) > 2 * MotorControl::powerSteps)
|
||||||
{
|
{
|
||||||
Serial.println("Invalid Argument in MotorControl::increasePower");
|
Serial.println("Invalid Argument in MotorControl::increasePower");
|
||||||
|
|||||||
@@ -38,20 +38,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void init(uint8_t pwmPin, uint8_t pwmChannel, uint8_t dir_1, uint8_t dir_2);
|
void init(uint8_t pwmPin, uint8_t pwmChannel, uint8_t dir_1, uint8_t dir_2);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the minimum duty cycle
|
|
||||||
*
|
|
||||||
* @param min duty cycle in percent
|
|
||||||
*/
|
|
||||||
void setMinPwm(uint8_t min);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set the maximum duty cycle
|
|
||||||
*
|
|
||||||
* @param max duty cycle in percent
|
|
||||||
*/
|
|
||||||
void setMaxPwm(uint8_t max);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the Target Power
|
* @brief Set the Target Power
|
||||||
*
|
*
|
||||||
@@ -103,6 +89,8 @@ private:
|
|||||||
static constexpr uint8_t pwmRes = 8;
|
static constexpr uint8_t pwmRes = 8;
|
||||||
static constexpr uint8_t powerSteps = 2; // A total of 20 levels ( 100 / SPEED_STEPS ) * RUN_MOTOR_CONTROL_DELAY = 500ms
|
static constexpr uint8_t powerSteps = 2; // A total of 20 levels ( 100 / SPEED_STEPS ) * RUN_MOTOR_CONTROL_DELAY = 500ms
|
||||||
static constexpr uint8_t maxPwmMin = 80;
|
static constexpr uint8_t maxPwmMin = 80;
|
||||||
|
static constexpr uint8_t maxPwmVal = 250;
|
||||||
|
static constexpr uint8_t minPwmVal = 55; // Max 98% of 2^PWM_RES
|
||||||
|
|
||||||
int8_t targetPower = 0;
|
int8_t targetPower = 0;
|
||||||
int8_t power = 0;
|
int8_t power = 0;
|
||||||
@@ -111,8 +99,6 @@ private:
|
|||||||
uint8_t pwmPin = 0;
|
uint8_t pwmPin = 0;
|
||||||
uint8_t pwmChannel = 0;
|
uint8_t pwmChannel = 0;
|
||||||
uint16_t dutycycle = 0;
|
uint16_t dutycycle = 0;
|
||||||
uint8_t dutycycleMin = 55;
|
|
||||||
uint8_t dutycycleMax = 98; // Max 98% of 2^PWM_RES
|
|
||||||
uint8_t dir_1 = 0;
|
uint8_t dir_1 = 0;
|
||||||
uint8_t dir_2 = 0;
|
uint8_t dir_2 = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,178 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file navigation.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the implementation of the class Navigation
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-01-31
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "navigation.h"
|
|
||||||
|
|
||||||
Navigation::Navigation(const SensorData *sensorData, Route *route)
|
|
||||||
: sensorData{sensorData}
|
|
||||||
{
|
|
||||||
this->init(route);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Navigation::init(Route *route)
|
|
||||||
{
|
|
||||||
if (static_cast<bool>(route))
|
|
||||||
{
|
|
||||||
this->route = route;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->route = new Route();
|
|
||||||
}
|
|
||||||
|
|
||||||
Component::loopDelay = Navigation::loopDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
Navigation::~Navigation()
|
|
||||||
{
|
|
||||||
delete this->route;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Navigation::run() {}
|
|
||||||
|
|
||||||
void Navigation::newRoute()
|
|
||||||
{
|
|
||||||
delete this->route;
|
|
||||||
this->route = new Route();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Navigation::startNavigation()
|
|
||||||
{
|
|
||||||
const Point newTargetPoint = this->route->startRoute();
|
|
||||||
this->navigationStarted = this->setTargetPoint(newTargetPoint);
|
|
||||||
if (this->navigationStarted)
|
|
||||||
{
|
|
||||||
this->navigationFinished = false;
|
|
||||||
}
|
|
||||||
return this->navigationStarted;
|
|
||||||
}
|
|
||||||
|
|
||||||
Navigation::Status Navigation::getCourseCorrection(CourseCorrection &correction, bool forceUpdate)
|
|
||||||
{
|
|
||||||
if (this->navigationFinished)
|
|
||||||
{
|
|
||||||
return Status::Complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->currentPosition.getAccuracy() <= this->minAccuracy)
|
|
||||||
{
|
|
||||||
return Status::InsufficientAccuracy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the Rover has moved, if the Rover hasnt moved this function will be return.
|
|
||||||
if (this->currentPosition.distanceTo(this->lastPointCalcCorrection) < (this->minDistanceToReachPoint) / 2 && !forceUpdate)
|
|
||||||
{
|
|
||||||
correction.correction = this->calculateCourseCorrection(this->lastPointCalcCorrection);
|
|
||||||
correction.distance = this->lastPointCalcCorrection.distanceTo(this->targetPoint);
|
|
||||||
return Status::Unchanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
double distance = this->currentPosition.distanceTo(this->targetPoint);
|
|
||||||
|
|
||||||
// Check if I need a new Point
|
|
||||||
if (distance < this->minDistanceToReachPoint && this->preventNextPoint == false)
|
|
||||||
{
|
|
||||||
if (!this->nextPoint())
|
|
||||||
{
|
|
||||||
this->navigationFinished = true;
|
|
||||||
this->navigationStarted = false;
|
|
||||||
return Status::Complete; // End of navigation
|
|
||||||
}
|
|
||||||
distance = this->currentPosition.distanceTo(this->targetPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
correction.correction = this->calculateCourseCorrection(this->currentPosition);
|
|
||||||
correction.distance = distance;
|
|
||||||
this->lastPointCalcCorrection = this->currentPosition;
|
|
||||||
return Status::Updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
Navigation::Status Navigation::addCurrentPosToRoute()
|
|
||||||
{
|
|
||||||
if (this->currentPosition.getAccuracy() <= this->minAccuracy)
|
|
||||||
{
|
|
||||||
return Status::InsufficientAccuracy;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First Point
|
|
||||||
if (this->route->getRouteInfo().totalPoints == 0)
|
|
||||||
{
|
|
||||||
this->route->addPointToRoute(this->currentPosition);
|
|
||||||
this->lastPointRouteInsert = this->currentPosition;
|
|
||||||
return Status::Updated;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every Point after the first
|
|
||||||
const double distance = this->currentPosition.distanceTo(this->lastPointRouteInsert);
|
|
||||||
if (Navigation::minDisBetweenPoints <= distance && Navigation::maxDisBetweenPoints >= distance)
|
|
||||||
{
|
|
||||||
this->route->addPointToRoute(this->currentPosition);
|
|
||||||
this->lastPointRouteInsert = this->currentPosition;
|
|
||||||
return Status::Updated;
|
|
||||||
}
|
|
||||||
return Status::Unchanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t Navigation::calculateCourseCorrection(Point &point)
|
|
||||||
{
|
|
||||||
const int16_t targetCourse = point.courseTo(this->targetPoint);
|
|
||||||
int16_t correctionCourse = 0;
|
|
||||||
|
|
||||||
if (this->sensorData->getCalcAzimuthState() == CalcAzimuth::State::Good || this->sensorData->getCalcAzimuthState() == CalcAzimuth::State::Super)
|
|
||||||
{
|
|
||||||
correctionCourse = targetCourse - this->sensorData->getCalcAzimuth();
|
|
||||||
this->lastUsedCalcAzimuth = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
correctionCourse = targetCourse - this->sensorData->getRealAzimuth();
|
|
||||||
this->lastUsedCalcAzimuth = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Navigation::fixDegree(correctionCourse);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Navigation::nextPoint()
|
|
||||||
{
|
|
||||||
if (!this->navigationStarted)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return this->setTargetPoint(this->route->getNextPoint());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Navigation::setTargetPoint(Point target)
|
|
||||||
{
|
|
||||||
if (target.isInit())
|
|
||||||
{
|
|
||||||
this->targetPoint = target;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t Navigation::fixDegree(int16_t degree)
|
|
||||||
{
|
|
||||||
static constexpr uint16_t fullCircle = 360;
|
|
||||||
|
|
||||||
while (degree < -fullCircle / 2 || degree > fullCircle / 2)
|
|
||||||
{
|
|
||||||
if (degree > fullCircle / 2)
|
|
||||||
{
|
|
||||||
degree -= fullCircle;
|
|
||||||
}
|
|
||||||
else if (degree < -fullCircle / 2)
|
|
||||||
{
|
|
||||||
degree += fullCircle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return degree;
|
|
||||||
}
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file navigation.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a class which navigate an object by the given route
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-01-10
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NAVIGATION_H
|
|
||||||
#define NAVIGATION_H
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "route.h"
|
|
||||||
#include "sensorData.h"
|
|
||||||
#include "component.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This struct inherits the result of the navigation
|
|
||||||
*
|
|
||||||
* The drive get objects of this struct and should
|
|
||||||
* correct the direction in dependency on this.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct CourseCorrection
|
|
||||||
{
|
|
||||||
int16_t correction;
|
|
||||||
double distance;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This class navigate an object
|
|
||||||
*
|
|
||||||
* The class use the given Route and the gps device
|
|
||||||
* to tell the driver in which direction he have to
|
|
||||||
* be drive and the distance to the next checkpoint.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Navigation : public Component
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Status
|
|
||||||
{
|
|
||||||
InsufficientAccuracy,
|
|
||||||
Unchanged,
|
|
||||||
Updated,
|
|
||||||
Complete
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Navigation object
|
|
||||||
*
|
|
||||||
* @param sensorData
|
|
||||||
* @param route
|
|
||||||
*/
|
|
||||||
Navigation(const SensorData *sensorData, Route *route = nullptr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroy the Navigation object
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
~Navigation();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief creates a new empty route
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void newRoute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tries to start the route
|
|
||||||
*
|
|
||||||
* For example the route can not be started
|
|
||||||
* if there are no Points or wrong Points.
|
|
||||||
*
|
|
||||||
* @return true route is started
|
|
||||||
* @return false route can not be started
|
|
||||||
*/
|
|
||||||
bool startNavigation();
|
|
||||||
void freezeTargetPoint(bool val = true) { this->preventNextPoint = val; };
|
|
||||||
|
|
||||||
double increaseMinDistanceToReachPoint() { return this->minDistanceToReachPoint += 0.1; }
|
|
||||||
double decreaseMinDistanceToReachPoint() { return this->minDistanceToReachPoint -= 0.1; }
|
|
||||||
|
|
||||||
// TODO: Dokumentation korrigieren.
|
|
||||||
/**
|
|
||||||
* @brief Get the Course Correction object
|
|
||||||
*
|
|
||||||
* @param correction
|
|
||||||
* @param forceUpdate
|
|
||||||
* @return Status
|
|
||||||
*/
|
|
||||||
Status getCourseCorrection(CourseCorrection &correction, bool forceUpdate = false);
|
|
||||||
|
|
||||||
// TODO: Dokumentation korrigieren.
|
|
||||||
/**
|
|
||||||
* @brief Tries to add the current Position to the route
|
|
||||||
*
|
|
||||||
* This can be go wrong if there is no valid GPS signal
|
|
||||||
*
|
|
||||||
* @return true successful added point
|
|
||||||
* @return false no point added to route
|
|
||||||
*/
|
|
||||||
Status addCurrentPosToRoute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Route Info object
|
|
||||||
*
|
|
||||||
* This object contains information about the route.
|
|
||||||
* For example the stored points.
|
|
||||||
*
|
|
||||||
* @return RouteInfo
|
|
||||||
*/
|
|
||||||
RouteInfo getRouteInfo() const { return this->route->getRouteInfo(); }
|
|
||||||
Route *getRoute() const { return this->route; }
|
|
||||||
Point getCurrentPosition() const { return this->currentPosition; }
|
|
||||||
|
|
||||||
Point::Accuracy getMinAccuracy() const { return this->minAccuracy; }
|
|
||||||
void setMinAccuracy(Point::Accuracy accuracy) { this->minAccuracy = accuracy; }
|
|
||||||
|
|
||||||
// map input in range from -180 to 180 degree
|
|
||||||
static int16_t fixDegree(int16_t degree);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void run() override;
|
|
||||||
void init(Route *route);
|
|
||||||
bool nextPoint();
|
|
||||||
bool setTargetPoint(Point target);
|
|
||||||
int16_t calculateCourseCorrection(Point &point);
|
|
||||||
|
|
||||||
static constexpr uint8_t loopDelay = 20;
|
|
||||||
static constexpr uint8_t maxDisBetweenPoints = 10;
|
|
||||||
static constexpr float minDisBetweenPoints = 0.3;
|
|
||||||
|
|
||||||
const SensorData *sensorData;
|
|
||||||
Route *route = nullptr;
|
|
||||||
|
|
||||||
Point lastPointRouteInsert;
|
|
||||||
Point lastPointCalcCorrection;
|
|
||||||
Point lastPointDrivingDirectionChange;
|
|
||||||
Point targetPoint;
|
|
||||||
Point currentPosition;
|
|
||||||
Point::Accuracy minAccuracy = Point::Accuracy::twoDigOfCM;
|
|
||||||
|
|
||||||
bool navigationStarted = false;
|
|
||||||
bool navigationFinished = false;
|
|
||||||
bool isNtripInit = false;
|
|
||||||
bool preventNextPoint = false;
|
|
||||||
bool directionChangeMode = false;
|
|
||||||
bool lastUsedCalcAzimuth = false;
|
|
||||||
|
|
||||||
uint8_t timeToWait = 200;
|
|
||||||
uint32_t lastMillis = 0;
|
|
||||||
uint32_t ubxUpdateTime = 0;
|
|
||||||
|
|
||||||
double minDistanceToReachPoint = 0.5;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // NAVIGATION_H
|
|
||||||
@@ -1,348 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file NTRIPClient.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the implementation of the class NTRIPClient.
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-09-18
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "ntripClient.h"
|
|
||||||
|
|
||||||
NTRIPClient::NTRIPClient(SFE_UBLOX_GNSS *gps, const char *host, uint16_t port, const char *mountPoint, const char *user, const char *password)
|
|
||||||
: gps{gps}, port{port}, host{host}, mountPoint{mountPoint}, user{user}, password{password}, ntripClient{new WiFiClient}, state{NTRIPClientStates::closeConnection}
|
|
||||||
{
|
|
||||||
Component::loopDelay = NTRIPClient::loopDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTRIPClient::~NTRIPClient()
|
|
||||||
{
|
|
||||||
delete this->ntripClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTRIPClient::run()
|
|
||||||
{
|
|
||||||
switch (this->state)
|
|
||||||
{
|
|
||||||
case NTRIPClientStates::openConnection:
|
|
||||||
if (!this->activated)
|
|
||||||
{
|
|
||||||
this->state = NTRIPClientStates::closeConnection;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Connecting to the NTRIP caster..." << std::endl;
|
|
||||||
if (this->beginClient())
|
|
||||||
{
|
|
||||||
std::cout << "Connected to the NTRIP caster!" << std::endl;
|
|
||||||
this->state = NTRIPClientStates::pushData;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Failed!" << std::endl;
|
|
||||||
this->state = NTRIPClientStates::wait;
|
|
||||||
this->activated = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NTRIPClientStates::pushData:
|
|
||||||
if (!processConnection() || !this->activated)
|
|
||||||
{
|
|
||||||
this->state = NTRIPClientStates::closeConnection;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NTRIPClientStates::closeConnection:
|
|
||||||
std::cout << "Closing the connection to the NTRIP caster..." << std::endl;
|
|
||||||
this->closeConnection();
|
|
||||||
state = NTRIPClientStates::wait;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NTRIPClientStates::wait:
|
|
||||||
if (this->activated)
|
|
||||||
{
|
|
||||||
this->state = NTRIPClientStates::openConnection;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->checkAutoReconnect();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NTRIPClientStates::notAvailable:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
std::cout << "Wrong state in NTRIPClient.cpp..." << std::endl;
|
|
||||||
this->state = NTRIPClientStates::closeConnection;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTRIPClient::runAsChild()
|
|
||||||
{
|
|
||||||
this->pushGPGGA();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTRIPClient::gpsConfiguration()
|
|
||||||
{
|
|
||||||
this->gps->setSPIOutput(COM_TYPE_UBX | COM_TYPE_NMEA);
|
|
||||||
this->gps->setPortInput(COM_PORT_SPI, COM_TYPE_UBX | COM_TYPE_NMEA | COM_TYPE_RTCM3);
|
|
||||||
// Set the differential mode - ambiguities are fixed whenever possible
|
|
||||||
this->gps->setDGNSSConfiguration(SFE_UBLOX_DGNSS_MODE_FIXED);
|
|
||||||
this->gps->setMainTalkerID(SFE_UBLOX_MAIN_TALKER_ID_GP);
|
|
||||||
this->gps->enableNMEAMessage(UBX_NMEA_GGA, COM_PORT_SPI, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NTRIPClient::setActivated(bool state)
|
|
||||||
{
|
|
||||||
if (state && this->state != NTRIPClientStates::notAvailable)
|
|
||||||
{
|
|
||||||
this->activated = true;
|
|
||||||
}
|
|
||||||
else if (state)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->activated = false;
|
|
||||||
this->autoReconnect = false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTRIPClient::setAutoReconnect(bool state)
|
|
||||||
{
|
|
||||||
if (state)
|
|
||||||
{
|
|
||||||
this->reconnectAttemps = 0;
|
|
||||||
this->autoReconnect = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->autoReconnect = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NTRIPClient::beginClient()
|
|
||||||
{
|
|
||||||
static constexpr uint16_t httpError = 401;
|
|
||||||
static constexpr uint16_t httpCheck = 200;
|
|
||||||
|
|
||||||
std::cout << "Opening socket to " << this->host << std::endl;
|
|
||||||
|
|
||||||
char serverRequest[this->bufferSize];
|
|
||||||
char credentials[this->bufferSize];
|
|
||||||
|
|
||||||
if (!static_cast<bool>(this->ntripClient->connect(static_cast<const char *>(this->host), this->port)))
|
|
||||||
{
|
|
||||||
std::cout << "Connection to caster failed" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::cout << "Connected to " << this->host << " : " << this->port << std::endl;
|
|
||||||
std::cout << "Requesting NTRIP Data from mount point " << this->mountPoint << std::endl;
|
|
||||||
|
|
||||||
// Generate the server request (GET)
|
|
||||||
snprintf(static_cast<char *>(serverRequest),
|
|
||||||
this->bufferSize,
|
|
||||||
static_cast<const char *>("GET /%s HTTP/1.0\r\nUser-Agent: NTRIP SparkFun u-blox Client v1.0\r\n"),
|
|
||||||
this->mountPoint);
|
|
||||||
|
|
||||||
// Credentials
|
|
||||||
const uint8_t userCredentialsLength = strlen(this->user) + strlen(this->password) + 2;
|
|
||||||
auto *userCredentials = new char[userCredentialsLength];
|
|
||||||
snprintf(static_cast<char *>(userCredentials), userCredentialsLength, static_cast<const char *>("%s:%s"), this->user, this->password);
|
|
||||||
|
|
||||||
std::cout << "Sending credentials: " << userCredentials << std::endl;
|
|
||||||
|
|
||||||
// Encode
|
|
||||||
const base64 base;
|
|
||||||
const String strEncodedCredentials = base64::encode(userCredentials);
|
|
||||||
delete userCredentials;
|
|
||||||
char encodedCredentials[strEncodedCredentials.length() + 1];
|
|
||||||
strEncodedCredentials.toCharArray(static_cast<char *>(encodedCredentials), sizeof(encodedCredentials));
|
|
||||||
|
|
||||||
snprintf(credentials, sizeof(credentials), static_cast<const char *>("Authorization: Basic %s\r\n"), static_cast<const char *>(encodedCredentials));
|
|
||||||
|
|
||||||
// Add the encoded credentials to the server request
|
|
||||||
strncat(static_cast<char *>(serverRequest), static_cast<const char *>(credentials), this->bufferSize);
|
|
||||||
strncat(static_cast<char *>(serverRequest), static_cast<const char *>("\r\n"), this->bufferSize);
|
|
||||||
|
|
||||||
std::cout << static_cast<const char *>("serverRequest size: ")
|
|
||||||
<< strlen(serverRequest)
|
|
||||||
<< static_cast<const char *>(" of ")
|
|
||||||
<< this->bufferSize
|
|
||||||
<< static_cast<const char *>(" bytes available")
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
// Send the server request
|
|
||||||
std::cout << "Sending server request: " << serverRequest << std::endl;
|
|
||||||
this->ntripClient->write(serverRequest, strlen(serverRequest));
|
|
||||||
|
|
||||||
// Wait up to 5 seconds for response
|
|
||||||
const uint32_t lastMillis = millis();
|
|
||||||
while (static_cast<bool>(!ntripClient->available()))
|
|
||||||
{
|
|
||||||
if (millis() - lastMillis > this->timeOut)
|
|
||||||
{
|
|
||||||
std::cout << "Caster timed out!" << std::endl;
|
|
||||||
this->ntripClient->stop();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
delay(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check reply
|
|
||||||
uint16_t httpStatusCode = 0;
|
|
||||||
char response[this->bufferSize];
|
|
||||||
uint16_t responseIndex = 0;
|
|
||||||
while (static_cast<bool>(this->ntripClient->available()))
|
|
||||||
{
|
|
||||||
if (responseIndex == sizeof(response))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
response[responseIndex++] = ntripClient->read();
|
|
||||||
|
|
||||||
if (httpStatusCode == 0)
|
|
||||||
{
|
|
||||||
if (strstr(response, static_cast<const char *>("200")) != nullptr)
|
|
||||||
{
|
|
||||||
httpStatusCode = httpCheck;
|
|
||||||
}
|
|
||||||
if (strstr(response, static_cast<const char *>("401")) != nullptr)
|
|
||||||
{
|
|
||||||
httpStatusCode = httpError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response[responseIndex] = '\0';
|
|
||||||
|
|
||||||
// std::cout << "Caster response: " << response << std::endl;
|
|
||||||
|
|
||||||
if (httpStatusCode != httpCheck)
|
|
||||||
{
|
|
||||||
std::cout << "Failed to connect to " << this->host << " - HTTP Code: " << (int)httpStatusCode
|
|
||||||
<< " Length of Response: " << responseIndex << std::endl;
|
|
||||||
|
|
||||||
if (httpStatusCode == 0)
|
|
||||||
{
|
|
||||||
std::cout << "Response: " << response << std::endl;
|
|
||||||
}
|
|
||||||
else if (httpStatusCode == httpError)
|
|
||||||
{
|
|
||||||
std::cout << "Statuscode 401 - Unauthorized" << std::endl;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Connected to: " << this->host << std::endl;
|
|
||||||
this->lastReceivedRtcmTime = millis();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTRIPClient::closeConnection()
|
|
||||||
{
|
|
||||||
if (static_cast<bool>(this->ntripClient->connected()))
|
|
||||||
{
|
|
||||||
this->ntripClient->stop();
|
|
||||||
}
|
|
||||||
this->activated = false;
|
|
||||||
std::cout << "NtripClient disconnected from: " << this->host << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NTRIPClient::processConnection()
|
|
||||||
{
|
|
||||||
if (static_cast<bool>(this->ntripClient->connected()))
|
|
||||||
{
|
|
||||||
uint8_t rtcmData[this->bufferSize * 8];
|
|
||||||
uint16_t rtcmCount = 0;
|
|
||||||
|
|
||||||
while (static_cast<bool>(this->ntripClient->available()))
|
|
||||||
{
|
|
||||||
rtcmData[rtcmCount++] = ntripClient->read();
|
|
||||||
if (rtcmCount == sizeof(rtcmData))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rtcmCount > 0)
|
|
||||||
{
|
|
||||||
this->lastReceivedRtcmTime = millis();
|
|
||||||
this->gps->pushRawData(static_cast<uint8_t *>(rtcmData), rtcmCount);
|
|
||||||
// std::cout << "Pushed " << rtcmCount << " RTCM bytes to ZED." << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Connection to " << this->host << " dropped!" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (millis() - this->lastReceivedRtcmTime > this->timeOut)
|
|
||||||
{
|
|
||||||
std::cout << "RTCM timeout!" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTRIPClient::checkAutoReconnect()
|
|
||||||
{
|
|
||||||
if (!this->autoReconnect)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (millis() - this->lastReconnectTime < this->reconnectDelayTime)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->lastReconnectTime = millis();
|
|
||||||
|
|
||||||
if (this->reconnectAttemps >= this->maxReconnectAttemps)
|
|
||||||
{
|
|
||||||
this->autoReconnect = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->activated = true;
|
|
||||||
this->reconnectAttemps++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTRIPClient::pushGPGGA()
|
|
||||||
{
|
|
||||||
if (!this->transmitLocation && !this->activated)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (millis() - this->lastGPGGAPushTime < this->pushGPGGATime)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->lastGPGGAPushTime = millis();
|
|
||||||
|
|
||||||
if (!this->ntripClient->connected())
|
|
||||||
{
|
|
||||||
std::cout << "Failed to pushing GGA to server: " << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *data = new NMEA_GGA_data_t;
|
|
||||||
const uint8_t res = this->gps->getLatestNMEAGPGGA(data);
|
|
||||||
if (res == 2)
|
|
||||||
{
|
|
||||||
this->ntripClient->print(reinterpret_cast<const char *>(data));
|
|
||||||
}
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NTRIPClient::isConnected()
|
|
||||||
{
|
|
||||||
return this->state == NTRIPClientStates::pushData;
|
|
||||||
}
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file ntripClient.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the class NTRIPClient
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2023-02-13
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2023
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NTRIP_CLIENT
|
|
||||||
#define NTRIP_CLIENT
|
|
||||||
|
|
||||||
#include <WiFiClient.h>
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <base64.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h>
|
|
||||||
|
|
||||||
#include "debugTimes.h"
|
|
||||||
#include "component.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief States for the state machine.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
enum NTRIPClientStates
|
|
||||||
{
|
|
||||||
openConnection,
|
|
||||||
pushData,
|
|
||||||
closeConnection,
|
|
||||||
wait,
|
|
||||||
notAvailable
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Ntrip Client
|
|
||||||
*
|
|
||||||
* This class can connect to a ntrip server to pull correction
|
|
||||||
* data and push it to a given gnss module. This module have to be compatible
|
|
||||||
* with the SparkFun u-blox GNSS Arduino Library.
|
|
||||||
*/
|
|
||||||
class NTRIPClient : public Component
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new NTRIPClient object
|
|
||||||
*
|
|
||||||
* @param gps The Gnss module
|
|
||||||
* @param host
|
|
||||||
* @param port
|
|
||||||
* @param mountPoint
|
|
||||||
* @param user
|
|
||||||
* @param password
|
|
||||||
*/
|
|
||||||
NTRIPClient(SFE_UBLOX_GNSS *gps, const char *host, uint16_t port, const char *mountPoint, const char *user, const char *password);
|
|
||||||
~NTRIPClient();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configure the Gnss module to accept correction data
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void gpsConfiguration();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Activate or deactivate the location transmission
|
|
||||||
*
|
|
||||||
* Some server need the position of the Gnss module to send the
|
|
||||||
* right correction data.
|
|
||||||
*
|
|
||||||
* @param b
|
|
||||||
*/
|
|
||||||
void setTransmitLocation(bool b) { this->transmitLocation = b; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Activate or deactivate the connection to the server.
|
|
||||||
*
|
|
||||||
* @param state
|
|
||||||
* @return true success
|
|
||||||
* @return false failure
|
|
||||||
*/
|
|
||||||
bool setActivated(bool state);
|
|
||||||
void setAutoReconnect(bool state);
|
|
||||||
|
|
||||||
bool isConnected();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Client State object
|
|
||||||
*
|
|
||||||
* Returns the state of the State machine
|
|
||||||
*
|
|
||||||
* @return NTRIPClientStates
|
|
||||||
*/
|
|
||||||
NTRIPClientStates getClientState() { return this->state; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void run() override;
|
|
||||||
void runAsChild() override;
|
|
||||||
void pushGPGGA();
|
|
||||||
bool beginClient();
|
|
||||||
void closeConnection();
|
|
||||||
bool processConnection();
|
|
||||||
void checkAutoReconnect();
|
|
||||||
|
|
||||||
SFE_UBLOX_GNSS *gps;
|
|
||||||
WiFiClient *ntripClient;
|
|
||||||
NTRIPClientStates state = NTRIPClientStates::notAvailable;
|
|
||||||
|
|
||||||
bool transmitLocation = false;
|
|
||||||
bool activated = true;
|
|
||||||
bool autoReconnect = false;
|
|
||||||
|
|
||||||
uint8_t reconnectAttemps = 0;
|
|
||||||
uint16_t port;
|
|
||||||
uint32_t lastReceivedRtcmTime = 0;
|
|
||||||
// uint32_t lastNtripConnectTime = 0; // can deleted?
|
|
||||||
uint32_t lastGPGGAPushTime = 0;
|
|
||||||
uint32_t lastReconnectTime = 0;
|
|
||||||
|
|
||||||
const char *host;
|
|
||||||
const char *mountPoint;
|
|
||||||
const char *user;
|
|
||||||
const char *password;
|
|
||||||
const uint8_t maxReconnectAttemps = 10;
|
|
||||||
const uint16_t reconnectDelayTime = 1000;
|
|
||||||
const uint16_t timeOut = 10000;
|
|
||||||
const uint16_t bufferSize = 512;
|
|
||||||
const uint16_t pushGPGGATime = 10000;
|
|
||||||
|
|
||||||
static constexpr uint8_t loopDelay = 20;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,100 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file route.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Implements the class Route and Point
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-01-31
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "route.h"
|
|
||||||
|
|
||||||
void Route::addPointToRoute(Point point)
|
|
||||||
{
|
|
||||||
this->points.push_back(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Route::clear()
|
|
||||||
{
|
|
||||||
this->points.clear();
|
|
||||||
this->currentPoint = 0;
|
|
||||||
this->started = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point Route::startRoute()
|
|
||||||
{
|
|
||||||
if (this->points.empty())
|
|
||||||
{
|
|
||||||
this->started = false;
|
|
||||||
return Point();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->it = this->points.begin();
|
|
||||||
this->currentPoint = 1;
|
|
||||||
this->started = true;
|
|
||||||
return *this->it;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point Route::endRoute()
|
|
||||||
{
|
|
||||||
if (this->points.empty())
|
|
||||||
{
|
|
||||||
this->started = false;
|
|
||||||
return Point();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->it = this->points.end();
|
|
||||||
// TODO: Understand why i have to decrement the iterator first to get realy the last element.
|
|
||||||
this->it--;
|
|
||||||
this->currentPoint = this->points.size();
|
|
||||||
this->started = true;
|
|
||||||
return *this->it;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point Route::getNextPoint()
|
|
||||||
{
|
|
||||||
Point point;
|
|
||||||
if (!this->started)
|
|
||||||
{
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->it != --this->points.end())
|
|
||||||
{
|
|
||||||
this->it++;
|
|
||||||
this->currentPoint++;
|
|
||||||
return *this->it;
|
|
||||||
// } else if (this->it == this->points.end() && this->currentPoint != this->points.size()) {
|
|
||||||
// this->currentPoint++;
|
|
||||||
// return *this->it;
|
|
||||||
}
|
|
||||||
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point Route::getPreviousPoint()
|
|
||||||
{
|
|
||||||
Point point;
|
|
||||||
if (!this->started)
|
|
||||||
{
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->it != this->points.begin())
|
|
||||||
{
|
|
||||||
this->it--;
|
|
||||||
this->currentPoint--;
|
|
||||||
return *this->it;
|
|
||||||
}
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
RouteInfo Route::getRouteInfo()
|
|
||||||
{
|
|
||||||
RouteInfo info{0, 0};
|
|
||||||
info.totalPoints = this->points.size();
|
|
||||||
info.currentPoint = this->currentPoint;
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file route.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the class Route
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-01-31
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ROUTE_H
|
|
||||||
#define ROUTE_H
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include "point.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Holds some route information
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
struct RouteInfo
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief Selected number of Points
|
|
||||||
*/
|
|
||||||
uint16_t currentPoint;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Total points stored in route
|
|
||||||
*/
|
|
||||||
uint16_t totalPoints;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A class to manage multiple points
|
|
||||||
*
|
|
||||||
* The list of point presents a route which can be driven
|
|
||||||
*/
|
|
||||||
class Route
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Adds a point to the list.
|
|
||||||
*
|
|
||||||
* @param point
|
|
||||||
*/
|
|
||||||
void addPointToRoute(Point point);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete all points
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Select the first point as target.
|
|
||||||
*
|
|
||||||
* @return Point
|
|
||||||
*/
|
|
||||||
Point startRoute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Select the last point as target.
|
|
||||||
*
|
|
||||||
* @return Point
|
|
||||||
*/
|
|
||||||
Point endRoute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the next point and set it as target.
|
|
||||||
*
|
|
||||||
* @return Point is zero if there are no more Points.
|
|
||||||
*/
|
|
||||||
Point getNextPoint();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the previous point and set it as target.
|
|
||||||
*
|
|
||||||
* @return Point
|
|
||||||
*/
|
|
||||||
Point getPreviousPoint();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Route Info object
|
|
||||||
*
|
|
||||||
* @return RouteInfo
|
|
||||||
*/
|
|
||||||
RouteInfo getRouteInfo();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Started object
|
|
||||||
*
|
|
||||||
* The Route will be marked as started when startRoute or
|
|
||||||
* endRoute has been called.
|
|
||||||
*
|
|
||||||
* @return true
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
bool getStarted() const { return this->started; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint16_t currentPoint = 0;
|
|
||||||
bool started = false;
|
|
||||||
|
|
||||||
std::list<Point> points;
|
|
||||||
std::list<Point>::iterator it;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // ROUTE_H
|
|
||||||
@@ -20,21 +20,6 @@ SensorData::SensorData()
|
|||||||
Component::loopDelay = SensorData::loopDelay;
|
Component::loopDelay = SensorData::loopDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
SensorData::~SensorData()
|
|
||||||
{
|
|
||||||
delete this->ntripClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SensorData::enableNtrip(String host, uint16_t port, String mountPoint, String user, String password)
|
|
||||||
{
|
|
||||||
this->ntripClient = new NTRIPClient(this->gnss, host.c_str(), port, mountPoint.c_str(), user.c_str(), password.c_str());
|
|
||||||
this->ntripClient->gpsConfiguration();
|
|
||||||
this->ntripClient->loop();
|
|
||||||
this->ntripClient->setActivated(false);
|
|
||||||
this->isNtripInit = true;
|
|
||||||
this->addChildComponent(this->ntripClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SensorData::enableGnss(SPIClass *spiPort, uint8_t csPin)
|
void SensorData::enableGnss(SPIClass *spiPort, uint8_t csPin)
|
||||||
{
|
{
|
||||||
this->gnss = new SFE_UBLOX_GNSS();
|
this->gnss = new SFE_UBLOX_GNSS();
|
||||||
@@ -68,7 +53,6 @@ void SensorData::enableRealCompass()
|
|||||||
this->realCompass = new QMC5883LCompass();
|
this->realCompass = new QMC5883LCompass();
|
||||||
// Init Compass
|
// Init Compass
|
||||||
Wire.beginTransmission(address);
|
Wire.beginTransmission(address);
|
||||||
// TODO: describe Bytes !!!
|
|
||||||
Wire.write(0x0b);
|
Wire.write(0x0b);
|
||||||
Wire.write(0x01);
|
Wire.write(0x01);
|
||||||
Wire.endTransmission();
|
Wire.endTransmission();
|
||||||
@@ -78,69 +62,6 @@ void SensorData::enableRealCompass()
|
|||||||
caliCompass.useData();
|
caliCompass.useData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SensorData::enableCalcCompass()
|
|
||||||
{
|
|
||||||
// TODO: !!! implementieren
|
|
||||||
}
|
|
||||||
|
|
||||||
void SensorData::enableGyroscope()
|
|
||||||
{
|
|
||||||
this->gyroscope = new MPU6050();
|
|
||||||
this->gyroscope->initialize();
|
|
||||||
if (!this->gyroscope->testConnection())
|
|
||||||
{
|
|
||||||
std::cout << "SensorData::enableGyroscope: Gyroskop is not conntected. Freeze!" << std::endl;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8_t deviceStatus = this->gyroscope->dmpInitialize();
|
|
||||||
|
|
||||||
// TODO: !!! MagicNumer 6x
|
|
||||||
this->gyroscope->setXGyroOffset(220);
|
|
||||||
this->gyroscope->setYGyroOffset(76);
|
|
||||||
this->gyroscope->setZGyroOffset(-85);
|
|
||||||
this->gyroscope->setZAccelOffset(1788);
|
|
||||||
|
|
||||||
if (deviceStatus == 0)
|
|
||||||
{
|
|
||||||
this->gyroscope->CalibrateAccel(6);
|
|
||||||
this->gyroscope->CalibrateGyro(6);
|
|
||||||
this->gyroscope->PrintActiveOffsets();
|
|
||||||
this->gyroscope->setDMPEnabled(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// ERROR!
|
|
||||||
// 1 = initial memory load failed
|
|
||||||
// 2 = DMP configuration updates failed
|
|
||||||
// (if it's going to break, usually the code will be 1)
|
|
||||||
std::cout << "SensorData::enableGyroscope: DMP Initialization failed (code" << static_cast<int>(deviceStatus) << "). Freeze!" << std::endl;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CalcAzimuth::State SensorData::getCalcAzimuthState() const
|
|
||||||
{
|
|
||||||
if (static_cast<bool>(this->calcCompass))
|
|
||||||
{
|
|
||||||
return this->calcCompass->getState();
|
|
||||||
}
|
|
||||||
return CalcAzimuth::State::Invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
NTRIPClientStates SensorData::getNtripState() const
|
|
||||||
{
|
|
||||||
if (static_cast<bool>(this->ntripClient))
|
|
||||||
{
|
|
||||||
return this->ntripClient->getClientState();
|
|
||||||
}
|
|
||||||
return NTRIPClientStates::notAvailable;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SensorData::printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct)
|
void SensorData::printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct)
|
||||||
{
|
{
|
||||||
static constexpr uint8_t stringSize = 32;
|
static constexpr uint8_t stringSize = 32;
|
||||||
@@ -235,13 +156,6 @@ void SensorData::run()
|
|||||||
this->realCompass->read();
|
this->realCompass->read();
|
||||||
this->realAzimuth = this->realCompass->getAzimuth();
|
this->realAzimuth = this->realCompass->getAzimuth();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (static_cast<bool>(this->gyroscope) && this->gyroscope->dmpGetCurrentFIFOPacket(static_cast<uint8_t *>(this->gyroBuffer)))
|
|
||||||
{
|
|
||||||
this->gyroscope->dmpGetQuaternion(&this->quaternion, static_cast<uint8_t *>(this->gyroBuffer));
|
|
||||||
this->gyroscope->dmpGetGravity(&this->gravity, &this->quaternion);
|
|
||||||
this->gyroscope->dmpGetYawPitchRoll(static_cast<float *>(this->yawPitchRoll), &this->quaternion, &this->gravity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SensorData::runAsChild()
|
void SensorData::runAsChild()
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#define SENSOR_DATA_H
|
#define SENSOR_DATA_H
|
||||||
|
|
||||||
#include <SPI.h>
|
#include <SPI.h>
|
||||||
#include <I2Cdev.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "component.h"
|
#include "component.h"
|
||||||
@@ -21,9 +20,6 @@
|
|||||||
|
|
||||||
#include <SparkFun_u-blox_GNSS_Arduino_Library.h>
|
#include <SparkFun_u-blox_GNSS_Arduino_Library.h>
|
||||||
#include <QMC5883LCompass.h>
|
#include <QMC5883LCompass.h>
|
||||||
#include <MPU6050_6Axis_MotionApps20.h>
|
|
||||||
#include "calcAzimuth.h"
|
|
||||||
#include "ntripClient.h"
|
|
||||||
|
|
||||||
#include "point.h"
|
#include "point.h"
|
||||||
|
|
||||||
@@ -38,8 +34,6 @@ public:
|
|||||||
SensorData();
|
SensorData();
|
||||||
~SensorData();
|
~SensorData();
|
||||||
|
|
||||||
void enableNtrip(String host, uint16_t port, String mountPoint, String user, String password);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable the gnss module over spi
|
* @brief Enable the gnss module over spi
|
||||||
*
|
*
|
||||||
@@ -55,7 +49,6 @@ public:
|
|||||||
|
|
||||||
void enableRealCompass();
|
void enableRealCompass();
|
||||||
void enableCalcCompass();
|
void enableCalcCompass();
|
||||||
void enableGyroscope();
|
|
||||||
|
|
||||||
// Interface Const
|
// Interface Const
|
||||||
/**
|
/**
|
||||||
@@ -65,45 +58,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
int16_t getRealAzimuth() const { return this->realAzimuth; }
|
int16_t getRealAzimuth() const { return this->realAzimuth; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the azimuth calculated by CalcAzimuth
|
|
||||||
*
|
|
||||||
* Consider to call getCalcAzimuthState() to check, if the data is valid.
|
|
||||||
*
|
|
||||||
* @return int16_t
|
|
||||||
*/
|
|
||||||
int16_t getCalcAzimuth() const { return this->calcAzimuth; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the CalcAzimuth::State object
|
|
||||||
*
|
|
||||||
* Needed to check the quality of calculated azimuth
|
|
||||||
*
|
|
||||||
* @return CalcAzimuth::State
|
|
||||||
*/
|
|
||||||
CalcAzimuth::State getCalcAzimuthState() const;
|
|
||||||
|
|
||||||
Point getCurrentPos() const { return this->currentPosition; }
|
Point getCurrentPos() const { return this->currentPosition; }
|
||||||
const UBX_NAV_PVT_data_t *getGnssData() const { return this->gnssData; };
|
const UBX_NAV_PVT_data_t *getGnssData() const { return this->gnssData; };
|
||||||
NTRIPClientStates getNtripState() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the data from the gyroscope
|
|
||||||
*
|
|
||||||
* The returned float pointer is an array of 3 floats
|
|
||||||
* - Yaw
|
|
||||||
* - Pitch
|
|
||||||
* - Roll
|
|
||||||
*
|
|
||||||
* @return const float*
|
|
||||||
*/
|
|
||||||
const float *getGyroData() const { return this->yawPitchRoll; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the CalcCompass object
|
|
||||||
* @return CalcAzimuth*
|
|
||||||
*/
|
|
||||||
CalcAzimuth *getCalcCompass() const { return this->calcCompass; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the RealCompass object
|
* @brief Get the RealCompass object
|
||||||
@@ -111,18 +67,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
QMC5883LCompass *getRealCompass() const { return this->realCompass; }
|
QMC5883LCompass *getRealCompass() const { return this->realCompass; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the NTRIPClient object
|
|
||||||
* @return NTRIPClient*
|
|
||||||
*/
|
|
||||||
NTRIPClient *getNtripClient() const { return this->ntripClient; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Gyroscope object
|
|
||||||
* @return MPU6050*
|
|
||||||
*/
|
|
||||||
MPU6050 *getGyroscope() const { return this->gyroscope; }
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
/**
|
/**
|
||||||
* @brief Set the output status for PVTdata.
|
* @brief Set the output status for PVTdata.
|
||||||
@@ -141,31 +85,14 @@ private:
|
|||||||
void updateUbxData();
|
void updateUbxData();
|
||||||
|
|
||||||
QMC5883LCompass *realCompass = nullptr;
|
QMC5883LCompass *realCompass = nullptr;
|
||||||
CalcAzimuth *calcCompass = nullptr;
|
|
||||||
SFE_UBLOX_GNSS *gnss = nullptr;
|
SFE_UBLOX_GNSS *gnss = nullptr;
|
||||||
NTRIPClient *ntripClient = nullptr;
|
|
||||||
MPU6050 *gyroscope = nullptr;
|
|
||||||
|
|
||||||
UBX_NAV_PVT_data_t *gnssData = nullptr;
|
UBX_NAV_PVT_data_t *gnssData = nullptr;
|
||||||
Point currentPosition;
|
Point currentPosition;
|
||||||
Quaternion quaternion;
|
|
||||||
VectorFloat gravity;
|
|
||||||
|
|
||||||
char *host = nullptr;
|
|
||||||
char *mountPoint = nullptr;
|
|
||||||
char *user = nullptr;
|
|
||||||
char *password = nullptr;
|
|
||||||
|
|
||||||
bool isNtripInit = false;
|
|
||||||
|
|
||||||
uint8_t gyroBuffer[64];
|
|
||||||
uint16_t port = 0;
|
|
||||||
int16_t realAzimuth = INT16_MAX;
|
int16_t realAzimuth = INT16_MAX;
|
||||||
int16_t calcAzimuth = INT16_MAX;
|
|
||||||
uint32_t lastUbxUpdate = 0;
|
uint32_t lastUbxUpdate = 0;
|
||||||
|
|
||||||
float yawPitchRoll[3]{0, 0, 0};
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
static void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct);
|
static void printPVTdata(UBX_NAV_PVT_data_t *ubxDataStruct);
|
||||||
static void savePVTdata(UBX_NAV_PVT_data_t *ubxDataStruct);
|
static void savePVTdata(UBX_NAV_PVT_data_t *ubxDataStruct);
|
||||||
|
|||||||
+2
-22
@@ -15,16 +15,14 @@ board_build.partitions = no_ota.csv
|
|||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
; monitor_port = COM6
|
monitor_port = COM6
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://git.kleiax.de/PlatformIO-Libs/SparkFunGNSS.git
|
https://git.kleiax.de/PlatformIO-Libs/SparkFunGNSS.git
|
||||||
knolleary/PubSubClient@^2.8
|
knolleary/PubSubClient@^2.8
|
||||||
br3ttb/PID@^1.2.1
|
br3ttb/PID@^1.2.1
|
||||||
marcoschwartz/LiquidCrystal_I2C@^1.1.4
|
marcoschwartz/LiquidCrystal_I2C@^1.1.4
|
||||||
bblanchon/ArduinoJson@^6.20.0
|
|
||||||
mprograms/QMC5883LCompass@^1.2.0
|
mprograms/QMC5883LCompass@^1.2.0
|
||||||
jrowberg/I2Cdevlib-MPU6050@^1.0.0
|
upload_port = COM6
|
||||||
; upload_port = COM6
|
|
||||||
test_ignore = test_desktop
|
test_ignore = test_desktop
|
||||||
build_type = debug
|
build_type = debug
|
||||||
monitor_filters = esp32_exception_decoder
|
monitor_filters = esp32_exception_decoder
|
||||||
@@ -42,21 +40,3 @@ test_ignore = test_embedded
|
|||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
description = A Rover who should be drive a route by gps.
|
description = A Rover who should be drive a route by gps.
|
||||||
|
|
||||||
|
|
||||||
; Bei Möglichkeit folgendes aus clang tidy entfernen
|
|
||||||
; cppcoreguidelines-owning-memory
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
;
|
|
||||||
#
|
|
||||||
|
|||||||
@@ -1,375 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuRoute.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the implementation of the classes MenuActionRoute, MenuRoute and MenuRouteWrapper.
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-12-28
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "menuRoute.h"
|
|
||||||
|
|
||||||
MenuActionRoute::MenuActionRoute(MenuRoute *menuRoute, DataFunction dataFunction)
|
|
||||||
: menuRoute{menuRoute}, dataFunction{dataFunction}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuActionRoute::action()
|
|
||||||
{
|
|
||||||
(this->menuRoute->*this->dataFunction)(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuRoute::MenuRoute(Route *route)
|
|
||||||
: route{route}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuRoute::~MenuRoute()
|
|
||||||
{
|
|
||||||
if (isInit)
|
|
||||||
{
|
|
||||||
delete this->mainMenu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::printMenu()
|
|
||||||
{
|
|
||||||
if (!this->isInit)
|
|
||||||
{
|
|
||||||
this->isInit = true;
|
|
||||||
this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
this->mainMenu->printMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::down()
|
|
||||||
{
|
|
||||||
if (blockInput)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->mainMenu->down();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::up()
|
|
||||||
{
|
|
||||||
if (blockInput)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->mainMenu->up();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::right()
|
|
||||||
{
|
|
||||||
if (blockInput)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->mainMenu->right();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::left()
|
|
||||||
{
|
|
||||||
if (blockInput)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this->mainMenu->isInSubmenu())
|
|
||||||
{
|
|
||||||
this->mainMenu->left();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->parentMenu->printMenu();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::yes()
|
|
||||||
{
|
|
||||||
if (blockInput)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->mainMenu->yes();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::no()
|
|
||||||
{
|
|
||||||
if (blockInput)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this->mainMenu->isInSubmenu())
|
|
||||||
{
|
|
||||||
this->mainMenu->no();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->left();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::init()
|
|
||||||
{
|
|
||||||
// auto dummy = []() {
|
|
||||||
// std::cout << "Dummy in Action" <<std::endl;
|
|
||||||
// };
|
|
||||||
|
|
||||||
this->mainMenu = new Menu;
|
|
||||||
auto *pointsMenu = new MenuRoutePoints(this->route);
|
|
||||||
|
|
||||||
this->mainMenu->setLcd(this->lcd);
|
|
||||||
pointsMenu->setLcd(this->lcd);
|
|
||||||
|
|
||||||
auto *importWrapper = new MenuIntInput(1, new MenuRouteWrapper(this, &MenuRoute::importRoute));
|
|
||||||
auto *exportWrapper = new MenuIntInput(1, new MenuRouteWrapper(this, &MenuRoute::exportRoute));
|
|
||||||
auto *deleteWrapper = new MenuIntInput(1, new MenuRouteWrapper(this, &MenuRoute::deleteRoute));
|
|
||||||
auto *clearWrapper = new MenuActionRoute(this, &MenuRoute::clearRoute);
|
|
||||||
|
|
||||||
importWrapper->setLcd(this->lcd);
|
|
||||||
importWrapper->setMinMax(0, MenuRoute::maxRouteNumber);
|
|
||||||
importWrapper->setPrintParentMenu(false);
|
|
||||||
importWrapper->setEntry(0, "Import Route");
|
|
||||||
|
|
||||||
exportWrapper->setLcd(this->lcd);
|
|
||||||
exportWrapper->setMinMax(0, MenuRoute::maxRouteNumber);
|
|
||||||
exportWrapper->setPrintParentMenu(false);
|
|
||||||
exportWrapper->setEntry(0, "Export Route");
|
|
||||||
|
|
||||||
deleteWrapper->setLcd(this->lcd);
|
|
||||||
deleteWrapper->setMinMax(0, MenuRoute::maxRouteNumber);
|
|
||||||
deleteWrapper->setPrintParentMenu(false);
|
|
||||||
deleteWrapper->setEntry(0, "Delete Route");
|
|
||||||
|
|
||||||
this->mainMenu->addEntry(new MenuAction("Points", pointsMenu));
|
|
||||||
this->mainMenu->addEntry(new MenuAction("Clear", clearWrapper));
|
|
||||||
this->mainMenu->addEntry(new MenuAction("Import", importWrapper));
|
|
||||||
this->mainMenu->addEntry(new MenuAction("Export", exportWrapper));
|
|
||||||
this->mainMenu->addEntry(new MenuAction("Delete", deleteWrapper));
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::importRoute(uint8_t routeNumber)
|
|
||||||
{
|
|
||||||
this->blockInput = true;
|
|
||||||
|
|
||||||
String lineOne = "";
|
|
||||||
String lineTwo = "";
|
|
||||||
|
|
||||||
if (WiFi.status() != WL_CONNECTED)
|
|
||||||
{
|
|
||||||
lineOne = "Not connected to";
|
|
||||||
lineTwo = "the WiFi.";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
this->blockInput = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ESP.getMaxAllocHeap() < JSON_DOCUMENT_SIZE_ROUTE)
|
|
||||||
{
|
|
||||||
lineOne = "Not enough mem";
|
|
||||||
lineTwo = "for Json obj";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
this->blockInput = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiFiClient client;
|
|
||||||
HTTPClient http;
|
|
||||||
DynamicJsonDocument doc(JSON_DOCUMENT_SIZE_ROUTE);
|
|
||||||
|
|
||||||
String host = "http://rover.kleiax.de/api/";
|
|
||||||
host.concat(routeNumber);
|
|
||||||
http.begin(client, host);
|
|
||||||
const int httpResponseCode = http.GET();
|
|
||||||
|
|
||||||
lineOne = "Import complete";
|
|
||||||
lineTwo = "Code: ";
|
|
||||||
|
|
||||||
if (httpResponseCode == MenuRoute::httpValidImport)
|
|
||||||
{
|
|
||||||
deserializeJson(doc, http.getStream());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne = "HTTP Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
lineTwo.concat(httpResponseCode);
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
|
|
||||||
if (httpResponseCode <= 0)
|
|
||||||
{
|
|
||||||
this->blockInput = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t totalPoints = doc["amountPoints"];
|
|
||||||
|
|
||||||
this->route->clear();
|
|
||||||
for (uint16_t i = 0; i < totalPoints; i++)
|
|
||||||
{
|
|
||||||
Point::Coordinates coords;
|
|
||||||
coords.lat = doc["points"][i][0].as<double>();
|
|
||||||
coords.lon = doc["points"][i][1].as<double>();
|
|
||||||
this->route->addPointToRoute(Point(coords, true));
|
|
||||||
}
|
|
||||||
|
|
||||||
this->blockInput = false;
|
|
||||||
http.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::exportRoute(uint8_t routeNumber)
|
|
||||||
{
|
|
||||||
this->blockInput = true;
|
|
||||||
uint16_t totalPoints = this->route->getRouteInfo().totalPoints;
|
|
||||||
|
|
||||||
String lineOne = "";
|
|
||||||
String lineTwo = "";
|
|
||||||
|
|
||||||
if (WiFiSTAClass::status() != WL_CONNECTED)
|
|
||||||
{
|
|
||||||
lineOne = "Not connected to";
|
|
||||||
lineTwo = "the WiFi.";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
this->blockInput = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ESP.getMaxAllocHeap() < JSON_DOCUMENT_SIZE_ROUTE)
|
|
||||||
{
|
|
||||||
lineOne = "Not enough mem";
|
|
||||||
lineTwo = "for Json obj";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
this->blockInput = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_DOCUMENT_SIZE_ROUTE);
|
|
||||||
doc["number"] = routeNumber;
|
|
||||||
doc["amountPoints"] = totalPoints;
|
|
||||||
|
|
||||||
Point::Coordinates coords = this->route->startRoute().getCoordinates();
|
|
||||||
doc["points"][0][0] = coords.lat;
|
|
||||||
doc["points"][0][1] = coords.lon;
|
|
||||||
for (uint16_t i = 1; i < totalPoints; i++)
|
|
||||||
{
|
|
||||||
coords = this->route->getNextPoint().getCoordinates();
|
|
||||||
doc["points"][i][0] = coords.lat;
|
|
||||||
doc["points"][i][1] = coords.lon;
|
|
||||||
}
|
|
||||||
String jsonData;
|
|
||||||
serializeJson(doc, jsonData);
|
|
||||||
|
|
||||||
WiFiClient client;
|
|
||||||
HTTPClient http;
|
|
||||||
|
|
||||||
http.begin(client, "http://rover.kleiax.de/api/");
|
|
||||||
http.addHeader("Content-Type", "application/json");
|
|
||||||
const int httpResponseCode = http.POST(jsonData);
|
|
||||||
|
|
||||||
if (httpResponseCode == MenuRoute::httpValidExport)
|
|
||||||
{
|
|
||||||
lineOne = "Export complete";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne = "HTTP Error";
|
|
||||||
}
|
|
||||||
lineTwo = "Code: ";
|
|
||||||
lineTwo.concat(httpResponseCode);
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
this->blockInput = false;
|
|
||||||
|
|
||||||
http.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::deleteRoute(uint8_t routeNumber)
|
|
||||||
{
|
|
||||||
this->blockInput = true;
|
|
||||||
|
|
||||||
String lineOne = "";
|
|
||||||
String lineTwo = "";
|
|
||||||
|
|
||||||
if (WiFiSTAClass::status() != WL_CONNECTED)
|
|
||||||
{
|
|
||||||
lineOne = "Not connected to";
|
|
||||||
lineTwo = "the WiFi.";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
this->blockInput = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ESP.getMaxAllocHeap() < JSON_DOCUMENT_SIZE_ROUTE)
|
|
||||||
{
|
|
||||||
lineOne = "Not enough mem";
|
|
||||||
lineTwo = "for Json obj";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
this->blockInput = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
WiFiClient client;
|
|
||||||
HTTPClient http;
|
|
||||||
DynamicJsonDocument doc(JSON_DOCUMENT_SIZE_ROUTE);
|
|
||||||
|
|
||||||
String host = "http://rover.kleiax.de/api/";
|
|
||||||
host.concat(routeNumber);
|
|
||||||
http.begin(client, host);
|
|
||||||
const int httpResponseCode = http.sendRequest("DELETE");
|
|
||||||
|
|
||||||
lineOne = "Delete complete";
|
|
||||||
lineTwo = "Code: ";
|
|
||||||
|
|
||||||
if (httpResponseCode == MenuRoute::httpValidDelete)
|
|
||||||
{
|
|
||||||
deserializeJson(doc, http.getStream());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne = "HTTP Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
lineTwo.concat(httpResponseCode);
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
|
|
||||||
this->blockInput = false;
|
|
||||||
http.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoute::clearRoute(uint8_t none)
|
|
||||||
{
|
|
||||||
// The parameter exist only for compability
|
|
||||||
none;
|
|
||||||
this->route->clear();
|
|
||||||
this->print("Currente route", "deleted...");
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuRouteWrapper::MenuRouteWrapper(MenuRoute *menuRoute, DataFunction dataFunction)
|
|
||||||
: menuRoute{menuRoute}, dataFunction{dataFunction}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRouteWrapper::action(int16_t *values, uint8_t length)
|
|
||||||
{
|
|
||||||
if (length < 1)
|
|
||||||
{
|
|
||||||
std::cout << "Error in MenuRouteWrapper::action" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (values[0] < 0)
|
|
||||||
{
|
|
||||||
values[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (values[0] > UINT8_MAX)
|
|
||||||
{
|
|
||||||
values[0] = UINT8_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
(this->menuRoute->*this->dataFunction)(values[0]);
|
|
||||||
}
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuRoute.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a classes to handles routes with the user input.
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-12-28
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MENU_ROUTE_H
|
|
||||||
#define MENU_ROUTE_H
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
#include <ArduinoJson.h>
|
|
||||||
#include <WiFi.h>
|
|
||||||
#include <HTTPClient.h>
|
|
||||||
|
|
||||||
#include "route.h"
|
|
||||||
#include "menu.h"
|
|
||||||
#include "menuControl.h"
|
|
||||||
#include "menuIntInput.h"
|
|
||||||
#include "menuRoutePoints.h"
|
|
||||||
|
|
||||||
#define JSON_DOCUMENT_SIZE_ROUTE 4096
|
|
||||||
|
|
||||||
class MenuRoute;
|
|
||||||
typedef void (MenuRoute::*DataFunction)(uint8_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief MenuActionWrapper to call DataFunctions
|
|
||||||
*
|
|
||||||
* This class should be used to call importRoute,
|
|
||||||
* exportRoute and clearRoute over the Menu.
|
|
||||||
*/
|
|
||||||
class MenuActionRoute : public MenuActionWrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Menu Action Route object
|
|
||||||
*
|
|
||||||
* @param menuRoute
|
|
||||||
* @param dataFunction like exportRoute
|
|
||||||
*/
|
|
||||||
MenuActionRoute(MenuRoute *menuRoute, DataFunction dataFunction);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Runs the given DataFunction
|
|
||||||
*/
|
|
||||||
void action() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MenuRoute *menuRoute;
|
|
||||||
DataFunction dataFunction;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handles routes
|
|
||||||
*
|
|
||||||
* With this menu the user can import, export and delete routes.
|
|
||||||
*/
|
|
||||||
class MenuRoute : public MenuControl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Menu Route object
|
|
||||||
*
|
|
||||||
* @param route
|
|
||||||
*/
|
|
||||||
MenuRoute(Route *route);
|
|
||||||
~MenuRoute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prints the last informations
|
|
||||||
*
|
|
||||||
* On first call this function calls the init function.
|
|
||||||
* On every call this functions call the printMenu function from
|
|
||||||
* the mainMenu of this class.
|
|
||||||
*/
|
|
||||||
void printMenu() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name User Inputs
|
|
||||||
* @brief Inputs given by the parentMenu
|
|
||||||
*/
|
|
||||||
///@{
|
|
||||||
void down() override;
|
|
||||||
void up() override;
|
|
||||||
void right() override;
|
|
||||||
void left() override;
|
|
||||||
void yes() override;
|
|
||||||
void no() override;
|
|
||||||
///@}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Import a Route.
|
|
||||||
*
|
|
||||||
* The functions tries to pull the given route id from the RoverApi.
|
|
||||||
*
|
|
||||||
* @param routeNumber id
|
|
||||||
*/
|
|
||||||
void importRoute(uint8_t routeNumber);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Export a Route.
|
|
||||||
*
|
|
||||||
* The functions tries to push the current route to the RoverApi.
|
|
||||||
*
|
|
||||||
* @param routeNumber id
|
|
||||||
*/
|
|
||||||
void exportRoute(uint8_t routeNumber);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete a Route
|
|
||||||
*
|
|
||||||
* The functions tries to delete the current route from the RoverApi.
|
|
||||||
*
|
|
||||||
* @param routeNumber
|
|
||||||
*/
|
|
||||||
void deleteRoute(uint8_t routeNumber);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete the current Route.
|
|
||||||
*
|
|
||||||
* @param none this param is not be used.
|
|
||||||
*/
|
|
||||||
void clearRoute(uint8_t none);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init();
|
|
||||||
|
|
||||||
Route *route;
|
|
||||||
Menu *mainMenu = nullptr;
|
|
||||||
|
|
||||||
bool isInit = false;
|
|
||||||
bool blockInput = false;
|
|
||||||
|
|
||||||
static constexpr uint8_t maxRouteNumber = 100;
|
|
||||||
static constexpr uint16_t httpValidExport = 201;
|
|
||||||
static constexpr uint16_t httpValidImport = 202;
|
|
||||||
static constexpr uint16_t httpValidDelete = 202;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief MenuRouteWrapper to call DataFunctions with numeric user input
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class MenuRouteWrapper : public MenuIntInputWrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Menu Route Wrapper object.
|
|
||||||
*
|
|
||||||
* @param menuRoute
|
|
||||||
* @param dataFunction
|
|
||||||
*/
|
|
||||||
MenuRouteWrapper(MenuRoute *menuRoute, DataFunction dataFunction);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calls the given DataFunction.
|
|
||||||
*
|
|
||||||
* @param values The value to be given to the DataFunction.
|
|
||||||
* @param length Number of values, should be 1.
|
|
||||||
*/
|
|
||||||
void action(int16_t *values, uint8_t length) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MenuRoute *menuRoute;
|
|
||||||
DataFunction dataFunction = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MENU_ROUTE_H
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuRoutePoints.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the implementation of the class MenuRoutePoints.
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-12-28
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "menuRoutePoints.h"
|
|
||||||
|
|
||||||
MenuRoutePoints::MenuRoutePoints(Route *route)
|
|
||||||
: route{route}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoutePoints::init()
|
|
||||||
{
|
|
||||||
const uint16_t amountPoints = this->route->getRouteInfo().totalPoints;
|
|
||||||
if (amountPoints > UINT8_MAX)
|
|
||||||
{
|
|
||||||
this->error = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->setCountPages(amountPoints);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuRoutePoints::printPage() const
|
|
||||||
{
|
|
||||||
static constexpr int8_t width = 9;
|
|
||||||
static constexpr int8_t prec = 7;
|
|
||||||
static constexpr int8_t bufSize = 20;
|
|
||||||
|
|
||||||
const uint8_t currentPage = this->getCurrentPage();
|
|
||||||
if (this->lastPageNumber == currentPage)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String lineOne = "N ";
|
|
||||||
String lineTwo = "E ";
|
|
||||||
|
|
||||||
if (this->error)
|
|
||||||
{
|
|
||||||
lineOne = "Error: To much";
|
|
||||||
lineTwo = "points are given";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RouteInfo info = this->route->getRouteInfo();
|
|
||||||
if (info.totalPoints == 0)
|
|
||||||
{
|
|
||||||
lineOne = "No Points are";
|
|
||||||
lineTwo = "available";
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point point;
|
|
||||||
if (currentPage == 0)
|
|
||||||
{
|
|
||||||
point = this->route->startRoute();
|
|
||||||
}
|
|
||||||
else if (this->lastPageNumber - 1 == currentPage)
|
|
||||||
{
|
|
||||||
point = this->route->getPreviousPoint();
|
|
||||||
}
|
|
||||||
else if (this->lastPageNumber + 1 == currentPage)
|
|
||||||
{
|
|
||||||
point = this->route->getNextPoint();
|
|
||||||
}
|
|
||||||
else if (currentPage == this->getCountPages() - 1)
|
|
||||||
{
|
|
||||||
point = this->route->endRoute();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "Error in: MenuRoutePoints::printPage()" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
char buf[bufSize];
|
|
||||||
char *string;
|
|
||||||
|
|
||||||
info = this->route->getRouteInfo();
|
|
||||||
string = dtostrf(point.getLatitude(), width, prec, static_cast<char *>(buf));
|
|
||||||
lineOne.concat(string);
|
|
||||||
lineOne.concat(" ");
|
|
||||||
lineOne.concat(info.currentPoint);
|
|
||||||
// lineOne.concat(currentPage);
|
|
||||||
string = dtostrf(point.getLongitude(), width, prec, static_cast<char *>(buf));
|
|
||||||
lineTwo.concat(string);
|
|
||||||
lineTwo.concat(" ");
|
|
||||||
lineTwo.concat(info.totalPoints);
|
|
||||||
// std::cout << "MenuRoutePoints::printPage currentPage: " << (int) currentPage << std::endl;
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuRoutePoints.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a class to print the coordinates of a Route.
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-12-28
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MENU_ROUTE_POINTS_H
|
|
||||||
#define MENU_ROUTE_POINTS_H
|
|
||||||
|
|
||||||
#include "navigation.h"
|
|
||||||
#include "route.h"
|
|
||||||
#include "menuInformationSites.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prints coordinates of Route side by side.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class MenuRoutePoints : public MenuInformationSites
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Menu Route Points object
|
|
||||||
*
|
|
||||||
* @param route
|
|
||||||
*/
|
|
||||||
MenuRoutePoints(Route *route);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configure the base class MenuInformationSites
|
|
||||||
*
|
|
||||||
* Set the amount of pages.
|
|
||||||
*/
|
|
||||||
void init() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prints the the coordinates of the current Point.
|
|
||||||
*/
|
|
||||||
void printPage() const override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Route *route;
|
|
||||||
bool error = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MENU_ROUTE_POINTS_H
|
|
||||||
@@ -31,27 +31,11 @@ void MenuSensorData::printPage() const
|
|||||||
switch (this->getCurrentPage())
|
switch (this->getCurrentPage())
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
lineOne = " Y P R :";
|
|
||||||
lineTwo.concat(this->sensorData->getGyroData()[0]);
|
|
||||||
lineTwo.concat(" ");
|
|
||||||
lineTwo.concat(this->sensorData->getGyroData()[1]);
|
|
||||||
lineTwo.concat(" ");
|
|
||||||
lineTwo.concat(this->sensorData->getGyroData()[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
lineOne = "Real Azimuth:";
|
lineOne = "Real Azimuth:";
|
||||||
lineTwo.concat(this->sensorData->getRealAzimuth());
|
lineTwo.concat(this->sensorData->getRealAzimuth());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 1:
|
||||||
lineOne = "Calc Azimuth:";
|
|
||||||
lineTwo.concat(this->sensorData->getCalcAzimuth());
|
|
||||||
lineTwo.concat(" ");
|
|
||||||
lineTwo.concat(CalcAzimuth::stateToString(this->sensorData->getCalcAzimuthState()));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
{
|
{
|
||||||
lineOne = "Lat:";
|
lineOne = "Lat:";
|
||||||
lineTwo = "Lon:";
|
lineTwo = "Lon:";
|
||||||
@@ -61,7 +45,7 @@ void MenuSensorData::printPage() const
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 2:
|
||||||
lineOne = "Time: ";
|
lineOne = "Time: ";
|
||||||
lineTwo = "";
|
lineTwo = "";
|
||||||
if (static_cast<bool>(fixType))
|
if (static_cast<bool>(fixType))
|
||||||
@@ -91,44 +75,7 @@ void MenuSensorData::printPage() const
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 3:
|
||||||
{
|
|
||||||
lineOne = "CarSol: ";
|
|
||||||
lineTwo = "Ntrip: ";
|
|
||||||
const uint8_t carrSoln = gpsData->flags.bits.carrSoln;
|
|
||||||
if (carrSoln == 0)
|
|
||||||
{
|
|
||||||
lineOne.concat("None");
|
|
||||||
}
|
|
||||||
else if (carrSoln == 1)
|
|
||||||
{
|
|
||||||
lineOne.concat("Floating");
|
|
||||||
}
|
|
||||||
else if (carrSoln == 2)
|
|
||||||
{
|
|
||||||
lineOne.concat("Fixed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne = "UNKNOWN";
|
|
||||||
}
|
|
||||||
const NTRIPClientStates status = this->sensorData->getNtripState();
|
|
||||||
if (status == NTRIPClientStates::pushData)
|
|
||||||
{
|
|
||||||
lineTwo.concat("enabled");
|
|
||||||
}
|
|
||||||
else if (status == NTRIPClientStates::notAvailable)
|
|
||||||
{
|
|
||||||
lineTwo.concat(" N/A");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTwo.concat("disabled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
lineOne = "HAcc: ";
|
lineOne = "HAcc: ";
|
||||||
lineTwo = "Sats: ";
|
lineTwo = "Sats: ";
|
||||||
if (static_cast<bool>(fixType))
|
if (static_cast<bool>(fixType))
|
||||||
|
|||||||
@@ -1,308 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuAutopilot.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains an implementation of the class MenuAutopilot
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-02-03
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "menuAutopilot.h"
|
|
||||||
|
|
||||||
void MenuAutopilot::printPage() const
|
|
||||||
{
|
|
||||||
const CourseCorrection correction = this->autopilot->getCourseCorrection();
|
|
||||||
const UBX_NAV_PVT_data_t *gpsData = this->autopilot->getSensorData()->getGnssData();
|
|
||||||
const bool navigationStarted = this->autopilot->getState() >= Autopilot::State::NavigationStarted;
|
|
||||||
|
|
||||||
String distanceString = "";
|
|
||||||
if (navigationStarted)
|
|
||||||
{
|
|
||||||
uint16_t distance = 0;
|
|
||||||
if (correction.distance < 1)
|
|
||||||
{
|
|
||||||
distance = static_cast<uint16_t>(correction.distance * 100);
|
|
||||||
distanceString.concat(distance);
|
|
||||||
distanceString.concat("cm");
|
|
||||||
}
|
|
||||||
else if (correction.distance < 1000)
|
|
||||||
{
|
|
||||||
distance = static_cast<uint16_t>(correction.distance);
|
|
||||||
distanceString.concat(distance);
|
|
||||||
distanceString.concat("m");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
distance = static_cast<uint16_t>(correction.distance / 1000);
|
|
||||||
distanceString.concat(distance);
|
|
||||||
distanceString.concat("km");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String lineOne = "No information";
|
|
||||||
String lineTwo = "available";
|
|
||||||
|
|
||||||
switch (this->getCurrentPage())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
lineOne = "Status: ";
|
|
||||||
lineTwo = "";
|
|
||||||
switch (this->autopilot->getState())
|
|
||||||
{
|
|
||||||
case Autopilot::State::InsufficientAccuracy:
|
|
||||||
lineTwo = "Err: LowAccuracy";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Autopilot::State::NoRoute:
|
|
||||||
lineTwo = "Err: No route";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Autopilot::State::NavigationStarted:
|
|
||||||
lineTwo = "Nav started";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Autopilot::State::GetToStartPoint:
|
|
||||||
lineTwo = "Drive to start";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Autopilot::State::SelfDrivingAvailable:
|
|
||||||
lineTwo = "Autopilot ready";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Autopilot::State::SelfDriving:
|
|
||||||
lineTwo = "Autopilot active";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Autopilot::State::SelfDrivingRotate:
|
|
||||||
lineTwo = "Rotating";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Autopilot::State::TargetReached:
|
|
||||||
lineTwo = "Target reached";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
lineTwo = "UNKOWN - ";
|
|
||||||
lineTwo.concat(static_cast<int>(this->autopilot->getState()));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
if (!navigationStarted)
|
|
||||||
{
|
|
||||||
lineOne = "Navigation is";
|
|
||||||
lineTwo = "not started";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lineOne = "Distance: ";
|
|
||||||
lineOne.concat(distanceString);
|
|
||||||
lineTwo = "Turn: ";
|
|
||||||
lineTwo.concat(correction.correction);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
lineOne = "Target waypoint";
|
|
||||||
lineTwo = "";
|
|
||||||
lineTwo.concat(this->autopilot->getRouteInfo().currentPoint);
|
|
||||||
lineTwo.concat(" from ");
|
|
||||||
lineTwo.concat(this->autopilot->getRouteInfo().totalPoints);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
NTRIPClientStates status = this->autopilot->getSensorData()->getNtripClient()->getClientState();
|
|
||||||
const uint8_t carrSoln = gpsData->flags.bits.carrSoln;
|
|
||||||
lineOne = "GNSS: ";
|
|
||||||
|
|
||||||
if (status == NTRIPClientStates::pushData)
|
|
||||||
{
|
|
||||||
if (carrSoln == 0)
|
|
||||||
{
|
|
||||||
lineOne.concat("None");
|
|
||||||
}
|
|
||||||
else if (carrSoln == 1)
|
|
||||||
{
|
|
||||||
lineOne.concat("Floating");
|
|
||||||
}
|
|
||||||
else if (carrSoln == 2)
|
|
||||||
{
|
|
||||||
lineOne.concat("Fixed");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne.concat("UNKNOWN");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (status == NTRIPClientStates::notAvailable)
|
|
||||||
lineOne.concat("No WiFi");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne.concat("Offline");
|
|
||||||
}
|
|
||||||
|
|
||||||
lineTwo = "hAcc: ";
|
|
||||||
if (static_cast<bool>(gpsData->fixType))
|
|
||||||
{
|
|
||||||
lineTwo.concat(gpsData->hAcc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTwo.concat("0");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
|
|
||||||
if (this->autopilot->getSensorData()->getCalcAzimuth() == CalcAzimuth::State::Good || this->autopilot->getSensorData()->getCalcAzimuth() == CalcAzimuth::State::Super)
|
|
||||||
{
|
|
||||||
lineOne = "Calc Azi: ";
|
|
||||||
lineTwo = "State: ";
|
|
||||||
lineOne.concat(this->autopilot->getSensorData()->getCalcAzimuth());
|
|
||||||
switch (this->autopilot->getSensorData()->getCalcAzimuthState())
|
|
||||||
{
|
|
||||||
case CalcAzimuth::State::Bad:
|
|
||||||
lineTwo.concat("Bad");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CalcAzimuth::State::Good:
|
|
||||||
lineTwo.concat("Good");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CalcAzimuth::State::Invalid:
|
|
||||||
lineTwo.concat("Invalid");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CalcAzimuth::State::Ok:
|
|
||||||
lineTwo.concat("Ok");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CalcAzimuth::State::Super:
|
|
||||||
lineTwo.concat("Super");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
lineTwo.concat("Unkown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne = "Real Azi: ";
|
|
||||||
lineTwo = "";
|
|
||||||
lineOne.concat(this->autopilot->getSensorData()->getRealAzimuth());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
lineOne = "Loop mode is";
|
|
||||||
if (this->autopilot->getLoopMode())
|
|
||||||
{
|
|
||||||
lineTwo = "enabled";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTwo = "disabled";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
lineOne = "Freeze target is";
|
|
||||||
if (this->targetFreezed)
|
|
||||||
{
|
|
||||||
lineTwo = "activated";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTwo = "deactivated";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
lineOne = "MinDisToPoint:";
|
|
||||||
lineTwo = "<- ";
|
|
||||||
lineTwo.concat(this->minDistance);
|
|
||||||
lineTwo.concat(" ->");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
this->printDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuAutopilot::runCommand()
|
|
||||||
{
|
|
||||||
switch (this->getCurrentPage())
|
|
||||||
{
|
|
||||||
case 5:
|
|
||||||
this->autopilot->switchLoopMode();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
if (this->targetFreezed)
|
|
||||||
{
|
|
||||||
this->targetFreezed = false;
|
|
||||||
this->autopilot->getNavigation()->freezeTargetPoint(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->targetFreezed = true;
|
|
||||||
this->autopilot->getNavigation()->freezeTargetPoint();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
this->minDistance = this->autopilot->getNavigation()->increaseMinDistanceToReachPoint();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuAutopilot::runCommandNo()
|
|
||||||
{
|
|
||||||
switch (this->getCurrentPage())
|
|
||||||
{
|
|
||||||
case 7:
|
|
||||||
this->minDistance = this->autopilot->getNavigation()->decreaseMinDistanceToReachPoint();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuAutopilot::update()
|
|
||||||
{
|
|
||||||
if (!this->autopilot->shouldUpdate())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->routeInfo = this->autopilot->getRouteInfo();
|
|
||||||
this->printMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuAutopilot::init()
|
|
||||||
{
|
|
||||||
this->setCountPages(8);
|
|
||||||
this->autopilot = new Autopilot();
|
|
||||||
this->driveManager->changeModus(this->autopilot);
|
|
||||||
this->routeInfo = this->autopilot->getRouteInfo();
|
|
||||||
|
|
||||||
// dirty hack to get the val, can be better!!! TODO
|
|
||||||
this->autopilot->getNavigation()->increaseMinDistanceToReachPoint();
|
|
||||||
this->minDistance = this->autopilot->getNavigation()->decreaseMinDistanceToReachPoint();
|
|
||||||
|
|
||||||
MenuDriveMode::init();
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuAutopilot.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a class to print informations about the Autopilot
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-02-03
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MENU_AUTOPILOT_DRIVE_H
|
|
||||||
#define MENU_AUTOPILOT_DRIVE_H
|
|
||||||
|
|
||||||
#include "SpecialMenus/driveModi/menuDriveMode.h"
|
|
||||||
#include "driveModi/Modi/Autopilot/autopilot.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A class to print informations about the Autopilot
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class MenuAutopilot : public MenuDriveMode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Menu Autopilot object
|
|
||||||
*
|
|
||||||
* @param driveManager for MenuDriveMode
|
|
||||||
*/
|
|
||||||
MenuAutopilot(DriveManager *driveManager) : MenuDriveMode(driveManager) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prints the Information to display and console
|
|
||||||
*
|
|
||||||
* The informations are only printed to the display if it
|
|
||||||
* set.
|
|
||||||
*
|
|
||||||
* Changes the DriveModi to Autopilot if it is the first time called
|
|
||||||
* and save the Autopilot object.
|
|
||||||
*/
|
|
||||||
void printPage() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief can be called to update shown data
|
|
||||||
*/
|
|
||||||
void update() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init() override;
|
|
||||||
void runCommand() override;
|
|
||||||
void runCommandNo() override;
|
|
||||||
|
|
||||||
bool mutable targetFreezed = false;
|
|
||||||
double mutable minDistance;
|
|
||||||
|
|
||||||
Autopilot *autopilot;
|
|
||||||
RouteInfo routeInfo;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MENU_AUTOPILOT_DRIVE_H
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuCaptureRoute.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains an implementation of the class MenuCaptureRoute
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-01-31
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include "menuCaptureRoute.h"
|
|
||||||
|
|
||||||
void MenuCaptureRoute::printPage() const
|
|
||||||
{
|
|
||||||
const RouteInfo routeInfo = this->captureRoute->getRouteInfo();
|
|
||||||
const UBX_NAV_PVT_data_t *gpsData = this->captureRoute->getSensorData()->getGnssData();
|
|
||||||
|
|
||||||
String lineOne = "";
|
|
||||||
String lineTwo = "";
|
|
||||||
|
|
||||||
switch (this->getCurrentPage())
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
lineOne = "Capture Route";
|
|
||||||
lineTwo = "You can drive";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
lineOne = "Saved waypoints";
|
|
||||||
lineTwo.concat(routeInfo.totalPoints);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
lineOne = "Last status:";
|
|
||||||
switch (this->captureRoute->getLastStatus())
|
|
||||||
{
|
|
||||||
case Navigation::Status::InsufficientAccuracy:
|
|
||||||
lineTwo = "Poor Accuracy";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Navigation::Status::Updated:
|
|
||||||
lineTwo = "Point added";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Navigation::Status::Unchanged:
|
|
||||||
lineTwo = "Point too close";
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
lineTwo = "---";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
lineOne = "Distance to last";
|
|
||||||
lineTwo = "point: ";
|
|
||||||
lineTwo.concat(this->captureRoute->getDistanceToLastPoint());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
{
|
|
||||||
NTRIPClientStates status = this->captureRoute->getSensorData()->getNtripClient()->getClientState();
|
|
||||||
lineOne = "NTRIP Client is";
|
|
||||||
|
|
||||||
if (status == NTRIPClientStates::pushData)
|
|
||||||
{
|
|
||||||
lineTwo = "enabled";
|
|
||||||
}
|
|
||||||
else if (status == NTRIPClientStates::notAvailable)
|
|
||||||
{
|
|
||||||
lineTwo = "not available";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTwo = "disabled";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
{
|
|
||||||
lineOne = "Carrier Solution";
|
|
||||||
uint8_t carrSoln = gpsData->flags.bits.carrSoln;
|
|
||||||
if (carrSoln == 0)
|
|
||||||
{
|
|
||||||
lineTwo = "None";
|
|
||||||
}
|
|
||||||
else if (carrSoln == 1)
|
|
||||||
{
|
|
||||||
lineTwo = "Floating";
|
|
||||||
}
|
|
||||||
else if (carrSoln == 2)
|
|
||||||
{
|
|
||||||
lineTwo = "Fixed";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTwo = "UNKNOWN";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
lineOne = "hAccuracy: ";
|
|
||||||
lineTwo = "Azimuth: ";
|
|
||||||
lineTwo.concat(this->captureRoute->getSensorData()->getRealAzimuth());
|
|
||||||
if (gpsData->fixType)
|
|
||||||
{
|
|
||||||
lineOne.concat(gpsData->hAcc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineOne.concat("0");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
lineOne = "Current minimal";
|
|
||||||
if (this->captureRoute->getNavigation()->getMinAccuracy() >= Point::Accuracy::twoDigOfCM)
|
|
||||||
{
|
|
||||||
lineTwo = "accuracy is high";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lineTwo = "accuracy is low";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
this->printDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->print(lineOne, lineTwo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuCaptureRoute::update()
|
|
||||||
{
|
|
||||||
if (!this->captureRoute->shouldUpdate())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this->printMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuCaptureRoute::runCommand()
|
|
||||||
{
|
|
||||||
switch (this->getCurrentPage())
|
|
||||||
{
|
|
||||||
case 7:
|
|
||||||
if (this->captureRoute->getNavigation()->getMinAccuracy() >= Point::Accuracy::twoDigOfCM)
|
|
||||||
{
|
|
||||||
this->captureRoute->getNavigation()->setMinAccuracy(Point::Accuracy::none);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->captureRoute->getNavigation()->setMinAccuracy(Point::Accuracy::twoDigOfCM);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MenuCaptureRoute::init()
|
|
||||||
{
|
|
||||||
this->setCountPages(8);
|
|
||||||
MenuDriveMode::updateDelay = MenuCaptureRoute::updateDelay;
|
|
||||||
this->captureRoute = new CaptureRoute();
|
|
||||||
this->driveManager->changeModus(this->captureRoute);
|
|
||||||
MenuDriveMode::init();
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file menuCaptureRoute.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a class to print informations about CaptureRoute
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-01-31
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#ifndef MENU_CAPTURE_ROUTE_H
|
|
||||||
#define MENU_MANUAL_DRIVE_H
|
|
||||||
|
|
||||||
#include "SpecialMenus/driveModi/menuDriveMode.h"
|
|
||||||
#include "driveModi/Modi/CaptureRoute/captureRoute.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A class to print informations about the Autopilot
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class MenuCaptureRoute : public MenuDriveMode
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new Menu Capture Route object
|
|
||||||
*
|
|
||||||
* @param driveManager
|
|
||||||
*/
|
|
||||||
MenuCaptureRoute(DriveManager *driveManager) : MenuDriveMode(driveManager) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Prints the Information to display and console
|
|
||||||
*
|
|
||||||
* The informations are only printed to the display if it
|
|
||||||
* set.
|
|
||||||
*
|
|
||||||
* Changes the DriveModi to CaptureRoute if it is the first time called
|
|
||||||
* and save the CaptureRoute object.
|
|
||||||
*/
|
|
||||||
void printPage() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief can be called to update shown data
|
|
||||||
*/
|
|
||||||
void update() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void runCommand() override;
|
|
||||||
void init() override;
|
|
||||||
|
|
||||||
CaptureRoute *captureRoute = nullptr;
|
|
||||||
|
|
||||||
static constexpr uint16_t updateDelay = 500;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // MENU_MANUAL_DRIVE_H
|
|
||||||
@@ -48,7 +48,6 @@ void MenuDriveMode::left()
|
|||||||
|
|
||||||
this->firstPrint = true;
|
this->firstPrint = true;
|
||||||
this->configureOnLeave();
|
this->configureOnLeave();
|
||||||
delete this->menuSpeed;
|
|
||||||
this->driveManager->changeModus();
|
this->driveManager->changeModus();
|
||||||
MenuInformationSites::left();
|
MenuInformationSites::left();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,304 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file autopilot.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the implementation of the class Autopilot
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-02-02
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "driveModi/Modi/Autopilot/autopilot.h"
|
|
||||||
#include "autopilot.h"
|
|
||||||
|
|
||||||
DirectionChangeSignal::DirectionChangeSignal(Autopilot *pilot)
|
|
||||||
: pilot {pilot}
|
|
||||||
{
|
|
||||||
this->action();
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectionChangeSignal::~DirectionChangeSignal()
|
|
||||||
{
|
|
||||||
CalcAzimuth *calcAzimuth = pilot->getSensorData()->getCalcCompass();
|
|
||||||
if (static_cast<bool>(calcAzimuth))
|
|
||||||
{
|
|
||||||
calcAzimuth->disableCalcAzimuth();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirectionChangeSignal::action()
|
|
||||||
{
|
|
||||||
CalcAzimuth *calcAzimuth = pilot->getSensorData()->getCalcCompass();
|
|
||||||
if (static_cast<bool>(calcAzimuth))
|
|
||||||
{
|
|
||||||
calcAzimuth->drivingDirectionChange(pilot->getSensorData()->getCurrentPos());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Autopilot::~Autopilot()
|
|
||||||
{
|
|
||||||
delete this->directionChangeSignal;
|
|
||||||
// this->navigation->getNTRIPClient()->setActivated(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::run()
|
|
||||||
{
|
|
||||||
this->routeInfo = this->navigation->getRouteInfo();
|
|
||||||
|
|
||||||
switch (this->state)
|
|
||||||
{
|
|
||||||
case State::InsufficientAccuracy:
|
|
||||||
this->askNavigationForOrder();
|
|
||||||
return;
|
|
||||||
|
|
||||||
case State::NoRoute:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case State::None:
|
|
||||||
return;
|
|
||||||
|
|
||||||
case State::NavigationStarted:
|
|
||||||
this->askNavigationForOrder();
|
|
||||||
this->checkButtonInput();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::GetToStartPoint:
|
|
||||||
ManualControl::run();
|
|
||||||
this->askNavigationForOrder();
|
|
||||||
if (this->routeInfo.currentPoint >= 2){
|
|
||||||
this->state = State::SelfDrivingAvailable;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::SelfDrivingAvailable:
|
|
||||||
ManualControl::run();
|
|
||||||
this->askNavigationForOrder();
|
|
||||||
this->checkButtonInput();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::SelfDriving:
|
|
||||||
this->askNavigationForOrder();
|
|
||||||
this->checkButtonInput();
|
|
||||||
this->selfDriving();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SelfDrivingRotate:
|
|
||||||
this->checkButtonInput();
|
|
||||||
this->rotate();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case State::TargetReached:
|
|
||||||
if (this->loopMode){
|
|
||||||
this->restartLoop();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::restart()
|
|
||||||
{
|
|
||||||
this->init();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Autopilot::shouldUpdate()
|
|
||||||
{
|
|
||||||
if (this->updateDisplay)
|
|
||||||
{
|
|
||||||
this->updateDisplay = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::testRotate(int16_t degree)
|
|
||||||
{
|
|
||||||
if (!static_cast<bool>(degree))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->courseCorrection.correction = degree;
|
|
||||||
this->beginRotate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::init()
|
|
||||||
{
|
|
||||||
if (this->navigation->startNavigation())
|
|
||||||
{
|
|
||||||
this->state = State::NavigationStarted;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->state = State::NoRoute;
|
|
||||||
}
|
|
||||||
this->routeInfo = this->navigation->getRouteInfo();
|
|
||||||
this->sensorData->getNtripClient()->setAutoReconnect(true);
|
|
||||||
|
|
||||||
this->lastOrderStatus = this->navigation->getCourseCorrection(this->courseCorrection, true);
|
|
||||||
|
|
||||||
this->courseCorrection.correction = 0;
|
|
||||||
this->courseCorrection.distance = 0;
|
|
||||||
this->updateDisplay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::drive()
|
|
||||||
{
|
|
||||||
DrivingSpeeds speeds = {0, 0};
|
|
||||||
if (this->courseCorrection.distance >= this->minRemainingDistance)
|
|
||||||
{
|
|
||||||
speeds.x = this->maxSpeeds.x;
|
|
||||||
}
|
|
||||||
this->moveControl->setSpeeds(speeds);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::beginRotate()
|
|
||||||
{
|
|
||||||
if (this->state != State::SelfDrivingRotate)
|
|
||||||
{
|
|
||||||
this->lastState = this->state;
|
|
||||||
this->state = State::SelfDrivingRotate;
|
|
||||||
this->rotationAimAzimuth = this->getSensorData()->getRealAzimuth() + this->courseCorrection.correction;
|
|
||||||
this->rotationAimAzimuth = Navigation::fixDegree(this->rotationAimAzimuth);
|
|
||||||
|
|
||||||
DrivingSpeeds speeds = {0, 0};
|
|
||||||
if (this->courseCorrection.correction > 0)
|
|
||||||
{
|
|
||||||
speeds.rot = -this->maxSpeeds.rot;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
speeds.rot = this->maxSpeeds.rot;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->moveControl->setSpeeds(speeds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::rotate()
|
|
||||||
{
|
|
||||||
if (abs(this->getSensorData()->getRealAzimuth() - this->rotationAimAzimuth) < this->maxCourseDeviationBeforeAct)
|
|
||||||
{
|
|
||||||
this->endRotate();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((abs(this->getSensorData()->getRealAzimuth() - this->rotationAimAzimuth) < this->maxCourseDeviationBeforeAct * 3) &&
|
|
||||||
((this->courseCorrection.correction > 0 && this->rotationAimAzimuth < this->getSensorData()->getRealAzimuth()) || (this->courseCorrection.correction < 0 && this->rotationAimAzimuth > this->getSensorData()->getRealAzimuth())))
|
|
||||||
{
|
|
||||||
this->endRotate();
|
|
||||||
std::cout << "Autopilot::rotate: Rover rotated too far" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::endRotate()
|
|
||||||
{
|
|
||||||
if (this->state != State::SelfDrivingRotate)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->state = this->lastState;
|
|
||||||
this->sensorData->getCalcCompass()->drivingDirectionChange(this->sensorData->getCurrentPos());
|
|
||||||
this->moveControl->setRotationSpeed(0);
|
|
||||||
this->moveControl->emergencyStop();
|
|
||||||
this->moveControl->setDrivingStatus(MoveControl::Status::Drive);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::checkButtonInput()
|
|
||||||
{
|
|
||||||
if (ControlPadButton::isControlPadButtonPressed(this->input, ControlPadButton::PadButton::Action) && millis() - this->lastAutopilotChangeMillis > this->autopilotChangeDelayMillis)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (this->state == State::SelfDrivingAvailable)
|
|
||||||
{
|
|
||||||
this->state = State::SelfDriving;
|
|
||||||
}
|
|
||||||
else if (this->state == State::SelfDriving || this->state == State::SelfDrivingRotate)
|
|
||||||
{
|
|
||||||
this->state = State::SelfDrivingAvailable;
|
|
||||||
}
|
|
||||||
else if (this->state == State::NavigationStarted)
|
|
||||||
{
|
|
||||||
this->state = State::GetToStartPoint;
|
|
||||||
}
|
|
||||||
this->updateDisplay = true;
|
|
||||||
this->lastAutopilotChangeMillis = millis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::askNavigationForOrder()
|
|
||||||
{
|
|
||||||
this->lastOrderStatus = this->navigation->getCourseCorrection(this->courseCorrection);
|
|
||||||
switch (this->lastOrderStatus)
|
|
||||||
{
|
|
||||||
case Navigation::Status::Complete:
|
|
||||||
this->state = State::TargetReached;
|
|
||||||
this->moveControl->setSpeed(0);
|
|
||||||
this->moveControl->setRotationSpeed(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Navigation::Status::InsufficientAccuracy:
|
|
||||||
if (this->state == State::InsufficientAccuracy){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this->lastState = this->state;
|
|
||||||
this->state = State::InsufficientAccuracy;
|
|
||||||
this->moveControl->setSpeed(0);
|
|
||||||
this->moveControl->setRotationSpeed(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Navigation::Status::Unchanged:
|
|
||||||
if (this->state == State::InsufficientAccuracy){
|
|
||||||
this->state = this->lastState;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Navigation::Status::Updated:
|
|
||||||
if (this->state == State::InsufficientAccuracy){
|
|
||||||
this->state = this->lastState;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::selfDriving()
|
|
||||||
{
|
|
||||||
if (this->state != State::SelfDriving)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abs(this->courseCorrection.correction) >= this->maxCourseDeviationBeforeAct)
|
|
||||||
{
|
|
||||||
this->beginRotate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->drive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::restartLoop()
|
|
||||||
{
|
|
||||||
this->navigation->startNavigation();
|
|
||||||
this->state = State::SelfDriving;
|
|
||||||
this->routeInfo = this->navigation->getRouteInfo();
|
|
||||||
this->lastOrderStatus = this->navigation->getCourseCorrection(this->courseCorrection, true);
|
|
||||||
this->updateDisplay = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Autopilot::afterActivate()
|
|
||||||
{
|
|
||||||
this->setInputMode(ManualControl::InputMode::Digital);
|
|
||||||
this->directionChangeSignal = new DirectionChangeSignal(this);
|
|
||||||
this->setDirectionChangeCallback(this->directionChangeSignal);
|
|
||||||
this->navigation = new Navigation(this->sensorData);
|
|
||||||
this->init();
|
|
||||||
}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file autopilot.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a class which use the navigate class to drive automaticaly
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-02-02
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AUTOPILOT_H
|
|
||||||
#define AUTOPILOT_H
|
|
||||||
|
|
||||||
#include "navigation.h"
|
|
||||||
#include "driveModi/Modi/ManualControl/manualControl.h"
|
|
||||||
|
|
||||||
class DirectionChangeSignal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This class use the navigate class to drive automaticaly
|
|
||||||
*
|
|
||||||
* This class get the information from the navigate class. When an
|
|
||||||
* object of this class is constructed the rover can be driven manually.
|
|
||||||
* When the Rover is near to the first position of the Route, you can
|
|
||||||
* switch to automatic drive.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class Autopilot : public ManualControl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum State
|
|
||||||
{
|
|
||||||
InsufficientAccuracy = -2,
|
|
||||||
NoRoute = -1,
|
|
||||||
None = 0,
|
|
||||||
NavigationStarted,
|
|
||||||
GetToStartPoint,
|
|
||||||
SelfDrivingAvailable,
|
|
||||||
SelfDriving,
|
|
||||||
SelfDrivingRotate,
|
|
||||||
TargetReached
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroy the Autopilot object
|
|
||||||
*
|
|
||||||
* Disconnect the NTRIP-Client
|
|
||||||
*/
|
|
||||||
~Autopilot();
|
|
||||||
|
|
||||||
void restart();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Route Info object
|
|
||||||
*
|
|
||||||
* @return RouteInfo
|
|
||||||
*/
|
|
||||||
RouteInfo getRouteInfo() const { return this->routeInfo; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Course Correction object
|
|
||||||
*
|
|
||||||
* @return CourseCorrection
|
|
||||||
*/
|
|
||||||
CourseCorrection getCourseCorrection() const { return this->courseCorrection; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the State object
|
|
||||||
*
|
|
||||||
* @return State
|
|
||||||
*/
|
|
||||||
State getState() const { return this->state; }
|
|
||||||
Navigation *getNavigation() const { return this->navigation; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tells if there are new informations to display
|
|
||||||
*
|
|
||||||
* @return true
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
bool shouldUpdate();
|
|
||||||
void testRotate(int16_t degree);
|
|
||||||
void endRotate();
|
|
||||||
void switchLoopMode() { this->loopMode = !this->loopMode; }
|
|
||||||
bool getLoopMode() const { return this->loopMode; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
void init();
|
|
||||||
void drive();
|
|
||||||
void beginRotate();
|
|
||||||
void rotate();
|
|
||||||
void run() override;
|
|
||||||
void checkButtonInput();
|
|
||||||
void askNavigationForOrder();
|
|
||||||
void selfDriving();
|
|
||||||
void restartLoop();
|
|
||||||
void afterActivate() override;
|
|
||||||
|
|
||||||
Navigation *navigation = nullptr;
|
|
||||||
CourseCorrection courseCorrection{0, 0};
|
|
||||||
RouteInfo routeInfo{0, 0};
|
|
||||||
State state = State::None;
|
|
||||||
State lastState = State::None;
|
|
||||||
Navigation::Status lastOrderStatus;
|
|
||||||
DirectionChangeSignal *directionChangeSignal = nullptr;
|
|
||||||
|
|
||||||
bool updateDisplay = false;
|
|
||||||
bool loopMode = false;
|
|
||||||
|
|
||||||
uint8_t maxCourseDeviationBeforeAct = 5;
|
|
||||||
uint16_t autopilotChangeDelayMillis = 500;
|
|
||||||
uint32_t lastAutopilotChangeMillis = 0;
|
|
||||||
|
|
||||||
int16_t rotationAimAzimuth = 0;
|
|
||||||
|
|
||||||
double minRemainingDistance = 0.25;
|
|
||||||
};
|
|
||||||
|
|
||||||
class DirectionChangeSignal : public DirectionChangeWrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DirectionChangeSignal(Autopilot *pilot);
|
|
||||||
~DirectionChangeSignal();
|
|
||||||
void action() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Autopilot *pilot;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // AUTOPILOT_H
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file captureRoute.cpp
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains the implementation of the class CaptureRoute
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-02-15
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "driveModi/Modi/CaptureRoute/captureRoute.h"
|
|
||||||
#include "captureRoute.h"
|
|
||||||
|
|
||||||
CaptureRoute::~CaptureRoute()
|
|
||||||
{
|
|
||||||
delete this->navigation;
|
|
||||||
|
|
||||||
if (static_cast<bool>(this->sensorData->getNtripClient()))
|
|
||||||
{
|
|
||||||
this->sensorData->getNtripClient()->setActivated(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CaptureRoute::run()
|
|
||||||
{
|
|
||||||
ManualControl::run();
|
|
||||||
if (ControlPadButton::isControlPadButtonPressed(this->input, ControlPadButton::PadButton::Action))
|
|
||||||
{
|
|
||||||
this->status = this->navigation->addCurrentPosToRoute();
|
|
||||||
if (this->status == Navigation::Status::Updated)
|
|
||||||
{
|
|
||||||
this->lastSavedPoint = this->navigation->getCurrentPosition();
|
|
||||||
this->routeInfo = navigation->getRouteInfo();
|
|
||||||
this->updateDisplay = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CaptureRoute::afterActivate()
|
|
||||||
{
|
|
||||||
this->navigation = new Navigation(this->sensorData);
|
|
||||||
this->navigation->getRoute()->clear();
|
|
||||||
this->sensorData->getNtripClient()->setAutoReconnect(true);
|
|
||||||
this->routeInfo = navigation->getRouteInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
double CaptureRoute::getDistanceToLastPoint() const
|
|
||||||
{
|
|
||||||
if (!this->lastSavedPoint.isInit())
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return this->lastSavedPoint.distanceTo(this->navigation->getCurrentPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CaptureRoute::shouldUpdate()
|
|
||||||
{
|
|
||||||
if (this->updateDisplay)
|
|
||||||
{
|
|
||||||
this->updateDisplay = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file captureRoute.h
|
|
||||||
* @author Alexander Klein (alex@kleiax.de)
|
|
||||||
* @brief Contains a class to capture a driven route
|
|
||||||
* @version 0.1
|
|
||||||
* @date 2022-02-15
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2022
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CAPTURE_ROUTE_H
|
|
||||||
#define CAPTURE_ROUTE_H
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "driveModi/Modi/ManualControl/manualControl.h"
|
|
||||||
#include "navigation.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A class to capture a driven class
|
|
||||||
*
|
|
||||||
* This class inherits ManualControl so you can drive
|
|
||||||
* normally as in ManualControl. If GPS signal is valid
|
|
||||||
* you can add a Point everytime you want.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class CaptureRoute : public ManualControl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Destroy the Capture Route object
|
|
||||||
*
|
|
||||||
* Disconnect the NTRIP-Client
|
|
||||||
*/
|
|
||||||
~CaptureRoute();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Route Info object
|
|
||||||
*
|
|
||||||
* @return RouteInfo
|
|
||||||
*/
|
|
||||||
RouteInfo getRouteInfo() const { return this->routeInfo; }
|
|
||||||
|
|
||||||
Navigation::Status getLastStatus() const { return this->status; }
|
|
||||||
Navigation *getNavigation() const { return this->navigation; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the distance to the last saved oint
|
|
||||||
*
|
|
||||||
* @return double in meters
|
|
||||||
*/
|
|
||||||
double getDistanceToLastPoint() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tells if there are new informations to display
|
|
||||||
*
|
|
||||||
* @return true
|
|
||||||
* @return false
|
|
||||||
*/
|
|
||||||
bool shouldUpdate();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void run() override;
|
|
||||||
void afterActivate() override;
|
|
||||||
|
|
||||||
Navigation *navigation = nullptr;
|
|
||||||
RouteInfo routeInfo;
|
|
||||||
Point lastSavedPoint;
|
|
||||||
Navigation::Status status = Navigation::Status::Complete;
|
|
||||||
|
|
||||||
bool updateDisplay = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CAPTURE_ROUTE_H
|
|
||||||
@@ -47,7 +47,7 @@ void ManualControl::analogControl()
|
|||||||
|
|
||||||
void ManualControl::digitalControl()
|
void ManualControl::digitalControl()
|
||||||
{
|
{
|
||||||
static constexpr uint8_t deadzone = 120;
|
static constexpr uint8_t deadzone = 110;
|
||||||
const int16_t yAxis = this->input->x - 127;
|
const int16_t yAxis = this->input->x - 127;
|
||||||
const int16_t xAxis = this->input->y - 127;
|
const int16_t xAxis = this->input->y - 127;
|
||||||
|
|
||||||
|
|||||||
@@ -82,8 +82,6 @@ bool TestMode::drive(int16_t cmDistance, int16_t degree)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// forward or backward and left or right
|
|
||||||
// TODO: Calculate roationspeed
|
|
||||||
if (cmDistance < 0)
|
if (cmDistance < 0)
|
||||||
{
|
{
|
||||||
this->moveControl->setSpeed(-this->maxSpeeds.x);
|
this->moveControl->setSpeed(-this->maxSpeeds.x);
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
#include "moveControl.h"
|
#include "moveControl.h"
|
||||||
#include "driveModi/driveModi.h"
|
#include "driveModi/driveModi.h"
|
||||||
#include "navigation.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "controlPadInput.h"
|
#include "controlPadInput.h"
|
||||||
#include "component.h"
|
#include "component.h"
|
||||||
|
|||||||
+17
-30
@@ -39,13 +39,10 @@
|
|||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "menuAction.h"
|
#include "menuAction.h"
|
||||||
#include "SpecialMenus/driveModi/ManualDrive/menuManualDrive.h"
|
#include "SpecialMenus/driveModi/ManualDrive/menuManualDrive.h"
|
||||||
#include "SpecialMenus/driveModi/CaptureRoute/menuCaptureRoute.h"
|
|
||||||
#include "SpecialMenus/driveModi/Autopilot/menuAutopilot.h"
|
|
||||||
#include "SpecialMenus/driveModi/TestMode/menuTestMode.h"
|
#include "SpecialMenus/driveModi/TestMode/menuTestMode.h"
|
||||||
#include "SpecialMenus/driveModi/CalibrateCompass/menuCalibrateCompass.h"
|
#include "SpecialMenus/driveModi/CalibrateCompass/menuCalibrateCompass.h"
|
||||||
#include "SpecialMenus/Systeminformation/menuSysteminformation.h"
|
#include "SpecialMenus/Systeminformation/menuSysteminformation.h"
|
||||||
#include "SpecialMenus/PID/menuPidSettings.h"
|
#include "SpecialMenus/PID/menuPidSettings.h"
|
||||||
#include "SpecialMenus/Route/menuRoute.h"
|
|
||||||
#include "SpecialMenus/SensorData/menuSensorData.h"
|
#include "SpecialMenus/SensorData/menuSensorData.h"
|
||||||
#include "SpecialMenus/CalibrateBattery/menuCalibrateBattery.h"
|
#include "SpecialMenus/CalibrateBattery/menuCalibrateBattery.h"
|
||||||
|
|
||||||
@@ -125,12 +122,6 @@ void setup()
|
|||||||
sensorData = new SensorData();
|
sensorData = new SensorData();
|
||||||
sensorData->enableGnss(spiPort, PinNumbers::gnssSpiCs);
|
sensorData->enableGnss(spiPort, PinNumbers::gnssSpiCs);
|
||||||
sensorData->enableRealCompass();
|
sensorData->enableRealCompass();
|
||||||
sensorData->enableNtrip(static_cast<const char *>(NtripConfig::host),
|
|
||||||
NtripConfig::port,
|
|
||||||
static_cast<const char *>(NtripConfig::mountPoint),
|
|
||||||
static_cast<const char *>(NtripConfig::user),
|
|
||||||
static_cast<const char *>(NtripConfig::password));
|
|
||||||
// sensorData->enableGyroscope();
|
|
||||||
driveManager = new DriveManager(&moveController, sensorData, controlPad->getControlPadDataPtr());
|
driveManager = new DriveManager(&moveController, sensorData, controlPad->getControlPadDataPtr());
|
||||||
|
|
||||||
char wifiIndicator = 'X';
|
char wifiIndicator = 'X';
|
||||||
@@ -138,12 +129,16 @@ void setup()
|
|||||||
{
|
{
|
||||||
wifiIndicator = '-';
|
wifiIndicator = '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lcdWrapper = new LcdWrapper(lcd);
|
||||||
|
lcdWrapper->setCallback(lcdWrapperCallback);
|
||||||
|
lcdWrapper->loop();
|
||||||
|
|
||||||
lcd->backlight();
|
lcd->backlight();
|
||||||
|
lcd->setCursor(0, 0);
|
||||||
lcd->printf("%c Kleiax-Rover %c", wifiIndicator, wifiIndicator);
|
lcd->printf("%c Kleiax-Rover %c", wifiIndicator, wifiIndicator);
|
||||||
lcd->setCursor(0, 1);
|
lcd->setCursor(0, 1);
|
||||||
lcd->printf("WiFi channel %u", Network::getCurrentChannel());
|
lcd->printf("WiFi channel %u", Network::getCurrentChannel());
|
||||||
lcdWrapper = new LcdWrapper(lcd);
|
|
||||||
lcdWrapper->setCallback(lcdWrapperCallback);
|
|
||||||
|
|
||||||
makeMenu();
|
makeMenu();
|
||||||
|
|
||||||
@@ -160,7 +155,7 @@ void loop()
|
|||||||
lcdWrapper->loop();
|
lcdWrapper->loop();
|
||||||
mainBattery->loop();
|
mainBattery->loop();
|
||||||
|
|
||||||
// new Value ervery 0.5s
|
// new Value every 0.5s
|
||||||
if (mainBattery->isNewValue())
|
if (mainBattery->isNewValue())
|
||||||
{
|
{
|
||||||
static uint8_t batteryLowCounter = 0;
|
static uint8_t batteryLowCounter = 0;
|
||||||
@@ -193,14 +188,14 @@ void loop()
|
|||||||
void i2cScanner()
|
void i2cScanner()
|
||||||
{
|
{
|
||||||
constexpr uint8_t checkForLength = 16;
|
constexpr uint8_t checkForLength = 16;
|
||||||
constexpr uint8_t maxAdresses = UINT8_MAX / 2;
|
constexpr uint8_t maxAddresses = UINT8_MAX / 2;
|
||||||
std::cout << "\nI2C Scanner" << std::endl;
|
std::cout << "\nI2C Scanner" << std::endl;
|
||||||
|
|
||||||
byte error = 0;
|
byte error = 0;
|
||||||
byte address = 0;
|
byte address = 0;
|
||||||
int nDevices = 0;
|
int nDevices = 0;
|
||||||
std::cout << "Scanning..." << std::endl;
|
std::cout << "Scanning..." << std::endl;
|
||||||
for (address = 1; address < maxAdresses; address++)
|
for (address = 1; address < maxAddresses; address++)
|
||||||
{
|
{
|
||||||
Wire.beginTransmission(address);
|
Wire.beginTransmission(address);
|
||||||
error = Wire.endTransmission();
|
error = Wire.endTransmission();
|
||||||
@@ -254,32 +249,24 @@ void makeMenu()
|
|||||||
auto *pidr_m = new MenuIntInput(3, new MenuPidSettings(moveController.getPID(1)));
|
auto *pidr_m = new MenuIntInput(3, new MenuPidSettings(moveController.getPID(1)));
|
||||||
auto *speed_m = new MenuIntInput(2, new MenuSpeed(driveManager->getDrivingSpeedsRef()));
|
auto *speed_m = new MenuIntInput(2, new MenuSpeed(driveManager->getDrivingSpeedsRef()));
|
||||||
auto *man_m = new MenuManualControl(driveManager);
|
auto *man_m = new MenuManualControl(driveManager);
|
||||||
auto *cap_m = new MenuCaptureRoute(driveManager);
|
|
||||||
auto *auto_m = new MenuAutopilot(driveManager);
|
|
||||||
auto *testM_m = new MenuTestMode(driveManager);
|
auto *testM_m = new MenuTestMode(driveManager);
|
||||||
auto *comp_m = new MenuCalibrateCompass(driveManager);
|
auto *comp_m = new MenuCalibrateCompass(driveManager);
|
||||||
auto *sys_m = new MenuSysteminformation(mainBattery);
|
auto *sys_m = new MenuSysteminformation(mainBattery);
|
||||||
auto *sen_m = new MenuSensorData(sensorData);
|
auto *sen_m = new MenuSensorData(sensorData);
|
||||||
// TODO: Wie bekommt jeder die dumme Route?
|
|
||||||
auto *rout_m = new MenuRoute(new Route());
|
|
||||||
auto *bat_m = new MenuCalibrateBattery(mainBattery);
|
auto *bat_m = new MenuCalibrateBattery(mainBattery);
|
||||||
|
|
||||||
auto_m->setUpdateDelay(displayUpdateDelay);
|
|
||||||
sys_m->setUpdateDelay(displayUpdateDelay);
|
sys_m->setUpdateDelay(displayUpdateDelay);
|
||||||
sen_m->setUpdateDelay(displayUpdateDelay);
|
sen_m->setUpdateDelay(displayUpdateDelay);
|
||||||
|
|
||||||
// Entry for the main menu
|
// Entry for the main menu
|
||||||
main_m->addEntry(new MenuAction("Mode", mode_m));
|
main_m->addEntry(new MenuAction("Mode", mode_m));
|
||||||
main_m->addEntry(new MenuAction("Sensor", sen_m));
|
main_m->addEntry(new MenuAction("Sensor", sen_m));
|
||||||
main_m->addEntry(new MenuAction("Route", rout_m));
|
|
||||||
main_m->addEntry(new MenuAction("Settings", set_m));
|
main_m->addEntry(new MenuAction("Settings", set_m));
|
||||||
main_m->addEntry(new MenuAction("Systeminfo", sys_m));
|
main_m->addEntry(new MenuAction("Systeminfo", sys_m));
|
||||||
main_m->addEntry(new MenuAction("Restart", restart));
|
main_m->addEntry(new MenuAction("Restart", restart));
|
||||||
|
|
||||||
// Entry for the mode Menu
|
// Entry for the mode Menu
|
||||||
mode_m->addEntry(new MenuAction("Manual Control", man_m));
|
mode_m->addEntry(new MenuAction("Manual Control", man_m));
|
||||||
mode_m->addEntry(new MenuAction("Capture Route", cap_m));
|
|
||||||
mode_m->addEntry(new MenuAction("Autopilot", auto_m));
|
|
||||||
mode_m->addEntry(new MenuAction("Gauge Compass", comp_m));
|
mode_m->addEntry(new MenuAction("Gauge Compass", comp_m));
|
||||||
mode_m->addEntry(new MenuAction("Test Mode", testM_m));
|
mode_m->addEntry(new MenuAction("Test Mode", testM_m));
|
||||||
mode_m->addEntry(new MenuAction("Consol Control", dummy));
|
mode_m->addEntry(new MenuAction("Consol Control", dummy));
|
||||||
@@ -357,16 +344,16 @@ void lcdWrapperCallback(const char data[][LcdWrapper::totalRows], uint8_t lines,
|
|||||||
|
|
||||||
NetworkAddresses setIPs()
|
NetworkAddresses setIPs()
|
||||||
{
|
{
|
||||||
NetworkAddresses adresses;
|
NetworkAddresses addresses;
|
||||||
adresses.localIP.fromString(static_cast<const char *>(NetworkConfig::ip));
|
addresses.localIP.fromString(static_cast<const char *>(NetworkConfig::ip));
|
||||||
adresses.subnet.fromString(static_cast<const char *>(NetworkConfig::subnet));
|
addresses.subnet.fromString(static_cast<const char *>(NetworkConfig::subnet));
|
||||||
adresses.gateway.fromString(static_cast<const char *>(NetworkConfig::gateway));
|
addresses.gateway.fromString(static_cast<const char *>(NetworkConfig::gateway));
|
||||||
adresses.dnsServer.fromString(static_cast<const char *>(NetworkConfig::dns));
|
addresses.dnsServer.fromString(static_cast<const char *>(NetworkConfig::dns));
|
||||||
if (NetworkConfig::mqtt)
|
if (NetworkConfig::mqtt)
|
||||||
{
|
{
|
||||||
adresses.mqttServer.fromString(static_cast<const char *>(MqttConfig::server));
|
addresses.mqttServer.fromString(static_cast<const char *>(MqttConfig::server));
|
||||||
adresses.mqttPort = MqttConfig::port;
|
addresses.mqttPort = MqttConfig::port;
|
||||||
}
|
}
|
||||||
|
|
||||||
return adresses;
|
return addresses;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user