Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,31 @@ jobs:
run: |
cd ./efc
west build -b eurus_nexus_v1_1 app

build-sitl:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
path: efc

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.12

- name: Install project requirements
run: |
sudo apt-get update && sudo apt-get update
sudo apt-get install libuv1-dev
cd ./efc
python -m venv python_venv
./python_venv/bin/pip install -r requirements.txt

- name: Build project
run: |
cd ./efc
cmake -B build -S sitl
cmake --build build
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,38 @@ cd efc
west build -b eurus_nexus_v1_1 app
```

## EFC SITL
SITL (Software In The Loop) for the EFC autopilot runs the EFC flight control software on a host machine (PC) while interfacing with a flight simulator that models vehicle dynamics and the environment. The simulator provides synthetic sensor data to EFC, and EFC computes and returns actuator commands, forming a closed control loop. This setup enables realistic testing and validation of the EFC autopilot without physical hardware.
EFC SITL is designed for the EFC autopilot to interact with [jMAVSim](https://github.com/PX4/jMAVSim) simulator.

## Build EFC SITL

### EFC SITL build dependencies

EFC SITL depends on [libuv](https://libuv.org/); therefore, `libuv` must be installed on the host system.
On Debian-based systems, `libuv` can be installed using:
```bash
apt-get install libuv1-dev
```

### EFC SITL build procedure

1. Create a efc-specific virtual environment and install the required packages (if it hasn't already been created):
```bash
cd ~/eurus/efc
python -m venv python_venv
source python_venv/bin/activate
pip install -r requirements.txt
deactivate
```
> Note: Sourcing the efc virtual environment will not be necessary after the first time as CMake will use the virtual environment python binary.

2. Use CMake to build EFC SITL
```bash
cd ~/eurus/efc
cmake -B build -S sitl
cmake --build build
```

## Contributing
The `efc` project uses code formatting rules described in `.clang-format`.
Expand Down
32 changes: 32 additions & 0 deletions sitl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# This file is part of the efc project <https://github.com/eurus-project/efc/>.
# Copyright (c) (2024 - Present), The efc developers.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required(VERSION 3.20.0)

project(efc-sitl
VERSION 0.1
LANGUAGES C
)

set(EFC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)
if(CMAKE_HOST_WIN32)
set(VENV_PYTHON ${EFC_SOURCE_DIR}/python_venv/Scripts/python)
else()
set(VENV_PYTHON ${EFC_SOURCE_DIR}/python_venv/bin/python)
endif()

add_subdirectory(external/mavlink)
add_subdirectory(external/autopilot)
add_subdirectory(app)
35 changes: 35 additions & 0 deletions sitl/app/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# This file is part of the efc project <https://github.com/eurus-project/efc/>.
# Copyright (c) (2024 - Present), The efc developers.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required(VERSION 3.20.0)

add_executable(efc_sitl
src/main.c
)

target_link_libraries(efc_sitl
PUBLIC
mavlink
uv
)

target_compile_options(efc_sitl
PUBLIC
-Wall
-Wextra
-Werror

-Wno-unused-parameter
)
79 changes: 79 additions & 0 deletions sitl/app/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* This file is part of the efc project <https://github.com/eurus-project/efc/>.
* Copyright (c) (2024 - Present), The efc developers.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <string.h>

#include <uv.h>

// MAVLink headers
// clang-format off
#include "mavlink_custom.h" // Needs to be included before any MAVLink header inclusion
#include "common/mavlink.h"
// clang-format on

#define TARGET_IP "127.0.0.1"
#define TARGET_PORT 14560

static uv_udp_t udp;
static uv_udp_send_t send_req;
static struct sockaddr_in target_addr;

const uint8_t telemetry_system_id = 0;
const uint8_t telemetry_component_id = MAV_COMP_ID_AUTOPILOT1;
const uint8_t telemetry_channel_ground = MAVLINK_COMM_0;

static mavlink_message_t mavlink_msg;
static uint8_t mavlink_ser_buf[MAVLINK_MAX_PACKET_LEN];

static void udp_cb(uv_udp_send_t *req, int status) {
if (status < 0) {
fprintf(stderr, "UDP send error: %s\n", uv_strerror(status));
}
}

static void heartbeat_timer_cb(uv_timer_t *handle) {
mavlink_msg_heartbeat_pack_chan(
telemetry_system_id, telemetry_component_id, telemetry_channel_ground,
&mavlink_msg, MAV_TYPE_GENERIC, MAV_AUTOPILOT_GENERIC,
MAV_MODE_FLAG_MANUAL_INPUT_ENABLED, 0, MAV_STATE_ACTIVE);

const uint16_t telemetry_msg_len =
mavlink_msg_to_send_buffer(mavlink_ser_buf, &mavlink_msg);

uv_buf_t buf = uv_buf_init((char *)mavlink_ser_buf, telemetry_msg_len);

uv_udp_send(&send_req, &udp, &buf, 1, (const struct sockaddr *)&target_addr,
udp_cb);
}

int main(void) {
uv_loop_t *loop = uv_default_loop();

uv_udp_init(loop, &udp);
uv_ip4_addr(TARGET_IP, TARGET_PORT, &target_addr);

uv_timer_t heartbeat_timer;
uv_timer_init(loop, &heartbeat_timer);
uv_timer_start(&heartbeat_timer, heartbeat_timer_cb, 0, 1000);

uv_run(loop, UV_RUN_DEFAULT);

uv_loop_close(loop);

return 0;
}
16 changes: 16 additions & 0 deletions sitl/external/autopilot/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This file is part of the efc project <https://github.com/eurus-project/efc/>.
# Copyright (c) (2024 - Present), The efc developers.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required(VERSION 3.20.0)
67 changes: 67 additions & 0 deletions sitl/external/mavlink/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# This file is part of the efc project <https://github.com/eurus-project/efc/>.
# Copyright (c) (2024 - Present), The efc developers.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

cmake_minimum_required(VERSION 3.20.0)

# Generate message headers
set(XML_FILES
${EFC_SOURCE_DIR}/tools/mavlink/message_definitions/v1.0/common.xml
)
set(GENERATED_DIR ${CMAKE_BINARY_DIR}/mavlink/generated)
set(GENERATOR_SCRIPT ${EFC_SOURCE_DIR}/tools/mavlink/pymavlink/tools/mavgen.py)

file(MAKE_DIRECTORY ${GENERATED_DIR})

set(DIALECT_HEADERS "")
foreach(file ${XML_FILES})
get_filename_component(dialect_name ${file} NAME_WLE)
set(DIALECT_HEADER ${GENERATED_DIR}/${dialect_name}/${dialect_name}.h)

add_custom_command(
OUTPUT ${DIALECT_HEADER}
COMMAND ${VENV_PYTHON} ${GENERATOR_SCRIPT} --lang=C --wire-protocol=2.0 -o ${GENERATED_DIR} ${file}
DEPENDS ${file} ${GENERATOR_SCRIPT}
COMMENT "Generating mavlink dialect from ${file}"
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)

list(APPEND DIALECT_HEADERS ${DIALECT_HEADER})
endforeach()

# Create the library
add_library(mavlink
STATIC
mavlink.c
${DIALECT_HEADERS} # Only used to make the library depend on all generation steps
)

target_include_directories(mavlink
SYSTEM PUBLIC
include
${GENERATED_DIR}
)

target_compile_definitions(mavlink
PUBLIC
# Conversions will be handled using different libraries
MAVLINK_NO_CONVERSION_HELPERS=true
# Good for both unreliable links and security
MAVLINK_CHECK_MESSAGE_LENGTH=true
# Use global buffers and statuses per channel, with helpers to point to them
# instead of them being defined in every source file mavlink is included in
# due to the unfortunate design of mavlink
MAVLINK_GET_CHANNEL_STATUS=mavlink_get_channel_status
MAVLINK_GET_CHANNEL_BUFFER=mavlink_get_channel_buffer
)
27 changes: 27 additions & 0 deletions sitl/external/mavlink/include/mavlink_custom.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* This file is part of the efc project <https://github.com/eurus-project/efc/>.
* Copyright (c) (2024 - Present), The efc developers.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __MAVLINK_CUSTOM_H__
#define __MAVLINK_CUSTOM_H__

#include "mavlink_types.h"

/* Global status and buffer instance getters */
mavlink_status_t *mavlink_get_channel_status(uint8_t chan);
mavlink_message_t *mavlink_get_channel_buffer(uint8_t chan);

#endif
30 changes: 30 additions & 0 deletions sitl/external/mavlink/mavlink.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* This file is part of the efc project <https://github.com/eurus-project/efc/>.
* Copyright (c) (2024 - Present), The efc developers.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "mavlink_custom.h"

/* Global status and buffer instances for each channel */
static mavlink_status_t chan_statuses[MAVLINK_COMM_NUM_BUFFERS];
static mavlink_message_t chan_buffers[MAVLINK_COMM_NUM_BUFFERS];

mavlink_status_t *mavlink_get_channel_status(uint8_t chan) {
return &chan_statuses[chan];
}

mavlink_message_t *mavlink_get_channel_buffer(uint8_t chan) {
return &chan_buffers[chan];
}