diff --git a/.github/workflows/build-image.yaml b/.github/workflows/build-image.yaml index 22316d72..6a525b35 100644 --- a/.github/workflows/build-image.yaml +++ b/.github/workflows/build-image.yaml @@ -48,9 +48,7 @@ jobs: # Get the repository's code - name: Checkout uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - - uses: pre-commit/action@v3.0.1 - name: Docker meta diff --git a/config/mower_config.schema.json b/config/mower_config.schema.json index b26871ff..46995b71 100644 --- a/config/mower_config.schema.json +++ b/config/mower_config.schema.json @@ -401,6 +401,32 @@ "description": "Set to true to record your session for debugging. Recordings will be stored in $HOME. Only enable for testing, otherwise your SD card will get full soon.", "x-environment-variable": "OM_ENABLE_RECORDING_ALL" }, + "OM_RAIN_MODE": { + "type": "string", + "enum": [ + "Ignore", + "Dock", + "Dock Until Dry", + "Pause Automatic Mode" + ], + "default": "Ignore", + "title": "Rain Mode", + "description": "Behaviour when rain detected", + "x-environment-variable": "OM_RAIN_MODE", + "x-remap-values": { + "Ignore": 0, + "Dock": 1, + "Dock Until Dry": 2, + "Pause Automatic Mowing": 3 + } + }, + "OM_RAIN_DELAY_MINUTES": { + "type": "number", + "default": 30, + "title": "Rain delay minutes", + "description": "How long to wait after rain to resume mowing when mode is \"Dock Until Dry\"", + "x-environment-variable": "OM_RAIN_DELAY_MINUTES" + }, "advanced": { "type": "boolean", "description": "Show advanced Mower Logic settings" diff --git a/config/mower_config.sh.example b/config/mower_config.sh.example index f1c0a767..7b085c8b 100644 --- a/config/mower_config.sh.example +++ b/config/mower_config.sh.example @@ -191,6 +191,17 @@ export OM_AUTOMATIC_MODE=0 export OM_OUTLINE_OFFSET=0.05 +# Rain mode +# 0 - Ignore +# 1 - Dock +# 2 - Dock Until Dry +# 3 - Pause Automatic Mode +export OM_RAIN_MODE=0 + +# Rain delay +# How long to wait after rain to resume mowing when mode is "Dock Until Dry" +export OM_RAIN_DELAY_MINUTES=30 + ################################ ## External MQTT Broker ## ################################ diff --git a/src/mower_logic/cfg/MowerLogic.cfg b/src/mower_logic/cfg/MowerLogic.cfg index 45024f79..e9e5cad8 100755 --- a/src/mower_logic/cfg/MowerLogic.cfg +++ b/src/mower_logic/cfg/MowerLogic.cfg @@ -33,5 +33,8 @@ gen.add("add_fake_obstacle", bool_t, 0, "True to add a fake obstacle to hopefull gen.add("ignore_gps_errors", bool_t, 0, "True to ignore gps errors. USE ONLY FOR SIMULATION!", False) gen.add("max_first_point_attempts", int_t, 0, "Maximum attempts to reach the first point of the mow path before trimming", 3, 1, 10) gen.add("max_first_point_trim_attempts", int_t, 0, "After we start to trim the path beginning this often", 3, 1, 10) +gen.add("rain_mode", int_t, 0, "0 - Ignore, 1 - Dock, 2 - Dock until dry, 3 - Pause Automatic Mode", 0, 0, 3) +gen.add("rain_delay_minutes", int_t, 0, "Time to wait after rain to resume mowing", 1, 30, 1440) +gen.add("rain_check_seconds", int_t, 0, "Rain must be detected continuosly for this time to trigger rain_mode", 0, 20, 300) exit(gen.generate("mower_logic", "mower_logic", "MowerLogic")) diff --git a/src/mower_logic/src/mower_logic/behaviors/IdleBehavior.cpp b/src/mower_logic/src/mower_logic/behaviors/IdleBehavior.cpp index 49ee6b16..15ce2c87 100644 --- a/src/mower_logic/src/mower_logic/behaviors/IdleBehavior.cpp +++ b/src/mower_logic/src/mower_logic/behaviors/IdleBehavior.cpp @@ -25,6 +25,7 @@ extern void setEmergencyMode(bool emergency); extern void setGPS(bool enabled); extern void setRobotPose(geometry_msgs::Pose &pose); extern void registerActions(std::string prefix, const std::vector &actions); +extern ros::Time rain_resume; extern ros::ServiceClient dockingPointClient; extern mower_msgs::Status getStatus(); @@ -74,9 +75,13 @@ Behavior *IdleBehavior::execute() { const bool active_semiautomatic_task = last_config.automatic_mode == eAutoMode::SEMIAUTO && shared_state->active_semiautomatic_task && !shared_state->semiautomatic_task_paused; + const bool rain_delay = last_config.rain_mode == 2 && ros::Time::now() < rain_resume; + if (rain_delay) { + ROS_INFO_STREAM_THROTTLE(300, "Rain delay: " << int((rain_resume - ros::Time::now()).toSec() / 60) << " minutes"); + } const bool mower_ready = last_status.v_battery > last_config.battery_full_voltage && last_status.mow_esc_status.temperature_motor < last_config.motor_cold_temperature && - !last_config.manual_pause_mowing; + !last_config.manual_pause_mowing && !rain_delay; if (manual_start_mowing || ((automatic_mode || active_semiautomatic_task) && mower_ready)) { // set the robot's position to the dock if we're actually docked diff --git a/src/mower_logic/src/mower_logic/mower_logic.cpp b/src/mower_logic/src/mower_logic/mower_logic.cpp index 6701eb86..c3bf169d 100644 --- a/src/mower_logic/src/mower_logic/mower_logic.cpp +++ b/src/mower_logic/src/mower_logic/mower_logic.cpp @@ -90,6 +90,10 @@ std::vector rootActions; ros::Time last_v_battery_check; double max_v_battery_seen = 0.0; +ros::Time last_rain_check; +bool rain_detected = true; +ros::Time rain_resume; + /** * Some thread safe methods to get a copy of the logic state */ @@ -534,6 +538,29 @@ void checkSafety(const ros::TimerEvent &timer_event) { dockingNeeded = true; } + // Rain detected is initialized to true and flips to false if rain is not detected + // continuously for rain_check_seconds. This is to avoid false positives due to noise + rain_detected = rain_detected && last_status.rain_detected; + if (last_config.rain_check_seconds == 0 || + ros::Time::now() - last_rain_check > ros::Duration(last_config.rain_check_seconds)) { + if (rain_detected) { + // Reset rain resume time + rain_resume = + ros::Time::now() + ros::Duration(last_config.rain_check_seconds + last_config.rain_delay_minutes * 60); + } + if (!dockingNeeded && rain_detected && last_config.rain_mode) { + dockingReason << "Rain detected"; + dockingNeeded = true; + if (last_config.rain_mode == 3) { + auto new_config = getConfig(); + new_config.manual_pause_mowing = true; + setConfig(new_config); + } + } + last_rain_check = ros::Time::now(); + rain_detected = true; + } + if (dockingNeeded && currentBehavior != &DockingBehavior::INSTANCE && currentBehavior != &UndockingBehavior::RETRY_INSTANCE && currentBehavior != &IdleBehavior::INSTANCE && currentBehavior != &IdleBehavior::DOCKED_INSTANCE) { @@ -815,7 +842,7 @@ int main(int argc, char **argv) { ROS_INFO("om_mower_logic: Got all servers, we can mow"); - last_v_battery_check = ros::Time::now(); + rain_resume = last_rain_check = last_v_battery_check = ros::Time::now(); ros::Timer safety_timer = n->createTimer(ros::Duration(0.5), checkSafety); ros::Timer ui_timer = n->createTimer(ros::Duration(1.0), updateUI); diff --git a/src/mower_simulation/cfg/MowerSimulation.cfg b/src/mower_simulation/cfg/MowerSimulation.cfg index 8ed1f0d5..21389477 100755 --- a/src/mower_simulation/cfg/MowerSimulation.cfg +++ b/src/mower_simulation/cfg/MowerSimulation.cfg @@ -11,6 +11,7 @@ gen.add("mower_error", bool_t, 0, "mower error", False) gen.add("mower_running", bool_t, 0, "mower running", False) gen.add("wheels_stalled", bool_t, 0, "wheels_stalled", False) gen.add("emergency_stop", bool_t, 0, "emergency_stop", False) +gen.add("rain", bool_t, 0, "rain", False) exit(gen.generate("mower_simulation", "mower_simulation", "MowerSimulation")) diff --git a/src/mower_simulation/src/mower_simulation.cpp b/src/mower_simulation/src/mower_simulation.cpp index 59deb46c..864ce151 100644 --- a/src/mower_simulation/src/mower_simulation.cpp +++ b/src/mower_simulation/src/mower_simulation.cpp @@ -103,6 +103,7 @@ void publishStatus(const ros::TimerEvent &timer_event) { fake_mow_status.stamp = ros::Time::now(); fake_mow_status.mow_enabled = config.mower_running; + fake_mow_status.rain_detected = config.rain; fake_mow_status.mow_esc_status.temperature_motor = config.temperature_mower; fake_mow_status.mow_esc_status.status = mower_msgs::ESCStatus::ESC_STATUS_OK; if (config.mower_error) { diff --git a/src/open_mower/launch/open_mower.launch b/src/open_mower/launch/open_mower.launch index 2a65743c..92ca188a 100644 --- a/src/open_mower/launch/open_mower.launch +++ b/src/open_mower/launch/open_mower.launch @@ -37,6 +37,9 @@ + + + diff --git a/src/open_mower/launch/sim_mower_logic.launch b/src/open_mower/launch/sim_mower_logic.launch index a35b92ad..c0d12428 100644 --- a/src/open_mower/launch/sim_mower_logic.launch +++ b/src/open_mower/launch/sim_mower_logic.launch @@ -13,7 +13,7 @@ - + @@ -35,6 +35,9 @@ + + +