Skip to content

Commit

Permalink
Trying to fix last will message for API
Browse files Browse the repository at this point in the history
First updates to the API, preparing for new UI
Added uiid for map coords and mow preview for new UI
  • Loading branch information
EinEinfach committed Jun 17, 2024
1 parent c83aba7 commit df7c3e0
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CaSSAndRA/app.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env python3

#Version:0.116.0 Added finish and restart button, some improvements on path planner
#Version:0.117.0 Some changes on API
# package imports
import os
import sys
Expand Down
2 changes: 1 addition & 1 deletion CaSSAndRA/src/backend/backendserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ def start(file_paths) -> None:
cfg = cfg = dict(CLIENT_ID=cfgdata.commcfg.api_mqtt_client_id, USERNAME=cfgdata.commcfg.api_mqtt_username, PASSWORD=cfgdata.commcfg.api_mqtt_pass,
MQTT_SERVER=cfgdata.commcfg.api_mqtt_server, PORT=cfgdata.commcfg.api_mqtt_port, NAME=cfgdata.commcfg.api_mqtt_cassandra_server_name)
mqttapi.create(cfg, topics)
mqttapi.client.will_set(mqttapi.mqtt_mower_name+'/status', payload='offline')
mqttapi.client.will_set(mqttapi.mqtt_mower_name+'/status', payload='offline', retain=True)
mqttapi.connect()
connection_start = datetime.now()
while mqttapi.client.connection_flag != True:
Expand Down
13 changes: 13 additions & 0 deletions CaSSAndRA/src/backend/comm/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from .. data.cfgdata import schedulecfg, pathplannercfgapi
from .. map import path, map
from .. comm import cmdlist
from .. comm.connections import mqttapi
from .. data.roverdata import robot

from icecream import ic
Expand All @@ -21,11 +22,13 @@ class API:
mapsstate: dict = field(default_factory=dict)
mowparametersstate: dict = field(default_factory=dict)
mapstate: dict = field(default_factory=dict)
coordsstate: dict = field(default_factory=dict)
robotstate_json: str = '{}'
tasksstate_json: str = '{}'
mapsstate_json: str = '{}'
mowparametersstate_json: str = '{}'
mapstate_json: str ='{}'
coordsstate_json: str = '{}'
loaded_tasks: list = field(default_factory=list)
commanded_object: str = ''
command: str = ''
Expand All @@ -40,6 +43,7 @@ def create_robot_payload(self) -> None:
self.robotstate['battery'] = dict(soc=robot.soc, voltage=robot.battery_voltage, electricCurrent=robot.amps)
self.robotstate['position'] = dict(x=robot.position_x, y=robot.position_y)
self.robotstate['target'] = dict(x=robot.target_x, y=robot.target_y)
self.robotstate['angle'] = robot.position_delta
self.robotstate_json = json.dumps(self.robotstate)

def create_maps_payload(self) -> None:
Expand Down Expand Up @@ -76,9 +80,15 @@ def create_mow_parameters_payload(self) -> None:
self.mowparametersstate_json = json.dumps(self.mowparametersstate)

def create_map_payload(self) -> None:
self.mapstate['mapId'] = current_map.map_id
self.mapstate['previewId'] = current_map.previewId
self.mapstate['mowprogressIdxPercent'] = current_map.idx_perc
self.mapstate['mowprogressDistancePercent'] = current_map.distance_perc
self.mapstate_json = json.dumps(self.mapstate)

def create_coords_payload(self) -> None:
self.coordsstate = current_map.perimeter_to_geojson()
self.coordsstate_json = json.dumps(self.coordsstate)

def update_payload(self) -> None:
self.create_api_payload()
Expand Down Expand Up @@ -109,6 +119,9 @@ def check_cmd(self, buffer: dict) -> None:
self.commanded_object = 'map'
buffer = buffer['map']
self.check_map_cmd(buffer)
elif 'coords' in buffer:
self.create_coords_payload()
mqttapi.api_publish('coords', self.coordsstate_json)
else:
logger.info('No valid object in api message found. Aborting')

Expand Down
2 changes: 1 addition & 1 deletion CaSSAndRA/src/backend/data/appdata.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import logging
logger = logging.getLogger(__name__)

