From b9af332ca9c5db4a7004e7d60edb05d61e0043c3 Mon Sep 17 00:00:00 2001 From: Pascal Schade <165774906+pascalzauberzeug@users.noreply.github.com> Date: Tue, 24 Sep 2024 07:55:01 +0200 Subject: [PATCH] Move to new learning loop project and update detector (#181) We will move the plant detection to a new learning loop project. These are the needed changes on the field_friend side --- docker-compose.jetson.orin.yml | 11 ++++------- .../automations/implements/weeding_implement.py | 2 +- .../automations/implements/weeding_screw.py | 2 +- field_friend/automations/plant_locator.py | 5 +++-- .../interface/components/plant_object.py | 12 +++++++----- field_friend/interface/components/robot_scene.py | 3 +-- field_friend/system.py | 10 ---------- tests/test_weeding.py | 16 ++++++++-------- 8 files changed, 25 insertions(+), 36 deletions(-) diff --git a/docker-compose.jetson.orin.yml b/docker-compose.jetson.orin.yml index 886d2967..7cfab951 100644 --- a/docker-compose.jetson.orin.yml +++ b/docker-compose.jetson.orin.yml @@ -6,7 +6,7 @@ services: privileged: true detector: - image: "zauberzeug/yolov5-detector:0.1.2-nlv0.10.10-35.4.1" + image: "zauberzeug/yolov5-detector:0.1.3-nlv0.10.12-35.4.1" restart: always ports: - "8004:80" @@ -14,16 +14,13 @@ services: environment: - HOST=learning-loop.ai - NVIDIA_VISIBLE_DEVICES=all - # - ORGANIZATION=zauberzeug - # - PROJECT=coins - - ORGANIZATION=zuckerruebe - - PROJECT=uckerbots + - ORGANIZATION=feldfreund + - PROJECT=plants volumes: - # - ~/data_coins:/data - ~/data_plants:/data monitoring: - image: "zauberzeug/yolov5-detector:0.1.2-nlv0.10.10-35.4.1" + image: "zauberzeug/yolov5-detector:0.1.3-nlv0.10.12-35.4.1" restart: always ports: - "8005:80" diff --git a/field_friend/automations/implements/weeding_implement.py b/field_friend/automations/implements/weeding_implement.py index 09f90b7b..f01ae2c4 100644 --- a/field_friend/automations/implements/weeding_implement.py +++ b/field_friend/automations/implements/weeding_implement.py @@ -26,7 +26,7 @@ def __init__(self, name: str, system: 'System', persistence_key: str = 'weeding rosys.persistence.PersistentModule.__init__(self, persistence_key=f'field_friend.automations.implements.{persistence_key}') - self.relevant_weeds = system.small_weed_category_names + system.big_weed_category_names + self.relevant_weeds = system.plant_locator.weed_category_names self.log = logging.getLogger('field_friend.weeding') self.system = system self.kpi_provider = system.kpi_provider diff --git a/field_friend/automations/implements/weeding_screw.py b/field_friend/automations/implements/weeding_screw.py index 14669b6b..46119dd3 100644 --- a/field_friend/automations/implements/weeding_screw.py +++ b/field_friend/automations/implements/weeding_screw.py @@ -14,7 +14,7 @@ class WeedingScrew(WeedingImplement): def __init__(self, system: 'System') -> None: super().__init__('Weed Screw', system, 'weeding_screw') - self.relevant_weeds = system.small_weed_category_names + system.big_weed_category_names + self.relevant_weeds = system.plant_locator.weed_category_names self.log.info(f'Using relevant weeds: {self.relevant_weeds}') self.weed_screw_depth: float = 0.13 self.max_crop_distance: float = 0.08 diff --git a/field_friend/automations/plant_locator.py b/field_friend/automations/plant_locator.py index a23ce1e7..b7b5e255 100644 --- a/field_friend/automations/plant_locator.py +++ b/field_friend/automations/plant_locator.py @@ -8,8 +8,9 @@ from .plant import Plant -WEED_CATEGORY_NAME = ['coin', 'weed', 'big_weed', 'thistle', 'orache', 'weedy_area', ] -CROP_CATEGORY_NAME = ['coin_with_hole', 'crop', 'sugar_beet', 'onion', 'garlic', ] +WEED_CATEGORY_NAME = ['coin', 'weed', 'big_weed', 'weedy_area', ] +CROP_CATEGORY_NAME = ['coin_with_hole', 'borrietsch', 'estragon', 'feldsalat', 'garlic', 'jasione', 'kohlrabi', 'liebstoeckel', 'maize', 'minze', 'onion', + 'oregano_majoran', 'pastinake', 'petersilie', 'pimpinelle', 'red_beet', 'salatkopf', 'schnittlauch', 'sugar_beet', 'thymian_bohnenkraut', 'zitronenmelisse', ] MINIMUM_CROP_CONFIDENCE = 0.3 MINIMUM_WEED_CONFIDENCE = 0.3 diff --git a/field_friend/interface/components/plant_object.py b/field_friend/interface/components/plant_object.py index 3db2265a..eb4be64f 100644 --- a/field_friend/interface/components/plant_object.py +++ b/field_friend/interface/components/plant_object.py @@ -1,18 +1,20 @@ import logging +from typing import TYPE_CHECKING import rosys from nicegui.elements.scene_objects import Group, Sphere -from ...automations import PlantProvider +if TYPE_CHECKING: + from system import System class plant_objects(Group): - def __init__(self, plant_provider: PlantProvider, weed_category_names: list[str]) -> None: + def __init__(self, system: 'System') -> None: super().__init__() - self.plant_provider = plant_provider - self.weed_category_names = weed_category_names + self.plant_provider = system.plant_provider + self.plant_locator = system.plant_locator self.log = logging.getLogger('field_friend.plant_objects') self.update() self.plant_provider.PLANTS_CHANGED.register_ui(self.update) @@ -29,7 +31,7 @@ def update(self) -> None: obj.delete() for id, plant in in_world.items(): if id not in rendered: - if plant.type in self.weed_category_names: + if plant.type in self.plant_locator.weed_category_names: Sphere(0.02).with_name(f'plant_{plant.type}:{id}') \ .material('#ef1208') \ .move(plant.position.x, plant.position.y, 0.02) diff --git a/field_friend/interface/components/robot_scene.py b/field_friend/interface/components/robot_scene.py index 4af25ffa..01b762a6 100644 --- a/field_friend/interface/components/robot_scene.py +++ b/field_friend/interface/components/robot_scene.py @@ -33,8 +33,7 @@ def toggle_lock(): with ui.scene(200, 200, on_click=self.handle_click, grid=False).classes('w-full') as self.scene: field_friend_object(self.system.odometer, self.system.camera_provider, self.system.field_friend) rosys.driving.driver_object(self.system.driver) - plant_objects(self.system.plant_provider, - self.system.big_weed_category_names + self.system.small_weed_category_names) + plant_objects(self.system) visualizer_object(self.system) field_object(self.system.field_provider, self.system.field_navigation.field) self.scene.move_camera(-0.5, -1, 2) diff --git a/field_friend/system.py b/field_friend/system.py index 0875d133..70898fdb 100644 --- a/field_friend/system.py +++ b/field_friend/system.py @@ -92,17 +92,7 @@ def watch_robot() -> None: self.kpi_provider.increment_on_rising_edge('low_battery', self.field_friend.bms.is_below_percent(10.0)) self.puncher = Puncher(self.field_friend, self.driver, self.kpi_provider) - self.big_weed_category_names = ['big_weed', 'thistle', 'orache', 'kamille', ] - self.small_weed_category_names = ['coin', 'weed',] - self.crop_category_names = [ - 'coin_with_hole', 'sugar_beet', 'onion', 'garlic', 'maize', 'liebstoekel', - 'red_beet', 'kohlrabi', 'schnittlauch', 'petersilie', 'bohnenkraut', 'sauerampfer', - 'oregano', 'pimpinelle', 'borrietsch', 'estragon', 'zitronenmelisse', 'pfefferminze', - 'marokanische_minze', 'thymian', - ] self.plant_locator = PlantLocator(self) - self.plant_locator.weed_category_names = self.big_weed_category_names + self.small_weed_category_names - self.plant_locator.crop_category_names = self.crop_category_names rosys.on_repeat(watch_robot, 1.0) diff --git a/tests/test_weeding.py b/tests/test_weeding.py index ac303993..5bdf4c6f 100644 --- a/tests/test_weeding.py +++ b/tests/test_weeding.py @@ -9,7 +9,7 @@ async def test_working_with_weeding_screw(system: System, detector: rosys.vision.DetectorSimulation): detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='maize', position=rosys.geometry.Point3d(x=0.2, y=0.0, z=0))) - detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='thistle', + detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='big_weed', position=rosys.geometry.Point3d(x=0.2, y=0.05, z=0))) system.current_implement = system.implements['Weed Screw'] system.current_navigation = system.straight_line_navigation @@ -22,7 +22,7 @@ async def test_working_with_weeding_screw(system: System, detector: rosys.vision async def test_keep_crops_safe(system: System, detector: rosys.vision.DetectorSimulation): detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='maize', position=rosys.geometry.Point3d(x=0.2, y=0.0, z=0))) - detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='thistle', + detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='big_weed', position=rosys.geometry.Point3d(x=0.2, y=system.field_friend.DRILL_RADIUS-0.01, z=0))) system.current_implement = system.implements['Weed Screw'] system.current_navigation = system.straight_line_navigation @@ -36,7 +36,7 @@ async def test_keep_crops_safe(system: System, detector: rosys.vision.DetectorSi async def test_weeding_screw_only_targets_big_weed(system: System, detector: rosys.vision.DetectorSimulation): detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='weed', position=rosys.geometry.Point3d(x=0.2, y=0.0, z=0))) - detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='thistle', + detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='big_weed', position=rosys.geometry.Point3d(x=0.15, y=0, z=0))) system.current_implement = system.implements['Weed Screw'] system.current_navigation = system.straight_line_navigation @@ -47,9 +47,9 @@ async def test_weeding_screw_only_targets_big_weed(system: System, detector: ros async def test_weeding_screw_does_not_skip_close_weed(system: System, detector: rosys.vision.DetectorSimulation): - detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='thistle', + detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='big_weed', position=rosys.geometry.Point3d(x=0.2, y=0, z=0))) - detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='thistle', + detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='big_weed', position=rosys.geometry.Point3d(x=0.2+system.field_friend.DRILL_RADIUS-0.01, y=0.05, z=0))) system.current_implement = system.implements['Weed Screw'] system.current_navigation = system.straight_line_navigation @@ -61,9 +61,9 @@ async def test_weeding_screw_does_not_skip_close_weed(system: System, detector: async def test_weeding_screw_focus_on_weed_close_to_crop(system: System, detector: rosys.vision.DetectorSimulation): detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='maize', position=rosys.geometry.Point3d(x=0.2, y=0.0, z=0))) - detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='thistle', + detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='big_weed', position=rosys.geometry.Point3d(x=0.1, y=0, z=0))) - detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='thistle', + detector.simulated_objects.append(rosys.vision.SimulatedObject(category_name='big_weed', position=rosys.geometry.Point3d(x=0.16, y=0, z=0))) system.current_implement = system.implements['Weed Screw'] system.current_navigation = system.straight_line_navigation @@ -73,7 +73,7 @@ async def test_weeding_screw_focus_on_weed_close_to_crop(system: System, detecto system.automator.start() await forward(40) assert len(detector.simulated_objects) == 2 - assert detector.simulated_objects[1].category_name == 'thistle' + assert detector.simulated_objects[1].category_name == 'big_weed' assert detector.simulated_objects[1].position.x == 0.1