diff --git a/field_friend/interface/components/operation.py b/field_friend/interface/components/operation.py index 9919ba85..267561a3 100644 --- a/field_friend/interface/components/operation.py +++ b/field_friend/interface/components/operation.py @@ -61,7 +61,6 @@ def show_field_selection() -> None: ui.separator() with ui.row(): ui.label('Automation').classes('text-xl') - ui.label('Automation').classes('text-xl') with ui.row().classes('w-full'): self.automations_toggle = ui.select([key for key in self.system.automations.keys()], on_change=self.handle_automation_changed) \ @@ -114,209 +113,137 @@ def show_field_selection() -> None: with ui.row().bind_visibility_from(self.with_field_planning, 'value', value=True): self.show_start_row() self.show_end_row() - ui.number('Min. turning radius', format='%.2f', value=0.5, step=0.05, min=0.05, max=2.0) \ - .props('dense outlined suffix=m').classes('w-30').bind_value( - self.system.weeding, 'minimum_turning_radius').tooltip( - ui.number('Min. turning radius', format='%.2f', - value=0.5, step=0.05, min=0.05, max=2.0) - .props('dense outlined suffix=m').classes('w-30').bind_value( - self.system.weeding, 'minimum_turning_radius').tooltip( - 'Set the turning radius for the weeding automation') - ui.number('turn_offset', format='%.2f', value=0.4, step=0.05, min=0.05, max=2.0) - .props('dense outlined suffix=m').classes('w-30').bind_value( - self.system.weeding, 'turn_offset').tooltip( - 'Set the turning offset for the weeding automation') - ui.separator() - ui.markdown('Detector settings').style('color: #6E93D6') - with ui.row(): - ui.number('Min. weed confidence', format='%.2f', - value=0.8, step=0.05, min=0.0, max=1.0) - .props('dense outlined').classes('w-24').bind_value( - self.system.plant_locator, 'minimum_weed_confidence').tooltip( - 'Set the minimum weed confidence for the weeding automation') - ui.number('Min. crop confidence', format='%.2f', - value=0.4, step=0.05, min=0.0, max=1.0) - .props('dense outlined').classes('w-24').bind_value( - self.system.plant_locator, 'minimum_crop_confidence').tooltip( - 'Set the minimum crop confidence for the weeding automation') - ui.separator() - ui.markdown('Tool settings').style('color: #6E93D6') - with ui.row(): - if self.system.field_friend.tool == 'tornado': - ui.number('turn_offset', format='%.2f', value=0.4, step=0.05, min=0.05, max=2.0) - .props('dense outlined suffix=m').classes('w-30').bind_value( - self.system.weeding, 'turn_offset').tooltip( - 'Set the turning offset for the weeding automation') - ui.separator() - ui.markdown('Detector settings').style('color: #6E93D6') - with ui.row(): - ui.number('Min. weed confidence', format='%.2f', - value=0.8, step=0.05, min=0.0, max=1.0) - .props('dense outlined').classes('w-24').bind_value( - self.system.plant_locator, 'minimum_weed_confidence').tooltip( - 'Set the minimum weed confidence for the weeding automation') - ui.number('Min. crop confidence', format='%.2f', - value=0.4, step=0.05, min=0.0, max=1.0) - .props('dense outlined').classes('w-24').bind_value( - self.system.plant_locator, 'minimum_crop_confidence').tooltip( - 'Set the minimum crop confidence for the weeding automation') - ui.separator() - ui.markdown('Tool settings').style('color: #6E93D6') - with ui.row(): - if self.system.field_friend.tool == 'tornado': - ui.number('Tornado angle', format='%.0f', value=180, step=1, min=1, max=180).props( - 'dense outlined suffix=°').classes('w-24').bind_value( - self.system.weeding, 'tornado_angle').tooltip( - 'Set the angle for the tornado drill') - elif self.system.field_friend.tool in ['weed_screw', 'dual_mechanism']: - ui.number('Drill depth', value=0.02, format='%.2f', step=0.01, - min=self.system.field_friend.z_axis.max_position, max=self.system.field_friend.z_axis.min_position*-1) - .props('dense outlined suffix=°').classes('w-24').bind_value( - self.system.weeding, 'weed_screw_depth').tooltip( - 'Set the drill depth for the weeding automation') - ui.number('Crop safety distance', value=0.01, step=0.01, min=0.0, max=0.05, format='%.2f').props( - 'dense outlined suffix=m').classes('w-24').bind_value( - self.system.weeding, 'crop_safety_distance').tooltip( - 'Set the crop safety distance for the weeding automation') - - ui.separator() - ui.markdown('Workflow settings').style('color: #6E93D6') - with ui.row(): - if self.system.field_friend.tool == 'tornado': - ui.checkbox('Drill 2x with open torando', value=False, on_change=system.weeding.invalidate).bind_value( - self.system.weeding, 'drill_with_open_tornado').tooltip( - 'Set the weeding automation to drill a second time with open tornado') - ui.checkbox('Drill between crops', value=False).bind_value( - self.system.weeding, 'drill_between_crops').tooltip( - 'Set the weeding automation to drill between crops') - elif self.system.field_friend.tool == 'dual_mechanism': - - ui.checkbox('Drilling', value=False).bind_value( - self.system.weeding, 'with_drilling').tooltip( - 'Set the weeding automation to with drill') - ui.checkbox('Chopping', value=False).bind_value( - self.system.weeding, 'with_chopping').tooltip( - 'Set the weeding automation to with chop') - - ui.checkbox('Chop if no crops', value=False).bind_value( - self.system.weeding, 'chop_if_no_crops').tooltip( - 'Set the weeding automation to chop also if no crops seen') - - ui.checkbox('Only monitoring').bind_value( - self.system.weeding, 'only_monitoring').tooltip( - 'Set the weeding automation to only monitor the field') - ui.separator() - ui.markdown('**Driver settings**').style('color: #6E93D6') - with ui.row(): - ui.number('linear_speed_on_row', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=m/s').classes('w-24') - .bind_value(self.system.weeding, 'linear_speed_on_row') - .tooltip('Set the linear speed on row for the weeding automation') - ui.number('linear_speed_between_rows', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=m/s').classes('w-24') - .bind_value(self.system.weeding, 'linear_speed_between_rows') - .tooltip('Set the linear speed between rows for the weeding automation') - ui.number('angular_speed_on_row', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=°/s').classes('w-24') - .bind_value(self.system.weeding, 'angular_speed_on_row') - .tooltip('Set the angular speed on row for the weeding automation') - ui.number('angular_speed_between_rows', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=°/s').classes('w-24') - .bind_value(self.system.weeding, 'angular_speed_between_rows') - .tooltip('Set the angular speed between rows for the weeding automation') - elif self.system.field_friend.tool in ['weed_screw', 'dual_mechanism']: - ui.number('Drill depth', value=0.02, format='%.2f', step=0.01, - min=self.system.field_friend.z_axis.max_position, max=self.system.field_friend.z_axis.min_position*-1) - .props('dense outlined suffix=°').classes('w-24').bind_value( - self.system.weeding, 'weed_screw_depth').tooltip( - 'Set the drill depth for the weeding automation') - ui.number('Crop safety distance', value=0.01, step=0.01, min=0.0, max=0.05, format='%.2f').props( - 'dense outlined suffix=m').classes('w-24').bind_value( - self.system.weeding, 'crop_safety_distance').tooltip( - 'Set the crop safety distance for the weeding automation') - ui.separator() - ui.markdown('Workflow settings').style('color: #6E93D6') - with ui.row(): - if self.system.field_friend.tool == 'tornado': - ui.checkbox('Drill 2x with open torando', value=False, on_change=system.weeding.invalidate).bind_value( - self.system.weeding, 'drill_with_open_tornado').tooltip( - 'Set the weeding automation to drill a second time with open tornado') - ui.checkbox('Drill between crops', value=False).bind_value( - self.system.weeding, 'drill_between_crops').tooltip( - 'Set the weeding automation to drill between crops') - elif self.system.field_friend.tool == 'dual_mechanism': - - ui.checkbox('Drilling', value=False).bind_value( - self.system.weeding, 'with_drilling').tooltip( - 'Set the weeding automation to with drill') - ui.checkbox('Chopping', value=False).bind_value( - self.system.weeding, 'with_chopping').tooltip( - 'Set the weeding automation to with chop') - - ui.checkbox('Chop if no crops', value=False).bind_value( - self.system.weeding, 'chop_if_no_crops').tooltip( - 'Set the weeding automation to chop also if no crops seen') - - ui.checkbox('Only monitoring').bind_value( - self.system.weeding, 'only_monitoring').tooltip( - 'Set the weeding automation to only monitor the field') - ui.separator() - ui.markdown('**Driver settings**').style('color: #6E93D6') - with ui.row(): - ui.number('linear_speed_on_row', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=m/s').classes('w-24') - .bind_value(self.system.weeding, 'linear_speed_on_row') - .tooltip('Set the linear speed on row for the weeding automation') - ui.number('linear_speed_between_rows', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=m/s').classes('w-24') - .bind_value(self.system.weeding, 'linear_speed_between_rows') - .tooltip('Set the linear speed between rows for the weeding automation') - ui.number('angular_speed_on_row', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=°/s').classes('w-24') - .bind_value(self.system.weeding, 'angular_speed_on_row') - .tooltip('Set the angular speed on row for the weeding automation') - ui.number('angular_speed_between_rows', value=0.5, step=0.1, min=0.1, format='%.1f') - .props('dense outlined suffix=°/s').classes('w-24') - .bind_value(self.system.weeding, 'angular_speed_between_rows') - .tooltip('Set the angular speed between rows for the weeding automation') + ui.number('Min. turning radius', format='%.2f', + value=0.5, step=0.05, min=0.05, max=2.0) \ + .props('dense outlined suffix=m').classes('w-30') \ + .bind_value(self.system.weeding, 'minimum_turning_radius') \ + .tooltip('Set the turning radius for the weeding automation') + ui.number('turn_offset', format='%.2f', value=0.4, step=0.05, min=0.05, max=2.0) \ + .props('dense outlined suffix=m').classes('w-30') \ + .bind_value(self.system.weeding, 'turn_offset') \ + .tooltip('Set the turning offset for the weeding automation') + ui.separator() + ui.markdown('Detector settings').style('color: #6E93D6') + with ui.row(): + ui.number('Min. weed confidence', format='%.2f', value=0.8, step=0.05, min=0.0, max=1.0) \ + .props('dense outlined') \ + .classes('w-24') \ + .bind_value(self.system.plant_locator, 'minimum_weed_confidence') \ + .tooltip('Set the minimum weed confidence for the weeding automation') + ui.number('Min. crop confidence', format='%.2f', value=0.4, step=0.05, min=0.0, max=1.0) \ + .props('dense outlined') \ + .classes('w-24') \ + .bind_value(self.system.plant_locator, 'minimum_crop_confidence') \ + .tooltip('Set the minimum crop confidence for the weeding automation') + ui.separator() + ui.markdown('Tool settings').style('color: #6E93D6') + with ui.row(): + if self.system.field_friend.tool == 'tornado': + ui.number('Tornado angle', format='%.0f', value=180, step=1, min=1, max=180) \ + .props('dense outlined suffix=°') \ + .classes('w-24') \ + .bind_value(self.system.weeding, 'tornado_angle') \ + .tooltip('Set the angle for the tornado drill') + elif self.system.field_friend.tool in ['weed_screw', 'dual_mechanism']: + ui.number('Drill depth', value=0.02, format='%.2f', step=0.01, + min=self.system.field_friend.z_axis.max_position, max=self.system.field_friend.z_axis.min_position*-1) \ + .props('dense outlined suffix=°') \ + .classes('w-24') \ + .bind_value(self.system.weeding, 'weed_screw_depth') \ + .tooltip('Set the drill depth for the weeding automation') + ui.number('Crop safety distance', value=0.01, step=0.01, min=0.0, max=0.05, format='%.2f') \ + .props('dense outlined suffix=m') \ + .classes('w-24') \ + .bind_value(self.system.weeding, 'crop_safety_distance') \ + .tooltip('Set the crop safety distance for the weeding automation') + ui.separator() + ui.markdown('Workflow settings').style('color: #6E93D6') + with ui.row(): + if self.system.field_friend.tool == 'tornado': + ui.checkbox('Drill 2x with open torando', value=False, on_change=system.weeding.invalidate) \ + .bind_value(self.system.weeding, 'drill_with_open_tornado') \ + .tooltip('Set the weeding automation to drill a second time with open tornado') + ui.checkbox('Drill between crops', value=False) \ + .bind_value(self.system.weeding, 'drill_between_crops') \ + .tooltip('Set the weeding automation to drill between crops') + elif self.system.field_friend.tool == 'dual_mechanism': + ui.checkbox('Drilling', value=False).bind_value(self.system.weeding, 'with_drilling') \ + .tooltip('Set the weeding automation to with drill') + ui.checkbox('Chopping', value=False) \ + .bind_value(self.system.weeding, 'with_chopping') \ + .tooltip('Set the weeding automation to with chop') + ui.checkbox('Chop if no crops', value=False) \ + .bind_value(self.system.weeding, 'chop_if_no_crops') \ + .tooltip('Set the weeding automation to chop also if no crops seen') + elif self.system.field_friend.tool in ['weed_screw', 'dual_mechanism']: + ui.number('Drill depth', value=0.02, format='%.2f', step=0.01, + min=self.system.field_friend.z_axis.max_position, max=self.system.field_friend.z_axis.min_position*-1) \ + .props('dense outlined suffix=°').classes('w-24') \ + .bind_value(self.system.weeding, 'weed_screw_depth') \ + .tooltip('Set the drill depth for the weeding automation') + ui.number('Crop safety distance', value=0.01, step=0.01, min=0.0, max=0.05, format='%.2f') \ + .props('dense outlined suffix=m').classes('w-24') \ + .bind_value(self.system.weeding, 'crop_safety_distance') \ + .tooltip('Set the crop safety distance for the weeding automation') + ui.checkbox('Only monitoring') \ + .bind_value(self.system.weeding, 'only_monitoring') \ + .tooltip('Set the weeding automation to only monitor the field') + ui.separator() + ui.markdown('**Driver settings**').style('color: #6E93D6') + with ui.row(): + ui.number('linear_speed_on_row', value=0.5, step=0.1, min=0.1, format='%.1f') \ + .props('dense outlined suffix=m/s') \ + .classes('w-24') \ + .bind_value(self.system.weeding, 'linear_speed_on_row') \ + .tooltip('Set the linear speed on row for the weeding automation') + ui.number('linear_speed_between_rows', value=0.5, step=0.1, min=0.1, format='%.1f') \ + .props('dense outlined suffix=m/s') \ + .classes('w-24') \ + .bind_value(self.system.weeding, 'linear_speed_between_rows') \ + .tooltip('Set the linear speed between rows for the weeding automation') + ui.number('angular_speed_on_row', value=0.5, step=0.1, min=0.1, format='%.1f') \ + .props('dense outlined suffix=°/s') \ + .classes('w-24') \ + .bind_value(self.system.weeding, 'angular_speed_on_row') \ + .tooltip('Set the angular speed on row for the weeding automation') + ui.number('angular_speed_between_rows', value=0.5, step=0.1, min=0.1, format='%.1f') \ + .props('dense outlined suffix=°/s') \ + .classes('w-24') \ + .bind_value(self.system.weeding, 'angular_speed_between_rows') \ + .tooltip('Set the angular speed between rows for the weeding automation') - with ui.column().bind_visibility_from(self.automations_toggle, 'value', value='monitoring'): - with ui.column(): - self.with_field_planning_monitor=ui.checkbox('Use field planning', value=True) - .bind_value(self.system.monitoring, 'use_field_planning').tooltip('Set the monitoring automation to use the field planning with GNSS') - self.with_field_planning_monitor=ui.checkbox('Use field planning', value=True) - .bind_value(self.system.monitoring, 'use_field_planning').tooltip('Set the monitoring automation to use the field planning with GNSS') + with ui.column().bind_visibility_from(self.automations_toggle, 'value', value='monitoring'): + with ui.column(): + self.with_field_planning_monitor = ui.checkbox('Use field planning', value=True) \ + .bind_value(self.system.monitoring, 'use_field_planning') \ + .tooltip('Set the monitoring automation to use the field planning with GNSS') + self.with_field_planning_monitor = ui.checkbox('Use field planning', value=True) \ + .bind_value(self.system.monitoring, 'use_field_planning') \ + .tooltip('Set the monitoring automation to use the field planning with GNSS') - with ui.row().bind_visibility_from(self.with_field_planning_monitor, 'value', value=True): - self.show_start_row() - self.show_end_row() - ui.number('Min. turning radius', format='%.2f', - value=0.5, step=0.05, min=0.05, max=2.0) - .props('dense outlined suffix=m').classes('w-30') - .bind_value(self.system.monitoring, 'minimum_turning_radius') - .tooltip('Set the turning radius for the monitoring automation') - ui.number('Min. turning radius', format='%.2f', - value=0.5, step=0.05, min=0.05, max=2.0) - .props('dense outlined suffix=m').classes('w-30') - .bind_value(self.system.monitoring, 'minimum_turning_radius') - .tooltip('Set the turning radius for the monitoring automation') + with ui.row().bind_visibility_from(self.with_field_planning_monitor, 'value', value=True): + self.show_start_row() + self.show_end_row() + ui.number('Min. turning radius', format='%.2f', + value=0.5, step=0.05, min=0.05, max=2.0) \ + .props('dense outlined suffix=m').classes('w-30') \ + .bind_value(self.system.monitoring, 'minimum_turning_radius') \ + .tooltip('Set the turning radius for the monitoring automation') + ui.number('Min. turning radius', format='%.2f', + value=0.5, step=0.05, min=0.05, max=2.0) \ + .props('dense outlined suffix=m').classes('w-30') \ + .bind_value(self.system.monitoring, 'minimum_turning_radius') \ + .tooltip('Set the turning radius for the monitoring automation') - with ui.column().bind_visibility_from(self.automations_toggle, 'value', value='collecting (demo)'): - with ui.row(): - ui.number( - 'Drill angle', format='%.0f', value=100, step=1, min=1, max=180) - .props('dense outlined suffix=°').classes('w-24') - .bind_value(self.system.coin_collecting, 'angle') - .tooltip('Set the drill depth for the weeding automation') - ui.checkbox('with drilling', value=True) - .bind_value(self.system.coin_collecting, 'with_drilling') - 'Drill angle', format='%.0f', value=100, step=1, min=1, max=180) \ + with ui.column().bind_visibility_from(self.automations_toggle, 'value', value='collecting (demo)'): + with ui.row(): + ui.number('Drill angle', format='%.0f', value=100, step=1, min=1, max=180) \ .props('dense outlined suffix=°').classes('w-24') \ .bind_value(self.system.coin_collecting, 'angle') \ .tooltip('Set the drill depth for the weeding automation') - ui.checkbox('with drilling', value=True) \ - .bind_value(self.system.coin_collecting, 'with_drilling') + ui.checkbox('with drilling', value=True) \ + .bind_value(self.system.coin_collecting, 'with_drilling') ui.space() with ui.row().style("margin: 1rem; width: calc(100% - 2rem);"): with ui.column(): @@ -325,16 +252,10 @@ def show_field_selection() -> None: ui.button('emergency reset', on_click=lambda: system.field_friend.estop.set_soft_estop(False)) \ .props('color=red-700 outline').classes('py-3 px-6 text-lg') \ .bind_visibility_from(system.field_friend.estop, 'is_soft_estop_active', value=True) - ui.button('emergency stop', on_click=lambda: system.field_friend.estop.set_soft_estop(True)).props('color=red') \ - .classes('py-3 px-6 text-lg').bind_visibility_from(system.field_friend.estop, 'is_soft_estop_active', value=False) - ui.button('emergency reset', on_click=lambda: system.field_friend.estop.set_soft_estop(False)) \ - .props('color=red-700 outline').classes('py-3 px-6 text-lg') \ - .bind_visibility_from(system.field_friend.estop, 'is_soft_estop_active', value=True) ui.space() with ui.row(): automation_controls(self.system, can_start=self.can_start) with ui.dialog() as self.dialog, ui.card(): - self.dialog_label = ui.label('Do you want to continue the canceled automation').classes('text-lg') self.dialog_label = ui.label('Do you want to continue the canceled automation').classes('text-lg') with ui.row(): ui.button('Yes', on_click=lambda: self.dialog.submit('Yes')) @@ -346,26 +267,18 @@ def show_start_row(self) -> None: if self.field_provider.active_field is not None: ui.select({row.id: row.name for row in self.field_provider.active_field.rows}, label='Start row') \ .bind_value(self.system.weeding, 'start_row_id').classes('w-24').tooltip('Select the row to start on') - ui.select({row.id: row.name for row in self.field_provider.active_field.rows}, label='Start row') \ - .bind_value(self.system.weeding, 'start_row_id').classes('w-24').tooltip('Select the row to start on') else: ui.select([None], label='Start row')\ .bind_value(self.system.weeding, 'start_row').classes('w-24').tooltip('Select the row to start on') - ui.select([None], label='Start row')\ - .bind_value(self.system.weeding, 'start_row').classes('w-24').tooltip('Select the row to start on') @ui.refreshable def show_end_row(self) -> None: if self.field_provider.active_field is not None: ui.select({row.id: row.name for row in self.field_provider.active_field.rows}, label='End row') \ .bind_value(self.system.weeding, 'end_row_id').classes('w-24').tooltip('Select the row to end on') - ui.select({row.id: row.name for row in self.field_provider.active_field.rows}, label='End row') \ - .bind_value(self.system.weeding, 'end_row_id').classes('w-24').tooltip('Select the row to end on') else: ui.select([None], label='End row') \ .bind_value(self.system.weeding, 'end_row').classes('w-24').tooltip('Select the row to end on') - ui.select([None], label='End row') \ - .bind_value(self.system.weeding, 'end_row').classes('w-24').tooltip('Select the row to end on') def set_field(self) -> None: for field in self.system.field_provider.fields: