LCOV - code coverage report
Current view: top level - SITL - SIM_Vicon.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 135 182 74.2 %
Date: 2026-09-09 11:02:08 Functions: 5 5 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 vicon simulator class
      17             : */
      18             : 
      19             : #include "SIM_config.h"
      20             : 
      21             : #if AP_SIM_VICON_ENABLED
      22             : 
      23             : #include "SIM_Vicon.h"
      24             : #include <stdio.h>
      25             : #include <unistd.h>
      26             : #include <fcntl.h>
      27             : 
      28             : extern const AP_HAL::HAL& hal;
      29             : 
      30             : using namespace SITL;
      31             : 
      32             : const AP_Param::GroupInfo SIM::ViconParms::var_info[] = {
      33             :     // @Param: POS_X
      34             :     // @DisplayName: SITL vicon position on vehicle in Forward direction
      35             :     // @Description: SITL vicon position on vehicle in Forward direction
      36             :     // @Units: m
      37             :     // @Range: 0 10
      38             :     // @User: Advanced
      39             : 
      40             :     // @Param: POS_Y
      41             :     // @DisplayName: SITL vicon position on vehicle in Right direction
      42             :     // @Description: SITL vicon position on vehicle in Right direction
      43             :     // @Units: m
      44             :     // @Range: 0 10
      45             :     // @User: Advanced
      46             : 
      47             :     // @Param: POS_Z
      48             :     // @DisplayName: SITL vicon position on vehicle in Down direction
      49             :     // @Description: SITL vicon position on vehicle in Down direction
      50             :     // @Units: m
      51             :     // @Range: 0 10
      52             :     // @User: Advanced
      53             :     AP_GROUPINFO("POS",     1, ViconParms,  pos_offset, 0),
      54             : 
      55             :     // @Param: GLIT_X
      56             :     // @DisplayName: SITL vicon position glitch North
      57             :     // @Description: SITL vicon position glitch North
      58             :     // @Units: m
      59             :     // @User: Advanced
      60             : 
      61             :     // @Param: GLIT_Y
      62             :     // @DisplayName: SITL vicon position glitch East
      63             :     // @Description: SITL vicon position glitch East
      64             :     // @Units: m
      65             :     // @User: Advanced
      66             : 
      67             :     // @Param: GLIT_Z
      68             :     // @DisplayName: SITL vicon position glitch Down
      69             :     // @Description: SITL vicon position glitch Down
      70             :     // @Units: m
      71             :     // @User: Advanced
      72             :     AP_GROUPINFO("GLIT",    2, ViconParms,  glitch, 0),
      73             : 
      74             :     // @Param: FAIL
      75             :     // @DisplayName: SITL vicon failure
      76             :     // @Description: SITL vicon failure
      77             :     // @Values: 0:Vicon Healthy, 1:Vicon Failed
      78             :     // @User: Advanced
      79             :     AP_GROUPINFO("FAIL",    3, ViconParms,  fail, 0),
      80             : 
      81             :     // @Param: YAW
      82             :     // @DisplayName: SITL vicon yaw angle in earth frame
      83             :     // @Description: SITL vicon yaw angle in earth frame
      84             :     // @Units: deg
      85             :     // @Range: 0 360
      86             :     // @User: Advanced
      87             :     AP_GROUPINFO("YAW",     4, ViconParms,  yaw, 0),
      88             : 
      89             :     // @Param: YAWERR
      90             :     // @DisplayName: SITL vicon yaw error
      91             :     // @Description: SITL vicon yaw added to reported yaw sent to vehicle
      92             :     // @Units: deg
      93             :     // @Range: -180 180
      94             :     // @User: Advanced
      95             :     AP_GROUPINFO("YAWERR",  5, ViconParms,  yaw_error, 0),
      96             : 
      97             :     // @Param: TMASK
      98             :     // @DisplayName: SITL vicon type mask
      99             :     // @Description: SITL vicon messages sent
     100             :     // @Bitmask: 0:VISION_POSITION_ESTIMATE, 1:VISION_SPEED_ESTIMATE, 2:VICON_POSITION_ESTIMATE, 3:VISION_POSITION_DELTA, 4:ODOMETRY
     101             :     // @User: Advanced
     102             :     AP_GROUPINFO("TMASK",   6, ViconParms,  type_mask, 3),
     103             : 
     104             :     // @Param: VGLI_X
     105             :     // @DisplayName: SITL vicon velocity glitch North
     106             :     // @Description: SITL vicon velocity glitch North
     107             :     // @Units: m/s
     108             :     // @User: Advanced
     109             : 
     110             :     // @Param: VGLI_Y
     111             :     // @DisplayName: SITL vicon velocity glitch East
     112             :     // @Description: SITL vicon velocity glitch East
     113             :     // @Units: m/s
     114             :     // @User: Advanced
     115             : 
     116             :     // @Param: VGLI_Z
     117             :     // @DisplayName: SITL vicon velocity glitch Down
     118             :     // @Description: SITL vicon velocity glitch Down
     119             :     // @Units: m/s
     120             :     // @User: Advanced
     121             :     AP_GROUPINFO("VGLI",    7, ViconParms,  vel_glitch, 0),
     122             : 
     123             :     // @Param: P_SD
     124             :     // @DisplayName: SITL vicon position standard deviation for gaussian noise
     125             :     // @Description: SITL vicon position standard deviation for gaussian noise
     126             :     // @Units: m
     127             :     // @User: Advanced
     128             :     AP_GROUPINFO("P_SD",  8, ViconParms,  pos_stddev, 0.0f),
     129             : 
     130             :     // @Param: V_SD
     131             :     // @DisplayName: SITL vicon velocity standard deviation for gaussian noise
     132             :     // @Description: SITL vicon velocity standard deviation for gaussian noise
     133             :     // @Units: m/s
     134             :     // @User: Advanced
     135             :     AP_GROUPINFO("V_SD",  9, ViconParms,  vel_stddev, 0.0f),
     136             : 
     137             :     // @Param: RATE
     138             :     // @DisplayName: SITL vicon rate
     139             :     // @Description: SITL vicon rate
     140             :     // @Units: Hz
     141             :     // @User: Advanced
     142             :     AP_GROUPINFO("RATE",  10, ViconParms,  rate_hz, 50),
     143             : 
     144             :     // @Param: QUAL
     145             :     // @DisplayName: SITL vicon odometry quality
     146             :     // @Description: SITL vicon odometry quality field sent in MAVLink ODOMETRY message (-1=failure, 0=unknown, 1-100=quality)
     147             :     // @Units: %
     148             :     // @Range: -1 100
     149             :     // @User: Advanced
     150             :     AP_GROUPINFO("QUAL", 11, ViconParms, quality, 50),
     151             : 
     152             :     AP_GROUPEND
     153             : };
     154             : 
     155           8 : Vicon::Vicon() :
     156           8 :     SerialDevice::SerialDevice()
     157             : {
     158           8 : }
     159             : 
     160      886133 : void Vicon::maybe_send_heartbeat()
     161             : {
     162      886133 :     const uint32_t now = AP_HAL::millis();
     163             : 
     164      886133 :     if (now - last_heartbeat_ms < 500) {
     165             :         // we only provide a heartbeat every so often
     166      884698 :         return;
     167             :     }
     168             : 
     169             :     uint8_t msg_buf_index;
     170       23722 :     if (!get_free_msg_buf_index(msg_buf_index)) {
     171       22287 :         return;
     172             :     }
     173             : 
     174        1435 :     last_heartbeat_ms = now;
     175             : 
     176        1435 :     const mavlink_heartbeat_t heartbeat{
     177             :         custom_mode: 0,
     178             :         type : MAV_TYPE_GCS,
     179             :         autopilot : MAV_AUTOPILOT_INVALID,
     180             :         base_mode: 0,
     181             :         system_status: 0,
     182             :         mavlink_version: 0,
     183             :     };
     184             : 
     185        1435 :     mavlink_msg_heartbeat_encode_status(
     186        1435 :         system_id,
     187        1435 :         component_id,
     188             :         &mav_status,
     189        1435 :         &msg_buf[msg_buf_index].obs_msg,
     190             :         &heartbeat
     191             :     );
     192        1435 :     msg_buf[msg_buf_index].time_send_us = AP_HAL::millis();
     193             : }
     194             : 
     195             : // get unused index in msg_buf
     196       48025 : bool Vicon::get_free_msg_buf_index(uint8_t &index)
     197             : {
     198      152450 :     for (uint8_t i=0; i<ARRAY_SIZE(msg_buf); i++) {
     199      124553 :         if (msg_buf[i].time_send_us == 0) {
     200       20128 :             index = i;
     201       20128 :             return true;
     202             :         }
     203             :     }
     204       27897 :     return false;
     205             : }
     206             : 
     207      886133 : void Vicon::update_vicon_position_estimate(const Location &loc,
     208             :                                            const Vector3d &position,
     209             :                                            const Vector3f &velocity,
     210             :                                            const Quaternion &attitude)
     211             : {
     212      886133 :     const uint64_t now_us = AP_HAL::micros64();
     213             : 
     214             :     // calculate a random time offset to the time sent in the message
     215             :     // simulates a time difference between the remote computer and autopilot
     216      886133 :     if (time_offset_us == 0) {
     217           8 :         time_offset_us = (unsigned(random()) % 7000) * 1000000ULL;
     218           8 :         printf("time_offset_us %llu\n", (long long unsigned)time_offset_us);
     219             :     }
     220             : 
     221             :     // send all messages in the buffer
     222      886133 :     bool waiting_to_send = false;
     223     3544532 :     for (uint8_t i=0; i<ARRAY_SIZE(msg_buf); i++) {
     224     2658399 :         if ((msg_buf[i].time_send_us > 0) && (now_us >= msg_buf[i].time_send_us)) {
     225             :             uint8_t buf[300];
     226       20113 :             uint16_t buf_len = mavlink_msg_to_send_buffer(buf, &msg_buf[i].obs_msg);
     227             : 
     228       20113 :             if (write_to_autopilot((char*)&buf, buf_len) != buf_len) {
     229           0 :                 hal.console->printf("Vicon: write failure\n");
     230             :             }
     231       20113 :             msg_buf[i].time_send_us = 0;
     232             :         }
     233     2658399 :         waiting_to_send = msg_buf[i].time_send_us != 0;
     234             :     }
     235      886133 :     if (waiting_to_send) {
     236             :         // waiting for the last msg to go out
     237      870666 :         return;
     238             :     }
     239             : 
     240      232615 :     if (_sitl->vicon.rate_hz == 0) {
     241           0 :         return;
     242             :     }
     243      232615 :     const uint64_t vicon_interval_us = 1000000UL / _sitl->vicon.rate_hz;  // Interval in microseconds based on rate
     244      232615 :     if (now_us - last_observation_usec < vicon_interval_us) {
     245             :         // create observations at rate specified by vicon_rate_hz
     246             :         // by default runs at 50Hz
     247      197718 :         return;
     248             :     }
     249             : 
     250             :     // failure simulation
     251       34897 :     if (_sitl->vicon.fail.get() != 0) {
     252       19430 :         return;
     253             :     }
     254             : 
     255             :     float roll;
     256             :     float pitch;
     257             :     float yaw;
     258       15467 :     attitude.to_euler(roll, pitch, yaw);
     259             : 
     260             :     // calculate sensor offset in earth frame
     261       15467 :     const Vector3f& pos_offset = _sitl->vicon.pos_offset.get();
     262       15467 :     Matrix3f rot;
     263       15467 :     rot.from_euler(radians(_sitl->state.rollDeg), radians(_sitl->state.pitchDeg), radians(_sitl->state.yawDeg));
     264       15467 :     Vector3f pos_offset_ef = rot * pos_offset;
     265             : 
     266             :     // add earth frame sensor offset and glitch to position
     267       15467 :     Vector3d pos_corrected = position + (pos_offset_ef + _sitl->vicon.glitch.get()).todouble();
     268             :     // add some gaussian noise to the position
     269       15467 :     pos_corrected += Vector3d(
     270       15467 :         Aircraft::rand_normal(0, _sitl->vicon.pos_stddev.get()),
     271       15467 :         Aircraft::rand_normal(0, _sitl->vicon.pos_stddev.get()),
     272       15467 :         Aircraft::rand_normal(0, _sitl->vicon.pos_stddev.get())
     273       15467 :     );
     274             : 
     275             :     // calculate a velocity offset due to the antenna position offset and body rotation rate
     276             :     // note: % operator is overloaded for cross product
     277       15467 :     Vector3f gyro(radians(_sitl->state.rollRate),
     278       15467 :                   radians(_sitl->state.pitchRate),
     279       15467 :                   radians(_sitl->state.yawRate));
     280       15467 :     Vector3f vel_rel_offset_bf = gyro % pos_offset;
     281             : 
     282             :     // rotate the velocity offset into earth frame and add to the c.g. velocity
     283       15467 :     Vector3f vel_rel_offset_ef = rot * vel_rel_offset_bf;
     284       15467 :     Vector3f vel_corrected = velocity + vel_rel_offset_ef + _sitl->vicon.vel_glitch.get();
     285             : 
     286             :     // adjust yaw, position and velocity to account for vicon's yaw
     287       15467 :     const int16_t vicon_yaw_deg = _sitl->vicon.yaw.get();
     288       15467 :     if (vicon_yaw_deg != 0) {
     289           0 :         const float vicon_yaw_rad = radians(vicon_yaw_deg);
     290           0 :         yaw = wrap_PI(yaw - vicon_yaw_rad);
     291           0 :         Matrix3d vicon_yaw_rot;
     292           0 :         vicon_yaw_rot.from_euler(0, 0, -vicon_yaw_rad);
     293           0 :         pos_corrected = vicon_yaw_rot * pos_corrected;
     294           0 :         vel_corrected = vicon_yaw_rot.tofloat() * vel_corrected;
     295             :     }
     296             : 
     297             :     // add some gaussian noise to the velocity
     298       15467 :     vel_corrected += Vector3f(
     299       15467 :         Aircraft::rand_normal(0, _sitl->vicon.vel_stddev.get()),
     300       15467 :         Aircraft::rand_normal(0, _sitl->vicon.vel_stddev.get()),
     301       15467 :         Aircraft::rand_normal(0, _sitl->vicon.vel_stddev.get())
     302       15467 :     );
     303             : 
     304             :     // add yaw error reported to vehicle
     305       15467 :     yaw = wrap_PI(yaw + radians(_sitl->vicon.yaw_error.get()));
     306             : 
     307             :     // 25ms to 124ms delay before sending
     308       15467 :     uint32_t delay_ms = 25 + unsigned(random()) % 100;
     309       15467 :     uint64_t time_send_us = now_us + delay_ms * 1000UL;
     310             : 
     311             : 
     312             :     float pose_cov[21];
     313       15467 :     memset(pose_cov, 0, sizeof(pose_cov));
     314             :     // Set variances (diagonal elements), assume no cross-correlation. TODO: figure out attitude variances
     315       15467 :     const float pos_variance = _sitl->vicon.pos_stddev*_sitl->vicon.pos_stddev;
     316       15467 :     pose_cov[0]  = pos_variance;   // x
     317       15467 :     pose_cov[6]  = pos_variance;   // y
     318       15467 :     pose_cov[11] = pos_variance;   // z
     319             : 
     320             :     // send vision position estimate message
     321             :     uint8_t msg_buf_index;
     322       15467 :     if (should_send(ViconTypeMask::VISION_POSITION_ESTIMATE) && get_free_msg_buf_index(msg_buf_index)) {
     323       10506 :         mavlink_vision_position_estimate_t vision_position_estimate{
     324       10506 :         usec: now_us + time_offset_us,
     325       10506 :         x: float(pos_corrected.x),
     326       10506 :         y: float(pos_corrected.y),
     327       10506 :         z: float(pos_corrected.z),
     328             :         roll: roll,
     329             :         pitch: pitch,
     330             :         yaw: yaw
     331       10506 :         };
     332       10506 :         memcpy(vision_position_estimate.covariance, pose_cov, sizeof(pose_cov));
     333             : 
     334       10506 :         mavlink_msg_vision_position_estimate_encode_status(
     335       10506 :             system_id,
     336       10506 :             component_id,
     337             :             &mav_status,
     338       10506 :             &msg_buf[msg_buf_index].obs_msg,
     339             :             &vision_position_estimate
     340             :         );
     341       10506 :         msg_buf[msg_buf_index].time_send_us = time_send_us;
     342             :     }
     343             : 
     344             :     // send older vicon position estimate message
     345       15467 :     if (should_send(ViconTypeMask::VICON_POSITION_ESTIMATE) && get_free_msg_buf_index(msg_buf_index)) {
     346           0 :         const mavlink_vicon_position_estimate_t vicon_position_estimate{
     347           0 :         usec: now_us + time_offset_us,
     348           0 :         x: float(pos_corrected.x),
     349           0 :         y: float(pos_corrected.y),
     350           0 :         z: float(pos_corrected.z),
     351             :         roll: roll,
     352             :         pitch: pitch,
     353             :         yaw: yaw
     354           0 :         };
     355           0 :         mavlink_msg_vicon_position_estimate_encode_status(
     356           0 :             system_id,
     357           0 :             component_id,
     358             :             &mav_status,
     359           0 :             &msg_buf[msg_buf_index].obs_msg,
     360             :             &vicon_position_estimate);
     361           0 :         msg_buf[msg_buf_index].time_send_us = time_send_us;
     362             :     }
     363             : 
     364             :     // send vision speed estimate
     365       15467 :     if (should_send(ViconTypeMask::VISION_SPEED_ESTIMATE) && get_free_msg_buf_index(msg_buf_index)) {
     366             :         float cov[9];
     367        4452 :         memset(cov, 0, sizeof(cov));
     368             :         // Set variances (diagonal elements), assume no cross-correlation
     369        4452 :         const float vel_variance = _sitl->vicon.vel_stddev*_sitl->vicon.vel_stddev;
     370        4452 :         cov[0] = vel_variance;   // x
     371        4452 :         cov[4] = vel_variance;   // y
     372        4452 :         cov[8] = vel_variance;   // z
     373        4452 :         mavlink_vision_speed_estimate_t vicon_speed_estimate{
     374        4452 :         usec: now_us + time_offset_us,
     375        4452 :         x: vel_corrected.x,
     376        4452 :         y: vel_corrected.y,
     377        4452 :         z: vel_corrected.z
     378        4452 :         };
     379        4452 :         memcpy(vicon_speed_estimate.covariance, cov, sizeof(cov));
     380             : 
     381        4452 :         mavlink_msg_vision_speed_estimate_encode_status(
     382        4452 :             system_id,
     383        4452 :             component_id,
     384             :             &mav_status,
     385        4452 :             &msg_buf[msg_buf_index].obs_msg,
     386             :             &vicon_speed_estimate
     387             :             );
     388        4452 :         msg_buf[msg_buf_index].time_send_us = time_send_us;
     389             :     }
     390             : 
     391             : 
     392             :     // send ODOMETRY message
     393       15467 :     if (should_send(ViconTypeMask::ODOMETRY) && get_free_msg_buf_index(msg_buf_index)) {
     394           0 :         const Vector3f vel_corrected_frd = attitude.inverse() * vel_corrected;
     395             :         float vel_cov[21];
     396           0 :         memset(vel_cov, 0, sizeof(vel_cov));
     397             :         // Set variances (diagonal elements), assume no cross-correlation. TODO: figure out angular velocity variances
     398           0 :         const float vel_variance = _sitl->vicon.vel_stddev*_sitl->vicon.vel_stddev;
     399           0 :         vel_cov[0] = vel_variance;   // x
     400           0 :         vel_cov[6] = vel_variance;   // y
     401           0 :         vel_cov[11] = vel_variance;   // z
     402             : 
     403           0 :         mavlink_odometry_t odometry{
     404           0 :         time_usec: now_us + time_offset_us,
     405           0 :         x: float(pos_corrected.x),
     406           0 :         y: float(pos_corrected.y),
     407           0 :         z: float(pos_corrected.z),
     408           0 :         q: {attitude[0], attitude[1], attitude[2], attitude[3]},
     409           0 :         vx: vel_corrected_frd.x,
     410           0 :         vy: vel_corrected_frd.y,
     411           0 :         vz: vel_corrected_frd.z,
     412           0 :         rollspeed: gyro.x,
     413           0 :         pitchspeed: gyro.y,
     414           0 :         yawspeed: gyro.z,
     415             :         pose_covariance: {},
     416             :         velocity_covariance: {},
     417             :         frame_id: MAV_FRAME_LOCAL_FRD,
     418             :         child_frame_id: MAV_FRAME_BODY_FRD,
     419             :         reset_counter: 0,
     420             :         estimator_type: MAV_ESTIMATOR_TYPE_VIO,
     421           0 :         quality: constrain_int8(_sitl->vicon.quality.get(), -1, 100),
     422           0 :         };
     423           0 :         memcpy(odometry.pose_covariance, pose_cov, sizeof(pose_cov));
     424           0 :         memcpy(odometry.velocity_covariance, vel_cov, sizeof(vel_cov));
     425             : 
     426           0 :         mavlink_msg_odometry_encode_status(
     427           0 :             system_id,
     428           0 :             component_id,
     429             :             &mav_status,
     430           0 :             &msg_buf[msg_buf_index].obs_msg,
     431             :             &odometry);
     432           0 :         msg_buf[msg_buf_index].time_send_us = time_send_us;
     433             :     }
     434             : 
     435             :     // determine time, position, and angular deltas
     436       15467 :     uint64_t time_delta = now_us - last_observation_usec;
     437             : 
     438       15467 :     Quaternion attitude_curr;                   // Rotation to current MAV_FRAME_BODY_FRD from MAV_FRAME_LOCAL_NED
     439       15467 :     attitude_curr.from_euler(roll, pitch, yaw); // Rotation to MAV_FRAME_LOCAL_NED from current MAV_FRAME_BODY_FRD
     440       15467 :     attitude_curr.invert();
     441             : 
     442       15467 :     Quaternion attitude_curr_prev = attitude_curr * _attitude_prev.inverse(); // Get rotation to current MAV_FRAME_BODY_FRD from previous MAV_FRAME_BODY_FRD
     443             : 
     444       15467 :     Matrix3f body_ned_m;
     445       15467 :     attitude_curr.rotation_matrix(body_ned_m);
     446             : 
     447       15467 :     Vector3f pos_delta = body_ned_m * (pos_corrected - _position_prev).tofloat();
     448             : 
     449             :     // send vision position delta
     450             :     // time_usec: (usec) Current time stamp
     451             :     // time_delta_usec: (usec) Time since last reported camera frame
     452             :     // angle_delta [3]: (radians) Roll, pitch, yaw angles that define rotation to current MAV_FRAME_BODY_FRD from previous MAV_FRAME_BODY_FRD
     453             :     // delta_position [3]: (meters) Change in position: To current position from previous position rotated to current MAV_FRAME_BODY_FRD from MAV_FRAME_LOCAL_NED
     454             :     // confidence: Normalized confidence level [0, 100]
     455       15467 :     if (should_send(ViconTypeMask::VISION_POSITION_DELTA) && get_free_msg_buf_index(msg_buf_index)) {
     456        3735 :         const mavlink_vision_position_delta_t vision_position_delta{
     457        3735 :         time_usec: now_us + time_offset_us,
     458             :         time_delta_usec: time_delta,
     459        3735 :         angle_delta: { attitude_curr_prev.get_euler_roll(),
     460        3735 :             attitude_curr_prev.get_euler_pitch(),
     461        3735 :             attitude_curr_prev.get_euler_yaw()
     462             :         },
     463        3735 :         position_delta: {pos_delta.x, pos_delta.y, pos_delta.z},
     464             :         confidence: 0
     465        3735 :         };
     466        3735 :         mavlink_msg_vision_position_delta_encode_status(
     467        3735 :             system_id,
     468        3735 :             component_id,
     469             :             &mav_status,
     470        3735 :             &msg_buf[msg_buf_index].obs_msg,
     471             :             &vision_position_delta);
     472        3735 :         msg_buf[msg_buf_index].time_send_us = time_send_us;
     473             :     }
     474             : 
     475             :     // set previous position & attitude
     476       15467 :     last_observation_usec = now_us;
     477       15467 :     _position_prev = pos_corrected;
     478       15467 :     _attitude_prev = attitude_curr;
     479             : }
     480             : 
     481             : /*
     482             :   update vicon sensor state
     483             :  */
     484      886133 : void Vicon::update(const Location &loc, const Vector3d &position, const Vector3f &velocity, const Quaternion &attitude)
     485             : {
     486      886133 :     if (!init_sitl_pointer()) {
     487           0 :         return;
     488             :     }
     489             : 
     490      886133 :     maybe_send_heartbeat();
     491      886133 :     update_vicon_position_estimate(loc, position, velocity, attitude);
     492             : }
     493             : 
     494             : #endif  // AP_SIM_VICON_ENABLED

Generated by: LCOV version 1.14