Skip to content

Commit

Permalink
Merge branch 'main' into crops_per_bed
Browse files Browse the repository at this point in the history
  • Loading branch information
LukasBaecker committed Dec 2, 2024
2 parents 44f627b + 4dc14c5 commit 6a7ad88
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 9 deletions.
7 changes: 7 additions & 0 deletions config/f16_config_rb43/camera.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
configuration = {
'parameters': {
'width': 1920,
'height': 1080,
'auto_exposure': True,
},
}
66 changes: 66 additions & 0 deletions config/f16_config_rb43/hardware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
configuration = {
'wheels': {
'version': 'double_wheels',
'name': 'wheels',
'left_back_can_address': 0x100,
'left_front_can_address': 0x000,
'right_back_can_address': 0x300,
'right_front_can_address': 0x200,
'is_left_reversed': True,
'is_right_reversed': False,
'odrive_version': 6,
},
'y_axis': {
'version': 'none',
},
'flashlight': {
'version': 'none',
},

'z_axis': {
'version': 'none',
},
'estop': {
'name': 'estop',
'pins': {'1': 34, '2': 35},
},
'bms': {
'name': 'bms',
'on_expander': True,
'rx_pin': 26,
'tx_pin': 27,
'baud': 9600,
'num': 2,
},
'battery_control': {
'name': 'battery_control',
'on_expander': True,
'reset_pin': 15,
'status_pin': 13,
},
'status_control': {
'name': 'status_control',
},
'bluetooth': {
'name': 'fieldfriend-f16',
},
'serial': {
'name': 'serial',
'rx_pin': 26,
'tx_pin': 27,
'baud': 115200,
'num': 1,
},
'expander': {
'name': 'p0',
'boot': 25,
'enable': 14,
},
'can': {
'name': 'can',
'on_expander': False,
'rx_pin': 32,
'tx_pin': 33,
'baud': 1_000_000,
},
}
11 changes: 11 additions & 0 deletions config/f16_config_rb43/params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
configuration = {
'motor_gear_ratio': 12.52,
'thooth_count': 15,
'pitch': 0.033,
'wheel_distance': 0.74,
'antenna_offset': 0.35,
'work_x': -0.06933333,
'work_y': 0.0094166667,
'drill_radius': 0.025,
'tool': 'none',
}
4 changes: 4 additions & 0 deletions config/f16_config_rb43/robotbrain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
configuration = {'robot_brain': {
'flash_params': ['nand', 'orin', 'v05']
},
}
6 changes: 3 additions & 3 deletions field_friend/automations/automation_watcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ def stop(self, reason: str) -> None:

def try_resume(self) -> None:
# Set conditions to True by default, which means they don't block the process if the watch is not active
# TODO: what to do if we don't have bumpers?
assert self.field_friend.bumper is not None
bumper_condition = not bool(self.field_friend.bumper.active_bumpers) if self.bumper_watch_active else True
bumper_condition = True
if self.field_friend.bumper is not None and self.bumper_watch_active:
bumper_condition = not bool(self.field_friend.bumper.active_bumpers)
gnss_condition = (self.gnss.current is not None and ('R' in self.gnss.current.mode or self.gnss.current.mode == 'SSSS')) \
if self.gnss_watch_active else True

Expand Down
30 changes: 26 additions & 4 deletions field_friend/automations/field.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import math
import uuid
from dataclasses import dataclass
from typing import Any, Self

Expand Down Expand Up @@ -167,15 +168,36 @@ def shapely_polygon(self) -> shapely.geometry.Polygon:

@classmethod
def args_from_dict(cls, data: dict[str, Any]) -> dict:
return data
# Ensure all required fields exist with defaults
defaults: dict[str, Any] = {
'id': str(uuid.uuid4()),
'name': 'Field',
'first_row_start': None,
'first_row_end': None,
'row_spacing': 1,
'row_count': 1,
'outline_buffer_width': 1,
'row_support_points': [],
'bed_count': 1,
'bed_spacing': 1
}
for key in defaults:
if key in data:
defaults[key] = data[key]
return defaults

