LCOV - code coverage report
Current view: top level - SITL - SIM_ICEngine.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 51 58 87.9 %
Date: 2026-09-09 11:02:08 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : /*
      16             :   simple internal combustion engine simulator class
      17             : */
      18             : 
      19             : #include "SIM_ICEngine.h"
      20             : #include <stdio.h>
      21             : 
      22             : using namespace SITL;
      23             : 
      24             : #include <GCS_MAVLink/GCS.h>
      25             : 
      26             : /*
      27             :   update engine state, returning power output from 0 to 1
      28             :  */
      29     1398922 : float ICEngine::update(const struct sitl_input &input)
      30             : {
      31     1398922 :     bool have_ignition = ignition_servo>=0;
      32     1398922 :     bool have_choke = choke_servo>=0;
      33     1398922 :     bool have_starter = starter_servo>=0;
      34     1398922 :     float throttle_demand = (input.servos[throttle_servo]-1000) * 0.001f;
      35     1398922 :     if (throttle_reversed) {
      36     1398922 :         throttle_demand = 1 - throttle_demand;
      37             :     }
      38             : 
      39     1398922 :     state.ignition = have_ignition?input.servos[ignition_servo]>1700:true;
      40     1398922 :     state.choke = have_choke?input.servos[choke_servo]>1700:false;
      41     1398922 :     state.starter = have_starter?input.servos[starter_servo]>1700:false;
      42             : 
      43     1398922 :     uint64_t now = AP_HAL::micros64();
      44     1398922 :     float dt = (now - last_update_us) * 1.0e-6f;
      45     1398922 :     float max_change = slew_rate * 0.01f * dt;
      46             :     
      47     1398922 :     if (!have_starter) {
      48             :         // always on
      49           0 :         last_output = throttle_demand;
      50           0 :         return last_output;
      51             :     }
      52             : 
      53     1398922 :     if (state.value != last_state.value) {
      54          62 :         GCS_SEND_TEXT(MAV_SEVERITY_INFO, "SIM_ICEngine: choke:%u starter:%u ignition:%u",
      55             :                       (unsigned)state.choke,
      56             :                       (unsigned)state.starter,
      57             :                       (unsigned)state.ignition);
      58             :     }
      59             : 
      60     1398922 :     if (have_ignition && !state.ignition) {
      61             :         // engine is off
      62      286167 :         if (!state.starter) {
      63      286167 :             goto engine_off;
      64             :         }
      65             :         // give 10% when on starter alone without ignition
      66           0 :         last_update_us = now;
      67           0 :         throttle_demand = 0.1;
      68           0 :         goto output;
      69             :     }
      70     1112755 :     if (have_choke && state.choke && now - start_time_us > 1000*1000UL) {
      71             :         // engine is choked, only run for 1s
      72           0 :         goto engine_off;
      73             :     }
      74     1112755 :     if (last_output <= 0 && !state.starter) {
      75             :         // not started
      76       31809 :         goto engine_off;
      77             :     }
      78     1080946 :     if (start_time_us == 0 && state.starter) {
      79          11 :         if (throttle_demand > 0.2) {
      80           0 :             GCS_SEND_TEXT(MAV_SEVERITY_INFO, "SIM_ICEngine: too much throttle to start: %.2f", throttle_demand);
      81             :         } else {
      82             :             // start the motor
      83          11 :             if (start_time_us == 0) {
      84          11 :                 GCS_SEND_TEXT(MAV_SEVERITY_INFO, "SIM_ICEngine: Engine started");
      85             :             }
      86          11 :             start_time_us = now;
      87             :         }
      88             :     }
      89     1080946 :     if (start_time_us != 0 && state.starter) {
      90       72981 :         uint32_t starter_time_us = (now - start_time_us);
      91       72981 :         if (starter_time_us > 3000*1000UL && !overheat) {
      92          14 :             overheat = true;
      93          14 :             GCS_SEND_TEXT(MAV_SEVERITY_INFO, "SIM_ICEngine: Starter overheat");
      94             :         }
      95       72981 :     } else {
      96     1007965 :         overheat = false;
      97             :     }
      98             : 
      99     1080946 : output:
     100     1080946 :     if (start_time_us != 0 && throttle_demand < 0.01) {
     101             :         // even idling it gives some thrust
     102      379511 :         throttle_demand = 0.01;
     103             :     }
     104             : 
     105     1080946 :     last_output = constrain_float(throttle_demand, last_output-max_change, last_output+max_change);
     106     1080946 :     last_output = constrain_float(last_output, 0, 1);
     107             :     
     108     1080946 :     last_update_us = now;
     109     1080946 :     last_state = state;
     110     1080946 :     return last_output;
     111             : 
     112      317976 : engine_off:
     113      317976 :     if (start_time_us != 0) {
     114          11 :         GCS_SEND_TEXT(MAV_SEVERITY_INFO, "SIM_ICEngine: Engine stopped");
     115             :     }
     116      317976 :     last_update_us = AP_HAL::micros64();
     117      317976 :     start_time_us = 0;
     118      317976 :     last_output = 0;
     119      317976 :     last_state = state;
     120      317976 :     start_time_us = 0;
     121      317976 :     return 0;
     122             : }

Generated by: LCOV version 1.14