version = '0.116.0'
version = '0.117.0'
37 changes: 36 additions & 1 deletion CaSSAndRA/src/backend/data/mapdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from dataclasses import dataclass, field, asdict
from shapely.geometry import *
from PIL import Image
import uuid

from .roverdata import robot
from .cfgdata import PathPlannerCfg, pathplannercfg, rovercfg
Expand All @@ -20,6 +21,7 @@
@dataclass
class Perimeter:
name: str = ''
map_id: str = None
angle_offset: int = 0
perimeter: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())
perimeter_polygon: Polygon = Polygon()
Expand All @@ -32,6 +34,7 @@ class Perimeter:
gotopoint: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())
mowpath: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())
preview: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())
previewId: str = None
obstacles: pd.DataFrame = field(default_factory=lambda: pd.DataFrame())
obstacle_img: Image = field(default_factory = lambda:
Image.open(os.path.dirname(__file__).replace('/backend/data', '/assets/icons/obstacle.png')))
Expand Down Expand Up @@ -223,6 +226,7 @@ def create(self, name: str) -> None:
self.preview = pd.DataFrame()
self.mowpath = pd.DataFrame()
self.obstacles = pd.DataFrame()
self.map_id = str(uuid.uuid4())
self.create_perimeter_polygon()
self.create_perimeter_for_plot()
self.create_points_from_polygon()
Expand All @@ -234,6 +238,7 @@ def calc_route_preview(self, route: list) -> None:
self.preview = pd.DataFrame(route)
self.preview.columns = ['X', 'Y']
self.preview['type'] = 'preview route'
self.previewId = str(uuid.uuid4())

def read_map_name(self) -> str:
try:
Expand All @@ -247,7 +252,7 @@ def read_map_name(self) -> str:
return ''

def save_map_name(self) -> None:
tmp_data = {'PERIMETERNAME': self.name}
tmp_data = {'PERIMETERNAME': self.name, 'MAPID': self.map_id}
try:
with open(self.current_perimeter_file, 'w') as f:
json.dump(tmp_data, f, indent=4)
Expand Down Expand Up @@ -302,6 +307,36 @@ def calc_mow_progress(self) -> None:
self.finished_idx = 0
self.idx = 0
self.idx_perc = 0

def perimeter_to_geojson(self) -> str:
try:
logger.info('Exporting current map to geojson')
perimeter_for_export = self.perimeter_for_plot
if not perimeter_for_export.empty:
geojson = dict(type="FeatureCollection", features=[])
#perimeter
coords = perimeter_for_export[perimeter_for_export['type'] == 'perimeter']
value = dict(type="Feature", properties=dict(name="perimeter"), geometry=dict(dict(type="Polygon", coordinates=[coords[['X', 'Y']].values.tolist()])))
geojson['features'].append(value)
#dockpoints
coords = perimeter_for_export[perimeter_for_export['type'] == 'dockpoints']
value = dict(type="Feature", properties=dict(name="dockpoints"), geometry=dict(dict(type="LineString", coordinates=coords[['X', 'Y']].values.tolist())))
geojson['features'].append(value)
#search wire
coords = perimeter_for_export[perimeter_for_export['type'] == 'search wire']
value = dict(type="Feature", properties=dict(name="search wire"), geometry=dict(dict(type="LineString", coordinates=coords[['X', 'Y']].values.tolist())))
geojson['features'].append(value)
#exclusions
filtered = perimeter_for_export[(perimeter_for_export['type'] != 'perimeter') & (perimeter_for_export['type'] != 'dockpoints') & (perimeter_for_export['type'] != 'search wire')]
for i, exclusion in enumerate(filtered['type'].unique()):
coords = perimeter_for_export[perimeter_for_export['type'] == exclusion]
value = dict(type="Feature", properties=dict(name="exclusion"), idx=i, geometry=dict(dict(type="Polygon", coordinates=[coords[['X', 'Y']].values.tolist()])))
geojson['features'].append(value)
return geojson
except Exception as e:
logger.error('Could not export current map to gejson')
logger.debug(f'{e}')
return e

@dataclass
class Perimeters:
Expand Down

0 comments on commit df7c3e0

Please sign in to comment.