LCOV - code coverage report
Current view: top level - SITL - SIM_Gazebo.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 70 0.0 %
Date: 2026-09-09 11:02:08 Functions: 0 6 0.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 connector for ardupilot version of Gazebo
      17             : */
      18             : 
      19             : #include "SIM_config.h"
      20             : 
      21             : #if AP_SIM_GAZEBO_ENABLED
      22             : 
      23             : #include "SIM_Gazebo.h"
      24             : 
      25             : #include <stdio.h>
      26             : #include <errno.h>
      27             : 
      28             : namespace SITL {
      29             : 
      30           0 : Gazebo::Gazebo(const char *frame_str) :
      31             :     Aircraft(frame_str),
      32           0 :     last_timestamp(0),
      33           0 :     socket_sitl{true}
      34             : {
      35           0 :     fprintf(stdout, "Starting SITL Gazebo\n");
      36           0 : }
      37             : 
      38             : /*
      39             :   Create and set in/out socket
      40             : */
      41           0 : void Gazebo::set_interface_ports(const char* address, const int port_in, const int port_out)
      42             : {
      43             :     // try to bind to a specific port so that if we restart ArduPilot
      44             :     // Gazebo keeps sending us packets. Not strictly necessary but
      45             :     // useful for debugging
      46           0 :     if (!socket_sitl.bind("0.0.0.0", port_in)) {
      47           0 :         fprintf(stderr, "SITL: socket in bind failed on sim in : %d  - %s\n", port_in, strerror(errno));
      48           0 :         fprintf(stderr, "Aborting launch...\n");
      49           0 :         exit(1);
      50             :     }
      51           0 :     printf("Bind %s:%d for SITL in\n", "127.0.0.1", port_in);
      52           0 :     socket_sitl.reuseaddress();
      53           0 :     socket_sitl.set_blocking(false);
      54             : 
      55           0 :     _gazebo_address = address;
      56           0 :     _gazebo_port = port_out;
      57           0 :     printf("Setting Gazebo interface to %s:%d \n", _gazebo_address, _gazebo_port);
      58           0 : }
      59             : 
      60             : /*
      61             :   decode and send servos
      62             : */
      63           0 : void Gazebo::send_servos(const struct sitl_input &input)
      64             : {
      65             :     servo_packet pkt;
      66             :     // should rename servo_command
      67             :     // 16 because struct sitl_input.servos is 16 large in SIM_Aircraft.h
      68           0 :     for (unsigned i = 0; i < 16; ++i)
      69             :     {
      70           0 :       pkt.motor_speed[i] = (input.servos[i]-1000) / 1000.0f;
      71             :     }
      72           0 :     socket_sitl.sendto(&pkt, sizeof(pkt), _gazebo_address, _gazebo_port);
      73           0 : }
      74             : 
      75             : /*
      76             :   receive an update from the FDM
      77             :   This is a blocking function
      78             :  */
      79           0 : void Gazebo::recv_fdm(const struct sitl_input &input)
      80             : {
      81             :     fdm_packet pkt;
      82             : 
      83             :     /*
      84             :       we re-send the servo packet every 0.1 seconds until we get a
      85             :       reply. This allows us to cope with some packet loss to the FDM
      86             :      */
      87           0 :     while (socket_sitl.recv(&pkt, sizeof(pkt), 100) != sizeof(pkt)) {
      88           0 :         send_servos(input);
      89             :         // Reset the timestamp after a long disconnection, also catch gazebo reset
      90           0 :         if (get_wall_time_us() > last_wall_time_us + GAZEBO_TIMEOUT_US) {
      91           0 :             last_timestamp = 0;
      92             :         }
      93             :     }
      94             : 
      95           0 :     const double deltat = pkt.timestamp - last_timestamp;  // in seconds
      96           0 :     if (deltat < 0) {  // don't use old packet
      97           0 :         time_now_us += 1;
      98           0 :         return;
      99             :     }
     100             :     // get imu stuff
     101           0 :     accel_body = Vector3f(static_cast<float>(pkt.imu_linear_acceleration_xyz[0]),
     102           0 :                           static_cast<float>(pkt.imu_linear_acceleration_xyz[1]),
     103           0 :                           static_cast<float>(pkt.imu_linear_acceleration_xyz[2]));
     104             : 
     105           0 :     gyro = Vector3f(static_cast<float>(pkt.imu_angular_velocity_rpy[0]),
     106           0 :                     static_cast<float>(pkt.imu_angular_velocity_rpy[1]),
     107           0 :                     static_cast<float>(pkt.imu_angular_velocity_rpy[2]));
     108             : 
     109             :     // compute dcm from imu orientation
     110           0 :     Quaternion quat(static_cast<float>(pkt.imu_orientation_quat[0]),
     111           0 :                     static_cast<float>(pkt.imu_orientation_quat[1]),
     112           0 :                     static_cast<float>(pkt.imu_orientation_quat[2]),
     113           0 :                     static_cast<float>(pkt.imu_orientation_quat[3]));
     114           0 :     quat.rotation_matrix(dcm);
     115             : 
     116           0 :     velocity_ef = Vector3f(static_cast<float>(pkt.velocity_xyz[0]),
     117           0 :                            static_cast<float>(pkt.velocity_xyz[1]),
     118           0 :                            static_cast<float>(pkt.velocity_xyz[2]));
     119             : 
     120           0 :     position = Vector3d(pkt.position_xyz[0],
     121             :                         pkt.position_xyz[1],
     122             :                         pkt.position_xyz[2]);
     123           0 :     position.xy() += origin.get_distance_NE_double(home);
     124             : 
     125             :     // auto-adjust to simulation frame rate
     126           0 :     time_now_us += static_cast<uint64_t>(deltat * 1.0e6);
     127             : 
     128           0 :     if (deltat < 0.01 && deltat > 0) {
     129           0 :         adjust_frame_time(static_cast<float>(1.0/deltat));
     130             :     }
     131           0 :     last_timestamp = pkt.timestamp;
     132             : 
     133             : }
     134             : 
     135             : /*
     136             :   Drain remaining data on the socket to prevent phase lag.
     137             :  */
     138           0 : void Gazebo::drain_sockets()
     139             : {
     140           0 :     const uint16_t buflen = 1024;
     141             :     char buf[buflen];
     142             :     ssize_t received;
     143           0 :     errno = 0;
     144             :     do {
     145           0 :         received = socket_sitl.recv(buf, buflen, 0);
     146           0 :         if (received < 0) {
     147           0 :             if (errno != EAGAIN && errno != EWOULDBLOCK && errno != 0) {
     148           0 :                 fprintf(stderr, "error recv on socket in: %s \n",
     149           0 :                         strerror(errno));
     150             :             }
     151             :         } else {
     152             :             // fprintf(stderr, "received from control socket: %s\n", buf);
     153             :         }
     154           0 :     } while (received > 0);
     155             : 
     156           0 : }
     157             : 
     158             : /*
     159             :   update the Gazebo simulation by one time step
     160             :  */
     161           0 : void Gazebo::update(const struct sitl_input &input)
     162             : {
     163           0 :     send_servos(input);
     164           0 :     recv_fdm(input);
     165           0 :     update_battery();
     166           0 :     update_position();
     167             : 
     168           0 :     time_advance();
     169             :     // update magnetic field
     170           0 :     update_mag_field_bf();
     171           0 :     drain_sockets();
     172           0 : }
     173             : 
     174             : }  // namespace SITL
     175             : 
     176             : 
     177             : #endif  // AP_SIM_GAZEBO_ENABLED

Generated by: LCOV version 1.14