Rebuild trinity visualizer from bare SDL and OpenGL to using Raylib. Added Code for serial parsing on linux. Current functionality reads incoming quaternion packet data coming in over serial and displays the values and also visualizes with a cube, connect and disconnect is implemented. Essentially rebuild the functionality of the old version with added linux support.
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
#include <cstdint>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include "raylib.h"
|
||||
#include <raymath.h>
|
||||
#include <uchar.h>
|
||||
#include "serialcomm.hpp"
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
//#define RAYGUI_IMPLEMENTATION
|
||||
//#include "ressources/raygui/raygui.h"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "ressources/rlImGui-Raylib_6_0/rlImGui.h"
|
||||
#include "rlImGui.h"
|
||||
//#include "glm/glm.hpp"
|
||||
|
||||
// global variables for the communication between parsing and main thread
|
||||
std::mutex quaternion_mutex;
|
||||
Quaternion newest_quaternion = {0.0f};
|
||||
std::vector<Quaternion> quaternion_history;
|
||||
bool read_new_quaternion_data = true;
|
||||
|
||||
|
||||
const int WIDTH = 1280;
|
||||
const int HEIGTH = 720;
|
||||
|
||||
|
||||
// seperate thread for the serial parsing of the incoming binary data from the mcu
|
||||
void serial_parser_thread() {
|
||||
// define data variables and open serial port
|
||||
int serPort = linux_initSerialPort();
|
||||
size_t bytes_read;
|
||||
std::vector<uint8_t> binary_data_buffer(64);
|
||||
std::vector<uint8_t> binary_Packet_Buffer;
|
||||
|
||||
while (read_new_quaternion_data) {
|
||||
if (linux_readSerialData(serPort, binary_data_buffer, bytes_read)) {
|
||||
binary_Packet_Buffer.insert(binary_Packet_Buffer.end(), binary_data_buffer.begin(), binary_data_buffer.begin() + bytes_read); //binary_data_buffer.end());
|
||||
|
||||
while(true) {
|
||||
std::vector<uint8_t>packet = extractPacket(binary_Packet_Buffer);
|
||||
|
||||
if (packet.empty()) break;
|
||||
|
||||
Quaternion quat;
|
||||
if (parseBinaryPacket(packet,quat)) {
|
||||
|
||||
// lock the mutex to update quaternion and add to quaternion_history
|
||||
std::lock_guard<std::mutex> lock(quaternion_mutex);
|
||||
newest_quaternion = quat;
|
||||
quaternion_history.push_back(quat);
|
||||
if (quaternion_history.size() > 200) {
|
||||
quaternion_history.erase((quaternion_history.begin()));
|
||||
}
|
||||
|
||||
// now print the quaternions formatted into the console for debugging
|
||||
std::cout << std::fixed << std::setprecision(6) <<
|
||||
"w: " << std::setw(10) << quat.w <<
|
||||
" x: " << std::setw(10) << quat.x <<
|
||||
" y: " << std::setw(10) << quat.y <<
|
||||
" z: " << std::setw(10) << quat.z << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (linux_close_serial_port(serPort)) {
|
||||
std::cout << "Serial port " << serPort << " succesfully closed" << std::endl;
|
||||
} else {
|
||||
std::cout << "[ERROR] closing Serial port " << serPort << std::endl;
|
||||
}
|
||||
std::cout << "Serial communication thread exiting" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
|
||||
// start the parsing thread
|
||||
std::thread *serial_parsing_thread = nullptr;
|
||||
serial_parsing_thread = new std::thread(serial_parser_thread);
|
||||
Quaternion cube_movement_quaternion;
|
||||
std::vector<Quaternion> quat_history;
|
||||
|
||||
// setup dear imgui for the UI
|
||||
rlImGuiSetup(true);
|
||||
|
||||
// Create the window
|
||||
InitWindow(WIDTH, HEIGTH, "Trinity Control");
|
||||
SetTargetFPS(60);
|
||||
|
||||
// define 3D camecra
|
||||
Camera camera = {0};
|
||||
camera.position = (Vector3){3.0f, 10.0f, 10.0f};
|
||||
camera.target = (Vector3){0.0f, 0.0f, 0.0f};
|
||||
camera.up = (Vector3){0.0f, 1.0f, 0.0f};
|
||||
camera.fovy = 45.0f;
|
||||
camera.projection = CAMERA_PERSPECTIVE;
|
||||
|
||||
Vector3 CubePosition = {0.0f, 0.0f, 0.0f};
|
||||
Vector3 CubeDimensions = {4.0f, 4.0f, 4.0f};
|
||||
|
||||
// load image for the cube texture
|
||||
Model model = LoadModelFromMesh(GenMeshCube(CubeDimensions.x, CubeDimensions.y, CubeDimensions.z));
|
||||
if (!IsModelValid(model)){
|
||||
std::cout << "Loaded model is not valid" << std::endl;
|
||||
}
|
||||
Mesh mesh = model.meshes[0];
|
||||
|
||||
Image img = LoadImage("kekusmaximus.png");
|
||||
Texture2D texture = LoadTextureFromImage(img);
|
||||
UnloadImage(img);
|
||||
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;
|
||||
|
||||
while (!WindowShouldClose()) {
|
||||
|
||||
// get the newest quaternion and quaternion_history from parsing thread
|
||||
Quaternion cube_movement_quaternion;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(quaternion_mutex);
|
||||
cube_movement_quaternion = newest_quaternion;
|
||||
quat_history = quaternion_history;
|
||||
|
||||
}
|
||||
|
||||
BeginDrawing();
|
||||
ClearBackground(RAYWHITE);
|
||||
DrawText("BIG TITTY GOTH GIRLS", 190, 200, 20, LIGHTGRAY);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
Matrix rot_matrix = QuaternionToMatrix(cube_movement_quaternion);
|
||||
model.transform = MatrixMultiply(rot_matrix, MatrixTranslate(CubePosition.x, CubePosition.y, CubePosition.z));
|
||||
DrawMesh(mesh, model.materials[0], model.transform);
|
||||
|
||||
DrawModel(model,CubePosition, 1.0f , WHITE);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
rlImGuiBegin();
|
||||
ImGui::Text("Im a good little slut, daddy");
|
||||
ImGui::Text("w: %.4f x: %.4f y: %.4f z: %.4f", cube_movement_quaternion.w, cube_movement_quaternion.x, cube_movement_quaternion.y, cube_movement_quaternion.z);
|
||||
ImGui::Text("Connection to MCU: ");
|
||||
|
||||
ImGui::BeginDisabled(serial_parsing_thread != nullptr);
|
||||
if (ImGui::Button("Connect")) {
|
||||
read_new_quaternion_data = true;
|
||||
serial_parsing_thread = new std::thread(serial_parser_thread);
|
||||
} ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::BeginDisabled(serial_parsing_thread == nullptr);
|
||||
if (ImGui::Button("Disconnect")) {
|
||||
read_new_quaternion_data = false;
|
||||
serial_parsing_thread -> join();
|
||||
delete serial_parsing_thread;
|
||||
serial_parsing_thread = nullptr;
|
||||
} ImGui::EndDisabled();
|
||||
|
||||
|
||||
// create scrolling section for last 200 measurements
|
||||
ImGui::BeginChild("History", ImVec2(0, 300), true, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
// loop through quadHistory vector and display each element as line
|
||||
for (uint32_t i = 0; i < quat_history.size(); i++) {
|
||||
const Quaternion& q = quat_history[i];
|
||||
ImGui::Text("w: %.4f x: %.4f y: %.4f z: %.4f", q.w, q.x, q.y, q.z);
|
||||
}
|
||||
// enable autoscroll to newest entry
|
||||
if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
rlImGuiEnd();
|
||||
EndDrawing();
|
||||
}
|
||||
|
||||
//close parser thread and unload texture/model
|
||||
serial_parsing_thread -> join();
|
||||
delete serial_parsing_thread;
|
||||
UnloadTexture(texture);
|
||||
UnloadModel(model);
|
||||
CloseWindow();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user