#include <stdio.h>
#include <chrono>
#include <math.h>
+#include <mutex>
+#include <thread>
// Pipes
#include <sys/types.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <common/mavlink.h>
#include <bcm2835.h>
+#include <Eigen/Core>
// Local
#include "pipe_def.h"
static err_t spi_init();
static err_t spi_write_alias(uint8_t reg, uint8_t* data_out, uint8_t len);
static err_t spi_read_alias(uint8_t reg, uint8_t* data_in, uint8_t len);
+[[noreturn]] static void send_mavlink(int);
+
+static vec3d gyro_vec;
+static vec3d accel_vec;
+static double temperature = 0.0;
+static Complementary_filter comp_filter{logger, 0.02};
+
+static std::mutex data_lock;
int main(int argc, char* argv[])
{
-
- logger = spdlog::stdout_color_mt("click_reader");
+ logger = spdlog::stdout_color_mt("controller");
logger->set_level(GLOB_LOGLEVEL);
logger->debug("Opening sendpipe for writing.");
int sendpipe_fd = open(SEND_PIPE, O_WRONLY);
+ logger->debug("Opening recvpipe for reading.");
+ int recvpipe_fd = open(RECV_PIPE, O_RDONLY);
+
logger->info("Initializing BCM2835 and SPI.");
if (spi_init() != OK)
{
c6dofimu17_cfg(&gyro_cfg, &accel_cfg);
- c6dofimu17_axis_t accel_data;
- c6dofimu17_axis_t gyro_data;
- double temperature = 0.0;
-
- Complementary_filter comp_filter{logger, 0.02};
-
int res = 0;
auto t_start = std::chrono::high_resolution_clock::now();
auto t_end = std::chrono::high_resolution_clock::now();
double time_d = 0.0;
- mavlink_message_t msg;
- mavlink_attitude_t attitude;
- mavlink_scaled_imu_t scaled_imu;
+ c6dofimu17_axis_t accel_data;
+ c6dofimu17_axis_t gyro_data;
+
+ // Mavlink thread
+ std::thread mavlink_task{send_mavlink, sendpipe_fd};
+
// Control loop
while (true)
{
THREAD_SLEEP(CLICK_READ_SPI_PERIOD);
+ std::lock_guard<std::mutex> lk{data_lock};
+
+ logger->debug("Controlling!");
+
res = c6dofimu17_get_gyro_data(&gyro_data);
t_end = std::chrono::high_resolution_clock::now();
time_d = std::chrono::duration<double>(t_end-t_start).count();
t_start = std::chrono::high_resolution_clock::now();
res += c6dofimu17_get_accel_data(&accel_data);
-
res += c6dofimu17_get_temperature(&temperature);
if (res != OK) {
continue;
}
- vec3d gyro_vec = struct_to_vec_scaled(gyro_data, (M_PI * 1000.0) / (32768.0 * 180.0));
- vec3d accel_vec = struct_to_vec_scaled(accel_data, (GRAVITY * 16.0) / 32768.0);
+ gyro_vec = struct_to_vec_scaled(gyro_data, (M_PI * 1000.0) / (32768.0 * 180.0));
+ accel_vec = struct_to_vec_scaled(accel_data, (GRAVITY * 16.0) / 32768.0);
comp_filter.update(gyro_vec, accel_vec, time_d);
-
- // Pack data into MAVLINK packages
- attitude.time_boot_ms = system_uptime_ms();
- attitude.roll = comp_filter.get_state()[1];
- attitude.pitch = comp_filter.get_state()[0];
- attitude.yaw = 0.0;
- attitude.rollspeed = 0.0;
- attitude.pitchspeed = 0.0;
- attitude.yawspeed = 0.0;
-
- scaled_imu.time_boot_ms = system_uptime_ms();
- scaled_imu.temperature = static_cast<int16_t>(temperature * 100);
- scaled_imu.xacc = static_cast<int16_t>(accel_vec[0] * 1000); // Maybe not correct?
- scaled_imu.yacc = static_cast<int16_t>(accel_vec[1] * 1000); // Maybe not correct?
- scaled_imu.zacc = static_cast<int16_t>(accel_vec[2] * 1000); // Maybe not correct?
- scaled_imu.xgyro = static_cast<int16_t>(gyro_vec[0] * 1000); // Maybe not correct?
- scaled_imu.ygyro = static_cast<int16_t>(gyro_vec[1] * 1000); // Maybe not correct?
- scaled_imu.zgyro = static_cast<int16_t>(gyro_vec[2] * 1000); // Maybe not correct?
- scaled_imu.xmag = INT16_MAX;
- scaled_imu.ymag = INT16_MAX;
- scaled_imu.zmag = INT16_MAX;
-
- mavlink_msg_attitude_encode(
- MAV_SYS_ID,
- MAV_COMP_ID,
- &msg,
- &attitude
- );
-
- uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
- int len;
-
- len = mavlink_msg_to_send_buffer(buffer, &msg);
- write(sendpipe_fd, buffer, len);
-
- mavlink_msg_scaled_imu_encode(
- MAV_SYS_ID,
- MAV_COMP_ID,
- &msg,
- &scaled_imu
- );
- len = mavlink_msg_to_send_buffer(buffer, &msg);
- write(sendpipe_fd, buffer, len);
}
close(sendpipe_fd);
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW); // the default
return OK;
+}
+
+[[noreturn]] static void send_mavlink(int sendpipe_fd)
+{
+ mavlink_message_t msg;
+ mavlink_attitude_t attitude;
+ mavlink_scaled_imu_t scaled_imu;
+
+ while (true)
+ {
+ THREAD_SLEEP(CONTROLLER_MAVLINK_PERIOD);
+ std::lock_guard<std::mutex> lk{data_lock};
+
+ logger->debug("Sending IMU Mavlink.");
+
+ // Pack data into MAVLINK packages
+ attitude.time_boot_ms = system_uptime_ms();
+ attitude.roll = comp_filter.get_state()[1];
+ attitude.pitch = comp_filter.get_state()[0];
+ attitude.yaw = 0.0;
+ attitude.rollspeed = 0.0;
+ attitude.pitchspeed = 0.0;
+ attitude.yawspeed = 0.0;
+
+ scaled_imu.time_boot_ms = system_uptime_ms();
+ scaled_imu.temperature = static_cast<int16_t>(temperature * 100);
+ scaled_imu.xacc = static_cast<int16_t>(accel_vec[0] * 1000); // Maybe not correct?
+ scaled_imu.yacc = static_cast<int16_t>(accel_vec[1] * 1000); // Maybe not correct?
+ scaled_imu.zacc = static_cast<int16_t>(accel_vec[2] * 1000); // Maybe not correct?
+ scaled_imu.xgyro = static_cast<int16_t>(gyro_vec[0] * 1000); // Maybe not correct?
+ scaled_imu.ygyro = static_cast<int16_t>(gyro_vec[1] * 1000); // Maybe not correct?
+ scaled_imu.zgyro = static_cast<int16_t>(gyro_vec[2] * 1000); // Maybe not correct?
+ scaled_imu.xmag = INT16_MAX;
+ scaled_imu.ymag = INT16_MAX;
+ scaled_imu.zmag = INT16_MAX;
+
+ mavlink_msg_attitude_encode(
+ MAV_SYS_ID,
+ MAV_COMP_ID,
+ &msg,
+ &attitude
+ );
+
+ uint8_t buffer[MAVLINK_MAX_PACKET_LEN];
+ int len;
+
+ len = mavlink_msg_to_send_buffer(buffer, &msg);
+ write(sendpipe_fd, buffer, len);
+
+ mavlink_msg_scaled_imu_encode(
+ MAV_SYS_ID,
+ MAV_COMP_ID,
+ &msg,
+ &scaled_imu
+ );
+ len = mavlink_msg_to_send_buffer(buffer, &msg);
+ write(sendpipe_fd, buffer, len);
+ }
}
\ No newline at end of file