@classmethod
def from_dict(cls, data: dict[str, Any]) -> Self:
data['first_row_start'] = GeoPoint(lat=data['first_row_start']['lat'], long=data['first_row_start']['long'])
data['first_row_end'] = GeoPoint(lat=data['first_row_end']['lat'], long=data['first_row_end']['long'])
data['first_row_start'] = GeoPoint(lat=data['first_row_start']['lat'],
long=data['first_row_start']['long']) if data.get('first_row_start') else GeoPoint(lat=0, long=0)
data['first_row_end'] = GeoPoint(lat=data['first_row_end']['lat'],
long=data['first_row_end']['long']) if data.get('first_row_end') else GeoPoint(lat=1, long=1)
data['row_support_points'] = [rosys.persistence.from_dict(
RowSupportPoint, sp) for sp in data['row_support_points']] if 'row_support_points' in data else []
RowSupportPoint, sp) for sp in data['row_support_points']] if data.get('row_support_points') else []
field_data = cls(**cls.args_from_dict(data))
# if id is None, set it to a random uuid
if field_data.id is None:
field_data.id = str(uuid.uuid4())
return field_data

def get_buffered_area(self, rows: list[Row], buffer_width: float) -> list[GeoPoint]:
Expand Down
2 changes: 2 additions & 0 deletions field_friend/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ def watch_robot() -> None:
self.current_implement = self.monitoring
if self.field_friend.bumper:
self.automation_watcher.bumper_watch_active = True
else:
self.log.warning('Bumper is not available, does robot have bumpers?')

if self.is_real:
assert isinstance(self.field_friend, FieldFriendHardware)
Expand Down
4 changes: 3 additions & 1 deletion tests/old_field_provider_persistence.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
"row_spacing": 0.5,
"row_count": 10,
"outline_buffer_width": 2,
"row_support_points": []
"row_support_points": [],
"bed_count": 1,
"bed_spacing": 0.5
}
}
}
19 changes: 19 additions & 0 deletions tests/old_field_provider_persistence_with_errors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"fields": {
"eb24db0f-d48e-4a88-b23a-4833cda55483": {
"id": "eb24db0f-d48e-4a88-b23a-4833cda55483",
"name": "field_1",
"first_row_start": {
"lat": 51.98333789813455,
"long": 7.434242765994318
},
"first_row_end": { "lat": 51.98334192260392, "long": 7.434293309874038 },
"row_spacing": 0.5,
"row_count": 10,
"not_existing_value": true,
"row_support_points": [],
"bed_count": 1,
"bed_spacing": 0.5
}
}
}
21 changes: 20 additions & 1 deletion tests/test_field_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from field_friend.localization import GeoPoint


def test_loading_from_old_persistence(system: System):
def test_loading_from_persistence(system: System):
system.field_provider.restore(json.loads(Path('tests/old_field_provider_persistence.json').read_text()))
assert len(system.field_provider.fields) == 1
field = system.field_provider.fields[0]
Expand All @@ -27,6 +27,25 @@ def test_loading_from_old_persistence(system: System):
assert field.first_row_end == GeoPoint(lat=51.98334192260392, long=7.434293309874038)


def test_loading_from_persistence_with_errors(system: System):
system.field_provider.restore(json.loads(Path('tests/old_field_provider_persistence_with_errors.json').read_text()))
assert len(system.field_provider.fields) == 1
field = system.field_provider.fields[0]
# should set outline_buffer_width to default value because it is missing in the persistence data
assert field.outline_buffer_width == 1
# should not write the not_existing_value to the field
assert not hasattr(field, 'not_existing_value')
assert field.row_count == 10
assert field.row_spacing == 0.5
assert len(field.outline) == 5
assert len(field.rows) == 10
assert len(field.row_support_points) == 0
for row in field.rows:
assert len(row.points) == 2
assert field.first_row_start == FIELD_FIRST_ROW_START
assert field.first_row_end == GeoPoint(lat=51.98334192260392, long=7.434293309874038)


def test_field_outline(system: System, field: Field):
field = system.field_provider.fields[0]
outline = field.outline
Expand Down

0 comments on commit 6a7ad88

Please sign in to comment.