Skip to content

Commit

Permalink
Dual redundancy
Browse files Browse the repository at this point in the history
  • Loading branch information
jnippula committed Jul 1, 2024
1 parent f2da227 commit 1b23e28
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 6 deletions.
9 changes: 7 additions & 2 deletions include/mavlink_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,13 @@ class MavlinkInterface {
void SetDevice(std::string device) {device_ = device;}
void SetEnableLockstep(bool enable_lockstep) {enable_lockstep_ = enable_lockstep;}
void SetMavlinkAddr(std::string mavlink_addr) {mavlink_addr_str_ = mavlink_addr;}
void SetSecondaryMavlinkAddr(std::string mavlink_addr) {secondary_mavlink_addr_str_ = mavlink_addr;}
void SetMavlinkTcpPort(int mavlink_tcp_port) {mavlink_tcp_port_ = mavlink_tcp_port;}
void SetMavlinkUdpRemotePort(int mavlink_udp_port) {mavlink_udp_remote_port_ = mavlink_udp_port;}
void SetMavlinkUdpLocalPort(int mavlink_udp_port) {mavlink_udp_local_port_ = mavlink_udp_port;}
bool IsRecvBuffEmpty() {return receiver_buffer_.empty();}

bool ReceivedHeartbeats() const { return received_heartbeats_; }
bool ReceivedHeartbeats() const { return received_heartbeats_[0] || received_heartbeats_[1]; }

private:
bool received_actuator_{false};
Expand Down Expand Up @@ -192,6 +193,8 @@ class MavlinkInterface {
socklen_t local_simulator_addr_len_;
struct sockaddr_in remote_simulator_addr_;
socklen_t remote_simulator_addr_len_;
struct sockaddr_in secondary_remote_simulator_addr_;
socklen_t secondary_remote_simulator_addr_len_;

unsigned char buf_[65535];
enum FD_TYPES {
Expand All @@ -205,7 +208,9 @@ class MavlinkInterface {
std::atomic<bool> close_conn_{false};

in_addr_t mavlink_addr_;
in_addr_t secondary_mavlink_addr_;
std::string mavlink_addr_str_{"INADDR_ANY"};
std::string secondary_mavlink_addr_str_{"INADDR_ANY"};
int mavlink_udp_remote_port_{kDefaultMavlinkUdpRemotePort}; // MAVLink refers to the PX4 simulator interface here
int mavlink_udp_local_port_{kDefaultMavlinkUdpLocalPort}; // MAVLink refers to the PX4 simulator interface here
int mavlink_tcp_port_{kDefaultMavlinkTcpPort}; // MAVLink refers to the PX4 simulator interface here
Expand Down Expand Up @@ -246,7 +251,7 @@ class MavlinkInterface {
//std::vector<HILData, Eigen::aligned_allocator<HILData>> hil_data_;
std::atomic<bool> gotSigInt_ {false};

bool received_heartbeats_ {false};
bool received_heartbeats_[2] {false, false};

std::mutex receiver_buff_mtx_;
std::queue<std::shared_ptr<mavlink_message_t>> receiver_buffer_;
Expand Down
7 changes: 7 additions & 0 deletions src/gazebo_mavlink_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ void GazeboMavlinkInterface::Configure(const gz::sim::Entity &_entity,
}
}

if (_sdf->HasElement("secondary_mavlink_addr")) {
std::string mavlink_addr_str = _sdf->Get<std::string>("secondary_mavlink_addr");
if (mavlink_addr_str != "INADDR_ANY") {
mavlink_interface_->SetSecondaryMavlinkAddr(mavlink_addr_str);
}
}

if (_sdf->HasElement("mavlink_udp_remote_port")) {
int mavlink_udp_remote_port = _sdf->Get<int>("mavlink_udp_remote_port");
mavlink_interface_->SetMavlinkUdpRemotePort(mavlink_udp_remote_port);
Expand Down
54 changes: 50 additions & 4 deletions src/mavlink_interface.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#include "mavlink_interface.h"

#define MAX_CONSECUTIVE_SPARE_MSG 10

MavlinkInterface::MavlinkInterface() {
}

Expand All @@ -24,6 +27,10 @@ void MavlinkInterface::Load()
remote_simulator_addr_.sin_family = AF_INET;
remote_simulator_addr_len_ = sizeof(remote_simulator_addr_);

memset((char *)&secondary_remote_simulator_addr_, 0, sizeof(secondary_remote_simulator_addr_));
secondary_remote_simulator_addr_.sin_family = AF_INET;
secondary_remote_simulator_addr_len_ = sizeof(secondary_remote_simulator_addr_);

memset((char *)&local_simulator_addr_, 0, sizeof(local_simulator_addr_));
local_simulator_addr_.sin_family = AF_INET;
local_simulator_addr_len_ = sizeof(local_simulator_addr_);
Expand Down Expand Up @@ -100,6 +107,8 @@ void MavlinkInterface::Load()
// When connecting to SITL, we specify the port where the mavlink traffic originates from.
remote_simulator_addr_.sin_addr.s_addr = mavlink_addr_;
remote_simulator_addr_.sin_port = htons(mavlink_udp_remote_port_);
secondary_remote_simulator_addr_.sin_addr.s_addr = secondary_mavlink_addr_;
secondary_remote_simulator_addr_.sin_port = htons(mavlink_udp_remote_port_);
local_simulator_addr_.sin_addr.s_addr = htonl(INADDR_ANY);
local_simulator_addr_.sin_port = htons(mavlink_udp_local_port_);

Expand Down Expand Up @@ -147,6 +156,9 @@ std::shared_ptr<mavlink_message_t> MavlinkInterface::PopRecvMessage() {
}

void MavlinkInterface::ReceiveWorker() {
struct sockaddr_in remote_addr;
socklen_t remote_addr_len = sizeof(remote_addr);

char thrd_name[64] = {0};
sprintf(thrd_name, "MAV_Recver_%d", gettid());
pthread_setname_np(pthread_self(), thrd_name);
Expand All @@ -167,7 +179,7 @@ void MavlinkInterface::ReceiveWorker() {
std::cout << "[" << thrd_name << "] Start receiving..." << std::endl;

while(!close_conn_ && !gotSigInt_) {
int ret = recvfrom(fds_[CONNECTION_FD].fd, buf_, sizeof(buf_), 0, (struct sockaddr *)&remote_simulator_addr_, &remote_simulator_addr_len_);
int ret = recvfrom(fds_[CONNECTION_FD].fd, buf_, sizeof(buf_), 0, (struct sockaddr *)&remote_addr, &remote_addr_len);
if (ret < 0) {
std::cerr << "[" << thrd_name << "] recvfrom error: " << strerror(errno) << std::endl;
if (errno == ECONNRESET) {
Expand Down Expand Up @@ -212,7 +224,17 @@ void MavlinkInterface::ReceiveWorker() {
receiver_buffer_.pop();
}
}
receiver_buffer_.push(msg);
if (remote_addr.sin_addr.s_addr == remote_simulator_addr_.sin_addr.s_addr) {
// Fix sysid to 1 for primary controller
msg->sysid = 1;
receiver_buffer_.push(msg);
} else if (remote_addr.sin_addr.s_addr == secondary_remote_simulator_addr_.sin_addr.s_addr) {
// Fix sysid to 2 for secondary controller
msg->sysid = 2;
receiver_buffer_.push(msg);
} else {
std::cerr << "[" << thrd_name << "] Received message from unknown address" << std::endl;
}
}
}
}
Expand Down Expand Up @@ -462,15 +484,38 @@ void MavlinkInterface::handle_message(mavlink_message_t *msg)
}
}

void MavlinkInterface::handle_heartbeat(mavlink_message_t *)
void MavlinkInterface::handle_heartbeat(mavlink_message_t *msg)
{
received_heartbeats_ = true;
if (msg->sysid == 1) {
received_heartbeats_[0] = true;
} else if (msg->sysid == 2) {
received_heartbeats_[1] = true;
}
}

void MavlinkInterface::handle_actuator_controls(mavlink_message_t *msg)
{
static int consecutive_spare_msg = 0;
const std::lock_guard<std::mutex> lock(actuator_mutex_);

if (msg->sysid == 2) {
if (consecutive_spare_msg < MAX_CONSECUTIVE_SPARE_MSG) {
consecutive_spare_msg++;
if (consecutive_spare_msg == MAX_CONSECUTIVE_SPARE_MSG) {
std::cout << "Primary controller not updating actuators => switch to backup controller" << std::endl;
} else {
return;
}
}
} else if (msg->sysid == 1) {
if (consecutive_spare_msg == MAX_CONSECUTIVE_SPARE_MSG) {
// Already switched to backup controller, ignore primary controller messages
return;
} else {
consecutive_spare_msg = 0;
}
}

mavlink_hil_actuator_controls_t controls;
mavlink_msg_hil_actuator_controls_decode(msg, &controls);

Expand Down Expand Up @@ -506,6 +551,7 @@ void MavlinkInterface::send_mavlink_message(const mavlink_message_t *message)
len = send(fds_[CONNECTION_FD].fd, buffer, packetlen, 0);
} else {
len = sendto(fds_[CONNECTION_FD].fd, buffer, packetlen, 0, (struct sockaddr *)&remote_simulator_addr_, remote_simulator_addr_len_);
len = sendto(fds_[CONNECTION_FD].fd, buffer, packetlen, 0, (struct sockaddr *)&secondary_remote_simulator_addr_, secondary_remote_simulator_addr_len_);
}
if (len < 0) {
if (received_first_actuator_) {
Expand Down

0 comments on commit 1b23e28

Please sign in to comment.