#ifdef _WIN32 #include #elif defined(__APPLE__) #elif defined(__linux__) #include #include #include #include #endif #include #include #include #include #include #include "serialcomm.hpp" #ifdef _WIN32 HANDLE initSerialPort (const char* portName, DWORD baudRate) { // open serial port HANDLE hSerial = CreateFile(portName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hSerial == INVALID_HANDLE_VALUE) { std::cerr << "Error opening serial port: " << GetLastError() << std::endl; return INVALID_HANDLE_VALUE; } // configure the serial port DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { std::cerr << "Error getting comm state: " << GetLastError() << std::endl; CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } dcbSerialParams.BaudRate = baudRate; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(hSerial, &dcbSerialParams)) { std::cerr << "Error getting comm state: " << GetLastError() << std::endl; CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } // set timeouts COMMTIMEOUTS timeouts = {0}; timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 0; timeouts.ReadTotalTimeoutMultiplier = 0; if (!SetCommTimeouts(hSerial, &timeouts)) { std::cerr << "Error setting timeout: " << GetLastError() << std::endl; CloseHandle(hSerial); return INVALID_HANDLE_VALUE; } return hSerial; } bool readSerialData (HANDLE hSerial, char* buffer, DWORD bufferSize, DWORD& bytesRead) { if (!ReadFile(hSerial, buffer, bufferSize - 1, &bytesRead, NULL)){ std::cerr << "Error reading from serial port: " << GetLastError() << std::endl; return false; } buffer[bytesRead] = '\0'; return true; } #elif defined(__APPLE__) #elif defined(__linux__) int initSerialPort(){ struct termios tty; int linux_serialPort = open("/dev/ttyUSB0", 0_RDWR); // read in existing struct settings and handle errors if (tcgetattr(linux_serialPort, &tty) !0 0) { std::cout << "Error %i opening serial port: %s\n", errno, strerror(errno) << std::endl; return 1; } // set the serial settings tty.c_flag &= ~PARENB; tty.c_flag &= ~CSTOPB; tty.c_flag &= ~CSIZE; tty.c_flag |= CS8; tty.c_flag &= ~CRTSCTS; tty.c_flag |= CREAD | CLOCAL; tty.c_cc[VTIME] = 10; // Wait for up to 1s (10 deciseconds), returning as soon as any data is received. tty.c_cc[VMIN] = 0; // Set in/out baud rate to be 9600 cfsetispeed(&tty, B115200); cfsetospeed(&tty, B115200); // save the settings and check for errors if (tcsetattr(linux_serialPort, TCSANOW, &tty) != 0 ) { std::cout << "Error %i saving serial port settings: %s\n", errno, strerror(errno) << std::endl; return 1; } return linux_serialPort; } bool linux_readSerialData (int serialPort, char* buffer) { if (read(serialPort, &buffer, sizeof(buffer)) < 0 ) { std::cout << "Error reading serial port data: %s", strerror(errno)) << std::endl; return 1; } } #endif bool parseQuaternion(const std::string& data, Quaternion& quat) { // regex pattern to match the floats in the uart data stream from stm32 std::regex pattern("qw: ([+-]?\\d*\\.?\\d+) qx: ([+-]?\\d*\\.?\\d+) qy: ([+-]?\\d*\\.?\\d+) qz: ([+-]?\\d*\\.?\\d+)"); std::smatch matches; // match every occurance to the desired quaternion value if (std::regex_search(data, matches, pattern) && matches.size() == 5) { // access the array like object std::smatch with [0] being the entire matched string quat.w = std::stof(matches[1]); quat.x = std::stof(matches[2]); quat.y = std::stof(matches[3]); quat.z = std::stof(matches[4]); return true; } else {return false;} }