LCOV - code coverage report
Current view: top level - SITL - SIM_PS_LightWare_SF45B.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 42 43 97.7 %
Date: 2026-09-09 11:02:08 Functions: 25 25 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             :   Simulator for the LightWare S45B proximity sensor
      17             : 
      18             : ./Tools/autotest/sim_vehicle.py --gdb --debug -v ArduCopter -A --serial5=sim:sf45b --speedup=1 -l 51.8752066,14.6487840,54.15,0
      19             : 
      20             : param set SERIAL5_PROTOCOL 11  # proximity
      21             : param set PRX1_TYPE 8  # s45b
      22             : reboot
      23             : 
      24             : arm throttle
      25             : rc 3 1600
      26             : 
      27             : # for avoidance:
      28             : param set DISARM_DELAY 0
      29             : param set AVOID_ENABLE 2 # use proximity sensor
      30             : param set AVOID_MARGIN 2.00  # 2m
      31             : param set AVOID_BEHAVE 0 # slide
      32             : reboot
      33             : mode loiter
      34             : script /tmp/post-locations.scr
      35             : arm throttle
      36             : rc 3 1600
      37             : rc 3 1500
      38             : rc 2 1450
      39             : 
      40             : */
      41             : 
      42             : #pragma once
      43             : 
      44             : #include "SIM_config.h"
      45             : 
      46             : #if AP_SIM_PS_LIGHTWARE_SF45B_ENABLED
      47             : 
      48             : #include "SIM_PS_LightWare.h"
      49             : 
      50             : #include <AP_Math/crc.h>
      51             : #include <AP_InternalError/AP_InternalError.h>
      52             : 
      53             : namespace SITL {
      54             : 
      55             : class PS_LightWare_SF45B : public PS_LightWare {
      56             : public:
      57             : 
      58             :     using PS_LightWare::PS_LightWare;
      59             : 
      60             :     uint32_t packet_for_location(const Location &location,
      61             :                                  uint8_t *data,
      62             :                                  uint8_t buflen) override;
      63             : 
      64             :     void update(const Location &location) override;
      65             : 
      66             : private:
      67             : 
      68             :     template <typename T>
      69             :     class PACKED PackedMessage {
      70             :     public:
      71        6264 :         PackedMessage(T _msg, uint16_t _flags) :
      72        6264 :             flags(_flags),
      73        6264 :             msg(_msg)
      74             :         {
      75        6264 :             flags |= (sizeof(T)) << 6;
      76        6264 :         }
      77             :         uint8_t preamble { PREAMBLE };
      78             :         uint16_t flags;
      79             :         T msg;
      80             :         uint16_t checksum;
      81             : 
      82        6264 :         uint16_t calculate_checksum(uint16_t len) const WARN_IF_UNUSED {
      83        6264 :             uint16_t ret = 0;
      84       56352 :             for (uint8_t i=0; i<len; i++) {
      85       50088 :                 ret = crc_xmodem_update(ret, ((const char*)this)[i]);
      86             :             }
      87        6264 :             return ret;
      88             :         }
      89        6264 :         uint16_t calculate_checksum() const WARN_IF_UNUSED {
      90        6264 :             return calculate_checksum(3+sizeof(T));
      91             :         }
      92             : 
      93        6264 :         void update_checksum() {
      94        6264 :             checksum = calculate_checksum();
      95        6264 :         }
      96             :     };
      97             : 
      98             :     class PACKED MsgStream {
      99             :     public:
     100           8 :         MsgStream(uint32_t _stream) :
     101           8 :             stream(_stream)
     102           8 :         { }
     103             :         uint8_t msgid { (uint8_t)MessageID::STREAM };
     104             :         uint32_t stream;
     105             :     };
     106             : 
     107             :     class PACKED DistanceOutput {
     108             :     public:
     109           8 :         DistanceOutput(uint32_t _desired_fields) :
     110           8 :             desired_fields(_desired_fields)
     111           8 :         { }
     112             :         uint8_t msgid { (uint8_t)MessageID::DISTANCE_OUTPUT };
     113             :         uint32_t desired_fields;
     114             :     };
     115             : 
     116             :     class PACKED UpdateRate {
     117             :     public:
     118           8 :         UpdateRate(uint8_t _rate) :
     119           8 :             rate(_rate)
     120           8 :         { }
     121             :         uint8_t msgid { (uint8_t)MessageID::UPDATE_RATE };
     122             :         uint8_t rate;
     123             :     };
     124             : 
     125             :     class PACKED DistanceDataCM {
     126             :     public:
     127        6240 :         DistanceDataCM(uint16_t _distance_cm, uint16_t _angle_cd) :
     128        6240 :             distance_cm(_distance_cm),
     129        6240 :             angle_cd(_angle_cd)
     130        6240 :         { }
     131             :         uint8_t msgid { (uint8_t)MessageID::DISTANCE_DATA_CM };
     132             :         uint16_t distance_cm;
     133             :         uint16_t angle_cd;
     134             :     };
     135             : 
     136             :     // message ids
     137             :     enum class MessageID : uint8_t {
     138             :         // PRODUCT_NAME = 0,
     139             :         // HARDWARE_VERSION = 1,
     140             :         // FIRMWARE_VERSION = 2,
     141             :         // SERIAL_NUMBER = 3,
     142             :         // TEXT_MESSAGE = 7,
     143             :         // USER_DATA = 9,
     144             :         // TOKEN = 10,
     145             :         // SAVE_PARAMETERS = 12,
     146             :         // RESET = 14,
     147             :         // STAGE_FIRMWARE = 16,
     148             :         // COMMIT_FIRMWARE = 17,
     149             :         DISTANCE_OUTPUT = 27,
     150             :         STREAM = 30,
     151             :         DISTANCE_DATA_CM = 44,
     152             :         // DISTANCE_DATA_MM = 45,
     153             :         // LASER_FIRING = 50,
     154             :         // TEMPERATURE = 57,
     155             :         UPDATE_RATE = 66,
     156             :         // NOISE = 74,
     157             :         // ZERO_OFFSET = 75,
     158             :         // LOST_SIGNAL_COUNTER = 76,
     159             :         // BAUD_RATE = 79,
     160             :         // I2C_ADDRESS = 80,
     161             :         // STEPPER_STATUS = 93,
     162             :         // SCAN_ON_STARTUP = 94,
     163             :         // SCAN_ENABLE = 96,
     164             :         // SCAN_POSITION = 97,
     165             :         // SCAN_LOW_ANGLE = 98,
     166             :         // SCAN_HIGH_ANGLE = 99
     167             :     };
     168             : 
     169             : 
     170             :     /*
     171             :      *  Input Handling
     172             :      */
     173             :     void update_input();
     174             : 
     175             :     // make the message in the buffer a read message and return to sender
     176             :     void boomerang_buffer_message(uint8_t len);
     177             : 
     178             :     // handle a complete checksummed message
     179             :     void handle_message();
     180             : 
     181             :     void send(const char *data, uint32_t len);
     182             : 
     183             :     union u {
     184           1 :         u() {}
     185             :         char buffer[256]; // from-autopilot
     186             :         PackedMessage<MsgStream> packed_msgstream;
     187             :         PackedMessage<DistanceOutput> packed_distance_output;
     188             :         PackedMessage<UpdateRate> packed_update_rate;
     189             :     } _msg;
     190             :     uint8_t _buflen;
     191             : 
     192          24 :     static uint16_t checksum_bytes(const char *buffer, uint8_t len) {
     193          24 :         uint16_t crc = 0;
     194         192 :         for (uint8_t i=0; i<len; i++) {
     195         168 :             crc = crc_xmodem_update(crc, buffer[i]);
     196             :         }
     197          24 :         return crc;
     198             :     }
     199             : 
     200          24 :     uint16_t msg_checksum() const {
     201             :         // 4 is 1 preamble, 2 flags, 1 msgid
     202          24 :         return checksum_bytes(_msg.buffer, payload_length() + 4);
     203             :     }
     204             : 
     205          72 :     uint8_t payload_length() const {
     206          72 :         if (_buflen < 3) {
     207           0 :             INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
     208             :         }
     209          72 :         return (_msg.packed_msgstream.flags >> 6) - 1;
     210             :     }
     211             : 
     212             :     static const uint8_t PREAMBLE = 0xAA;
     213             : 
     214             :     void move_preamble_in_buffer(uint8_t search_start_pos=0);
     215             : 
     216             :     enum class InputState {
     217             :         WANT_PREAMBLE = 45,
     218             :         WANT_FLAGS = 46,
     219             :         WANT_PAYLOAD = 47,
     220             :         WANT_CRC = 48,
     221             :     };
     222             :     InputState _inputstate = InputState::WANT_PREAMBLE;
     223          96 :     void set_inputstate(InputState newstate) {
     224             :         // ::fprintf(stderr, "Moving from inputstate (%u) to (%u)\n", (uint8_t)_inputstate, (uint8_t)newstate);
     225          96 :         _inputstate = newstate;
     226          96 :     }
     227             : 
     228             :     /*
     229             :      * SETTINGS
     230             :      */
     231             :     uint32_t stream;
     232             :     uint32_t desired_fields;
     233             :     uint8_t update_rate;
     234             : 
     235             :     /*
     236             :      * OUTPUT HANDLING
     237             :      */
     238             : 
     239             :     struct {
     240             :         bool stream;
     241             :         bool desired_fields;
     242             :         bool update_rate;
     243             :     } send_response;
     244             : 
     245             :     enum class State {
     246             :         SCANNING = 21,
     247             :     };
     248             :     State _state = State::SCANNING;
     249             :     void set_state(State newstate) {
     250             :         // ::fprintf(stderr, "Moving from state (%u) to (%u)\n", (uint8_t)_state, (uint8_t)newstate);
     251             :         _state = newstate;
     252             :     }
     253             : 
     254             :     void update_output(const Location &location);
     255             :     void update_output_responses();
     256             :     void update_output_scan(const Location &location);
     257             : 
     258             :     uint32_t last_scan_output_time_ms;
     259             : 
     260             :     float last_degrees_bf;  // previous iteration's lidar angle
     261             :     float last_dir = 1;     // previous iterations movement direction.  +1 CW, -1 for CCW
     262             : 
     263             : };
     264             : 
     265             : };
     266             : 
     267             : #endif  // AP_SIM_PS_LIGHTWARE_SF45B_ENABLED

Generated by: LCOV version 1.14