From d627b7e41fc1d8ca04e2a59ae18172ed3770f7bf Mon Sep 17 00:00:00 2001 From: zeisele <zeisele@iastate.edu> Date: Thu, 10 Mar 2022 10:47:21 +0100 Subject: [PATCH] fix get/set on backend and implement on gui --- crazyflie_groundstation/src/CTOC.cpp | 20 +- .../src/ccrazyflie/CCrazyflie_commands.cpp | 67 +++--- .../ccrazyflie/CCrazyflie_loggingFuncs.cpp | 5 +- .../gui/MicroCART/crazyflieworker.cpp | 182 ++++++++++++++- groundStation/gui/MicroCART/crazyflieworker.h | 34 ++- groundStation/gui/MicroCART/mainwindow.cpp | 127 +++++++++- groundStation/gui/MicroCART/mainwindow.h | 15 ++ groundStation/gui/MicroCART/mainwindow.ui | 219 +++++++++++++++++- groundStation/src/backend/param.c | 31 +-- 9 files changed, 626 insertions(+), 74 deletions(-) diff --git a/crazyflie_groundstation/src/CTOC.cpp b/crazyflie_groundstation/src/CTOC.cpp index d60940447..bf93a6fb9 100644 --- a/crazyflie_groundstation/src/CTOC.cpp +++ b/crazyflie_groundstation/src/CTOC.cpp @@ -30,10 +30,10 @@ #include <limits> -static const char *param_header = "Param ID\tType\t\tGroup\t\t" +static const char *param_header = "Param ID\tType\tGroup\t" "Identifier Name"; -static const char *log_header = "Log ID\tType\t\tGroup\t\t" +static const char *log_header = "Log ID\tType\tGroup\t" "Identifier Name"; CTOC::CTOC(CCrazyRadio *crRadio, CCrazyflie *crazyflie, int radioChannel, int nPort) { @@ -172,6 +172,7 @@ bool CTOC::downloadTOC() { printf("Parameter Progress: %i / %i\n", nI+1, m_nItemCount); this->requestItem(nI); } + param_toc_file.close(); } else { this->requestMetaData(); @@ -179,6 +180,7 @@ bool CTOC::downloadTOC() { printf("Logging Progress: %i / %i\n", nI+1, m_nItemCount); this->requestItem(nI); } + log_toc_file.close(); } if( ALL_THE_DEBUG ) printf( "Exit: %s\n", __FUNCTION__); return true; @@ -219,10 +221,10 @@ bool CTOC::processItem(CCRTPPacket* crtpItem) { if(ALL_THE_DEBUG) printf("Group.Name: %s.%s ID: %i Type: %i ", strGroup.c_str(), strIdentifier.c_str(), nID, nType); if(m_nPort == 0x02) { - this->param_toc_file << teNew.nID << "\t\t" << teNew.nType << "\t\t" << teNew.strGroup << "\t\t" << teNew.strIdentifier << std::endl; + this->param_toc_file << teNew.nID << "\t" << teNew.nType << "\t" << teNew.strGroup << "\t" << teNew.strIdentifier << std::endl; } else if(m_nPort = 0x05) { - this->log_toc_file << teNew.nID << "\t\t" << teNew.nType << "\t\t" << teNew.strGroup << "\t\t" << teNew.strIdentifier << std::endl; + this->log_toc_file << teNew.nID << "\t" << teNew.nType << "\t" << teNew.strGroup << "\t" << teNew.strIdentifier << std::endl; } m_lstTOCElements.push_back(teNew); @@ -945,8 +947,9 @@ void CTOC::openParamTOCFile(char *baseFileName) { printf("Opening param toc file %s for quadcopter %d...", logFileName, (this->m_crazyflie->getQuadcopterNumber() + 1)); try { - char dir[250]; - getcwd(dir, 250); + char dir[256]; + dir[0] = '/'; + getcwd(&dir[1], 255); std::string fullFilePath(dir); fullFilePath += "/"; fullFilePath += logFileName; @@ -985,8 +988,9 @@ void CTOC::openLogTOCFile(char *baseFileName) { printf("Opening param toc file %s for quadcopter %d...", logFileName, (this->m_crazyflie->getQuadcopterNumber() + 1)); try { - char dir[250]; - getcwd(dir, 250); + char dir[256]; + dir[0] = '/'; + getcwd(&dir[1], 255); std::string fullFilePath(dir); fullFilePath += "/"; fullFilePath += logFileName; diff --git a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp index 7916a1100..bc0a76965 100644 --- a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp +++ b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_commands.cpp @@ -179,7 +179,7 @@ bool CCrazyflie::parseReceivedUserCommand() { case ACMD_GETPARAM: { - int nSize = 1; + int nSize = 2; char cBuffer[nSize]; CCRTPPacket *crtpPacket = new CCRTPPacket(cBuffer, nSize, CRTP_PORT_PARAM); @@ -187,13 +187,15 @@ bool CCrazyflie::parseReceivedUserCommand() { CCRTPPacket *crtpReceived; //int id = (char) command.payload; - char id = (char) command.payload[2]; + //char id = (char) command.payload[2]; + uint16_t id; + memcpy(&id, &command.payload[2], sizeof(uint16_t)); + memcpy(cBuffer, &command.payload[2], sizeof(uint16_t)); //float fvalue = build_float(&command.payload[4]); //uint16_t pvalue = (uint16_t) fvalue; bool bFound = false; struct TOCElement element = this->m_tocParameters->elementForID(id, bFound); - cBuffer[0] = id; //memcpy(&cBuffer[1 * sizeof(uint16_t)], &pvalue, sizeof(uint16_t)); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); @@ -208,7 +210,7 @@ bool CCrazyflie::parseReceivedUserCommand() { case ACMD_SETPARAM: { - int nSize = sizeof(double) + 1; + int nSize = sizeof(double) + 2; char cBuffer[nSize]; CCRTPPacket *crtpPacket = new CCRTPPacket(cBuffer, nSize, CRTP_PORT_PARAM); @@ -216,7 +218,10 @@ bool CCrazyflie::parseReceivedUserCommand() { CCRTPPacket *crtpReceived; //int id = (char) command.payload; - char pid = (char) command.payload[2]; + //char pid = (char) command.payload[2]; + uint16_t pid; + memcpy(&pid, &command.payload[2], 2); + memcpy(cBuffer, &command.payload[2], 2); bool bFound = false; struct TOCElement element = this->m_tocParameters->elementForID(pid, bFound); uint8_t pType = element.nType; @@ -226,9 +231,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { uint8_t pvalue = (uint8_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(uint8_t)); - nSize = 1 + sizeof(uint8_t); + memcpy(&cBuffer[2], &pvalue, sizeof(uint8_t)); + nSize = 2 + sizeof(uint8_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -237,9 +241,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { uint16_t pvalue = (uint16_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(uint16_t)); - nSize = 1 + sizeof(uint16_t); + memcpy(&cBuffer[2], &pvalue, sizeof(uint16_t)); + nSize = 2 + sizeof(uint16_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -248,9 +251,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { uint32_t pvalue = (uint32_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(uint32_t)); - nSize = 1 + sizeof(uint32_t); + memcpy(&cBuffer[2], &pvalue, sizeof(uint32_t)); + nSize = 2 + sizeof(uint32_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -259,9 +261,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { uint64_t pvalue = (uint64_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(uint64_t)); - nSize = 1 + sizeof(uint64_t); + memcpy(&cBuffer[2], &pvalue, sizeof(uint64_t)); + nSize = 2 + sizeof(uint64_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -270,9 +271,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { int8_t pvalue = (int8_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(int8_t)); - nSize = 1 + sizeof(int8_t); + memcpy(&cBuffer[2], &pvalue, sizeof(int8_t)); + nSize = 2 + sizeof(int8_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -281,9 +281,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { int16_t pvalue = (int16_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(int16_t)); - nSize = 1 + sizeof(int16_t); + memcpy(&cBuffer[2], &pvalue, sizeof(int16_t)); + nSize = 2 + sizeof(int16_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -292,9 +291,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { int32_t pvalue = (uint32_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(int32_t)); - nSize = 1 + sizeof(int32_t); + memcpy(&cBuffer[2], &pvalue, sizeof(int32_t)); + nSize = 2 + sizeof(int32_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -303,9 +301,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { int64_t pvalue = (int64_t) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(int64_t)); - nSize = 1 + sizeof(int64_t); + memcpy(&cBuffer[2], &pvalue, sizeof(int64_t)); + nSize = 2 + sizeof(int64_t); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -314,9 +311,8 @@ bool CCrazyflie::parseReceivedUserCommand() { { float pvalue = fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(float)); - nSize = 1 + sizeof(float); + memcpy(&cBuffer[2], &pvalue, sizeof(float)); + nSize = 2 + sizeof(float); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; @@ -325,16 +321,13 @@ bool CCrazyflie::parseReceivedUserCommand() { { double pvalue = (double) fvalue; - cBuffer[0] = pid; - memcpy(&cBuffer[1], &pvalue, sizeof(double)); - nSize = 1 + sizeof(double); + memcpy(&cBuffer[2], &pvalue, sizeof(double)); + nSize = 2 + sizeof(double); crtpPacket->setData(cBuffer, nSize); crtpReceived = m_crRadio->sendAndReceive(crtpPacket, m_nRadioChannel, this); break; } } - - break; } diff --git a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp index 293470194..bec1dd0f9 100644 --- a/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp +++ b/crazyflie_groundstation/src/ccrazyflie/CCrazyflie_loggingFuncs.cpp @@ -52,8 +52,9 @@ void CCrazyflie::openLogFile(char *baseFileName) { printf("Opening log file %s for quadcopter %d...", logFileName, (m_quadNum + 1)); try { - char dir[250]; - getcwd(dir, 250); + char dir[256]; + dir[0] = '/'; + getcwd(&dir[1], 255); std::string fullFilePath(dir); fullFilePath += "/"; fullFilePath += logFileName; diff --git a/groundStation/gui/MicroCART/crazyflieworker.cpp b/groundStation/gui/MicroCART/crazyflieworker.cpp index 6e5be8620..17629e40b 100644 --- a/groundStation/gui/MicroCART/crazyflieworker.cpp +++ b/groundStation/gui/MicroCART/crazyflieworker.cpp @@ -1,6 +1,9 @@ #include "crazyflieworker.h" +#include <iostream> +#include <unistd.h> +#include <sys/stat.h> -CrazyflieWorker::CrazyflieWorker(QObject *parent) : QObject(parent) +CrazyflieWorker::CrazyflieWorker(QObject *parent) : QObject(parent), conn(NULL) { } @@ -21,8 +24,16 @@ void CrazyflieWorker::connectBackend() conn = ucart_backendConnect(); emit (connected()); } else { - qInfo() << "Attempted to connect trackerworker when already connected!"; + qInfo() << "Attempted to connect crazyflieworker when already connected!"; } + loadParamIds(); + loadLogIds(); + QStringList paramGroupList; + for(int i = 0; i < paramGroups.size(); i++) { + QString qgName(paramGroups.at(i).groupName.c_str()); + paramGroupList.append(qgName); + } + emit(gotParamGroups(paramGroupList)); } /** @@ -87,18 +98,175 @@ void CrazyflieWorker::sendAttSetpoint() } void CrazyflieWorker::getParamValue(QString paramName){ - struct frontend_param_data data = paramNameLookup(paramName); + struct toc_info info = paramNameLookup(paramName); + + struct frontend_param_data data; + data.block = 0; + data.param = info.id; + data.value = info.value; if(frontend_getparam(conn, &data) == 0){ emit(gotParamValue(paramName, data.value)); } } -struct frontend_param_data CrazyflieWorker::paramNameLookup(QString paramName){ - //TODO - //if param is in cache, use that else lookup from file - struct frontend_param_data paramData; +void CrazyflieWorker::setParamValue(QString paramName, double value) { + struct toc_info info = paramNameLookup(paramName); + + struct frontend_param_data data; + data.block = 0; + data.param = info.id; + data.value = (float) value; + + if(frontend_setparam(conn, &data) != 0){ + //emit(gotParamValue(paramName, data.value)); + qInfo() << "setParamError"; + } +} + +struct toc_info CrazyflieWorker::paramNameLookup(QString paramName){ + struct toc_info paramData = paramIds.value(paramName); return paramData; } +std::string CrazyflieWorker::getLogFile(int type) { + struct frontend_getlogfile_data logfile; + char fname[256]; + logfile.command = type; + logfile.name = fname; + if(frontend_getlogfile(conn, &logfile)) { + return ""; + } + std::string result(logfile.name, strlen(logfile.name)); + return result; +} + +void CrazyflieWorker::loadParamIds() { + std::string filename = getLogFile(1); + std::ifstream paramTOCFile; + paramTOCFile.open(filename.c_str()); + std::string line; + //header and top line + std::getline(paramTOCFile, line); + std::getline(paramTOCFile, line); + //actual values; + while(std::getline(paramTOCFile, line)) { + struct toc_info values; + std::stringstream ss(line); + std::string temp_str; + for(int i = 0; i < 4; i++) { + std::getline(ss, temp_str, '\t'); + if(i == 0) { + values.id = (int16_t) stoi(temp_str); + } + else if(i == 1) { + values.dataType = (int8_t) stoi(temp_str); + } + else if(i == 2) { + values.strGroup = temp_str; + } + else if(i == 3) { + values.strName = temp_str; + } + } + values.value = 0; + + int gFound = findParamGroup(values.strGroup); + if(gFound == -1) { + struct toc_group groupx; + groupx.groupName = values.strGroup; + groupx.entryNames.push_back(values.strName); + paramGroups.push_back(groupx); + } + else { + paramGroups.at(gFound).entryNames.push_back(values.strName); + } + + std::string identifier = values.strGroup + "." + values.strName; + QString Qidentifier(identifier.c_str()); + paramIds.insert(Qidentifier, values); + } + paramTOCFile.close(); +} +void CrazyflieWorker::loadLogIds() { + std::string filename = getLogFile(2); + std::ifstream logTOCFile; + logTOCFile.open(filename.c_str()); + std::string line; + //top line + std::getline(logTOCFile, line); + std::getline(logTOCFile, line); + //actual values; + while(std::getline(logTOCFile, line)) { + struct toc_info values; + std::stringstream ss(line); + std::string temp_str; + for(int i = 0; i < 4; i++) { + std::getline(ss, temp_str, '\t'); + if(i == 0) { + values.id = (int16_t) stoi(temp_str); + } + else if(i == 1) { + values.dataType = (int8_t) stoi(temp_str); + } + else if(i == 2) { + values.strGroup = temp_str; + } + else if(i == 3) { + values.strName = temp_str; + } + } + values.value = 0; + + int gFound = findLogGroup(values.strGroup); + if(gFound == -1) { + struct toc_group groupx; + groupx.groupName = values.strGroup; + groupx.entryNames.push_back(values.strName); + logGroups.push_back(groupx); + } + else { + logGroups.at(gFound).entryNames.push_back(values.strName);; + } + + std::string identifier = values.strGroup + "." + values.strName; + QString Qidentifier(identifier.c_str()); + logIds.insert(Qidentifier, values); + } + logTOCFile.close(); +} + +int CrazyflieWorker::findParamGroup(std::string gName) { + int result = -1; + for(int i = 0; i < paramGroups.size(); i++) { + if(!paramGroups.at(i).groupName.compare(gName)) { + result = i; + break; + } + } + return result; +} + +int CrazyflieWorker::findLogGroup(std::string gName) { + int result = -1; + for(int i = 0; i < logGroups.size(); i++) { + if(!logGroups.at(i).groupName.compare(gName)) { + result = i; + break; + } + } + return result; +} + +void CrazyflieWorker::getGroupEntries(int box, QString gName) { + std::string name = gName.toStdString(); + int index = findParamGroup(name); + std::vector<std::string> entries = paramGroups.at(index).entryNames; + QStringList entryList; + for(int i = 0; i < entries.size(); i++) { + QString cur(entries.at(i).c_str()); + entryList.append(cur); + } + emit(gotGroupEntries(box, entryList)); +} \ No newline at end of file diff --git a/groundStation/gui/MicroCART/crazyflieworker.h b/groundStation/gui/MicroCART/crazyflieworker.h index 8b5ae498e..c3a93825f 100644 --- a/groundStation/gui/MicroCART/crazyflieworker.h +++ b/groundStation/gui/MicroCART/crazyflieworker.h @@ -2,12 +2,29 @@ #define CRAZYFLIEWORKER_H #include <QObject> +#include <fstream> +#include <sstream> +#include <vector> +#include <QStringList> #include "frontend_common.h" #include "frontend_param.h" #include "frontend_override.h" +#include "frontend_logfile.h" #include "setpoint.h" #include <QDebug> +struct toc_info { + int16_t id; + int8_t dataType; + std::string strGroup; + std::string strName; + float value; +}; + +struct toc_group { + std::string groupName; + std::vector<std::string> entryNames; +}; /** * @brief The crazyflieworker class @@ -25,6 +42,8 @@ public: signals: void gotParamValue(QString paramName, float value); + void gotParamGroups(QStringList paramGroupList); + void gotGroupEntries(int box, QStringList groupEntries); void connected(); void disconnected(); @@ -35,6 +54,8 @@ public slots: void sendAttSetpoint(); void sendAttRateSetpoint(); void getParamValue(QString paramName); + void setParamValue(QString paramName, double value); + void getGroupEntries(int box, QString gName); private: struct backend_conn * conn; @@ -42,9 +63,16 @@ private: Setpoint currAttitudeRateSetpoint; void sendAttitudeSetpoint(); void sendAttitudeRateSetpoint(); - struct frontend_param_data paramNameLookup(QString paramName); - - + std::string getLogFile(int type); + void loadParamIds(); + void loadLogIds(); + int findParamGroup(std::string gName); + int findLogGroup(std::string gName); + struct toc_info paramNameLookup(QString paramName); + QMap<QString, struct toc_info> paramIds; + QMap<QString, struct toc_info> logIds; + std::vector<struct toc_group> paramGroups; + std::vector<struct toc_group> logGroups; }; #endif // CRAZYFLIEWORKER_H diff --git a/groundStation/gui/MicroCART/mainwindow.cpp b/groundStation/gui/MicroCART/mainwindow.cpp index d62956482..50d2226d8 100644 --- a/groundStation/gui/MicroCART/mainwindow.cpp +++ b/groundStation/gui/MicroCART/mainwindow.cpp @@ -13,6 +13,7 @@ #include "trackerworker.h" #include "controlworker.h" +#include "crazyflieworker.h" #include "quaditem.h" #include "slotprocess.h" #include "qFlightInstruments.h" @@ -91,13 +92,35 @@ MainWindow::MainWindow(QWidget *parent) : connect(this, SIGNAL (setParamValue(QString, QString, float)), controlWorker, SLOT (setParamValue(QString, QString, float))); connect(this, SIGNAL (getNodeOutput(QString)), controlWorker, SLOT (getNodeOutput(QString))); + /* Create another work for the crazyflie communication */ + QThread * cfThread = new QThread(this); + CrazyflieWorker * crazyflieWorker = new CrazyflieWorker(); + crazyflieWorker->moveToThread(cfThread); + + /* connect signals for crazyflie worker */ + connect(crazyflieWorker, SIGNAL (gotParamGroups(QStringList)), this, SLOT (setParamGroups(QStringList))); + connect(ui->paramGroupComboBox, SIGNAL (currentIndexChanged(int)), this, SLOT (getGroupBoxChange(int))); + connect(ui->paramGroupComboBox_2, SIGNAL (currentIndexChanged(int)), this, SLOT (getGroupBox2Change(int))); + connect(ui->paramEntriesComboBox, SIGNAL (currentIndexChanged(int)), this, SLOT (getEntryBoxChange(int))); + connect(ui->paramEntriesComboBox_2, SIGNAL (currentIndexChanged(int)), this, SLOT (getEntryBoxChange2(int))); + connect(ui->pb_getParam, SIGNAL (clicked()), this, SLOT (on_pb_getParam_click())); + connect(ui->pb_setParam, SIGNAL (clicked()), this, SLOT (on_pb_setParam_click())); + connect(crazyflieWorker, SIGNAL (gotGroupEntries(int, QStringList)), this, SLOT (newGroupEntries(int, QStringList))); + connect(this, SIGNAL (getGroupEntries(int, QString)), crazyflieWorker, SLOT (getGroupEntries(int, QString))); + connect(this, SIGNAL (getParamValue(QString)), crazyflieWorker, SLOT (getParamValue(QString))); + connect(this, SIGNAL (setParamValue(QString, double)), crazyflieWorker, SLOT (setParamValue(QString, double))); + connect(crazyflieWorker, SIGNAL (gotParamValue(QString, float)), this, SLOT (displayParamValue(QString, float))); + /* Connect and disconnect from backend when signals emitted */ connect(workerStartTimer, SIGNAL (timeout()), trackerWorker, SLOT (connectBackend())); connect(workerStartTimer, SIGNAL (timeout()), controlWorker, SLOT (connectBackend())); + connect(workerStartTimer, SIGNAL (timeout()), crazyflieWorker, SLOT (connectBackend())); connect(this, SIGNAL (connectWorkers()), trackerWorker, SLOT (connectBackend())); connect(this, SIGNAL (connectWorkers()), controlWorker, SLOT (connectBackend())); + connect(this, SIGNAL (connectWorkers()), crazyflieWorker, SLOT (connectBackend())); connect(this, SIGNAL (disconnectWorkers()), trackerWorker, SLOT (disconnectBackend())); connect(this, SIGNAL (disconnectWorkers()), controlWorker, SLOT (disconnectBackend())); + connect(this, SIGNAL (disconnectWorkers()), crazyflieWorker, SLOT (disconnectBackend())); connect(backendProcess, SIGNAL (started()), this, SLOT (backendStarted())); connect(backendProcess, SIGNAL (errorOccurred(QProcess::ProcessError)), this, SLOT (backendError(QProcess::ProcessError))); @@ -111,6 +134,9 @@ MainWindow::MainWindow(QWidget *parent) : connect(trackerWorker, SIGNAL (connected()), this, SLOT (workerConnected())); connect(trackerWorker, SIGNAL (disconnected()), this, SLOT (workerDisconnected())); + connect(crazyflieWorker, SIGNAL (connected()), this, SLOT (workerConnected())); + connect(crazyflieWorker, SIGNAL (disconnected()), this, SLOT (workerDisconnected())); + /* Connect refresh button and refresh timer to tracker worker */ connect(trackerTimer, SIGNAL(timeout()), this, SLOT(updatePosAtt())); // connect(ui->pbRefresh, SIGNAL (clicked()), this, SLOT (updatePosAtt())); @@ -125,11 +151,19 @@ MainWindow::MainWindow(QWidget *parent) : trackerTimer->start(100); workerThread->start(); cwThread->start(); + cfThread->start(); matlabProcess->start(); /* Connect the setpointlist to the model */ // ui->setpointList->setModel(setpointList); + ui->pb_getParam->setEnabled(false); + ui->pb_setParam->setEnabled(false); + ui->setValueSpin->setMaximum(10000.00); + ui->setValueSpin->setMinimum(-10000.00); + ui->setValueSpin->setSingleStep(0.01); + ui->setValueSpin->setValue(0); + /* Connect various things that can result in sending setpoints */ // connect(ui->pbSendSetpoint, SIGNAL (clicked()), this, SLOT (sendSetpoints())); // connect(ui->setpointList, SIGNAL (doubleClicked(QModelIndex)), this, SLOT (sendSelectedSetpoint())); @@ -143,7 +177,6 @@ MainWindow::MainWindow(QWidget *parent) : scriptProcess->setProgram(scriptsDir.filePath(scripts[i])); connect(action, SIGNAL (triggered()), scriptProcess, SLOT (startProcess())); } - } MainWindow::~MainWindow() @@ -274,6 +307,98 @@ void MainWindow::newNodes(QStringList blocks) // this->ui->noGraphWarningLine->setVisible(false); } +void MainWindow::setParamGroups(QStringList groupNames) { + ui->paramGroupComboBox->addItem(""); + ui->paramGroupComboBox->addItems(groupNames); + ui->paramGroupComboBox_2->addItem(""); + ui->paramGroupComboBox_2->addItems(groupNames); +} + +void MainWindow::getGroupBoxChange(int index) { + // for(int i = 0; i < ui->paramGroupComboBox->count(); i++) { + // ui->paramEntriesComboBox->removeItem(i); + // } + ui->paramEntriesComboBox->clear(); + QString qStrGroup = ui->paramGroupComboBox->itemText(index); + std::string check = qStrGroup.toStdString(); + ui->valueVallabel->clear(); + if(!check.compare("")) { + ui->pb_getParam->setEnabled(false); + } + else { + emit(getGroupEntries(1, qStrGroup)); + } +} + +void MainWindow::getGroupBox2Change(int index) { + // for(int i = 0; i < ui->paramGroupComboBox->count(); i++) { + // ui->paramEntriesComboBox->removeItem(i); + // } + ui->paramEntriesComboBox_2->clear(); + QString qStrGroup = ui->paramGroupComboBox_2->itemText(index); + std::string check = qStrGroup.toStdString(); + if(!check.compare("")) { + ui->pb_setParam->setEnabled(false); + } + else { + emit(getGroupEntries(2, qStrGroup)); + } +} + +void MainWindow::getEntryBoxChange(int index) { + QString qStrGroup = ui->paramEntriesComboBox->itemText(index); + std::string check = qStrGroup.toStdString(); + ui->valueVallabel->clear(); + if(!check.compare("")) { + ui->pb_getParam->setEnabled(false); + } + else { + ui->pb_getParam->setEnabled(true); + } +} + +void MainWindow::getEntryBoxChange2(int index) { + QString qStrGroup = ui->paramEntriesComboBox_2->itemText(index); + std::string check = qStrGroup.toStdString(); + if(!check.compare("")) { + ui->pb_setParam->setEnabled(false); + } + else { + ui->pb_setParam->setEnabled(true); + } +} + +void MainWindow::newGroupEntries(int box, QStringList entries) { + if(box == 1) { + ui->paramEntriesComboBox->addItem(""); + ui->paramEntriesComboBox->addItems(entries); + } + else { + ui->paramEntriesComboBox_2->addItem(""); + ui->paramEntriesComboBox_2->addItems(entries); + } +} + +void MainWindow::on_pb_getParam_click() { + ui->valueVallabel->clear(); + QString group = ui->paramGroupComboBox->currentText(); + QString entry = ui->paramEntriesComboBox->currentText(); + QString key = group + "." + entry; + emit(getParamValue(key)); +} + +void MainWindow::on_pb_setParam_click() { + QString group = ui->paramGroupComboBox_2->currentText(); + QString entry = ui->paramEntriesComboBox_2->currentText(); + QString key = group + "." + entry; + double value = ui->setValueSpin->value(); + emit(setParamValue(key, value)); +} + +void MainWindow::displayParamValue(QString key, float value) { + ui->valueVallabel->setNum(value); +} + void MainWindow::newConstantBlocks(QStringList blocks) { // ui->xSetpointSelect->clear(); diff --git a/groundStation/gui/MicroCART/mainwindow.h b/groundStation/gui/MicroCART/mainwindow.h index 4e24931aa..a79eea751 100644 --- a/groundStation/gui/MicroCART/mainwindow.h +++ b/groundStation/gui/MicroCART/mainwindow.h @@ -23,9 +23,12 @@ signals: void connectWorkers(); void disconnectWorkers(); void getParamValue(QString node, QString param); + void getParamValue(QString key); void getNodeOutput(QString node); void setParamValue(QString node, QString param, float value); + void setParamValue(QString key, double value); void getPosAttFromBackend(); + void getGroupEntries(int box, QString gName); private slots: void on_pbStart_clicked(); @@ -45,6 +48,11 @@ private slots: void newParamValue(QString node, QString param, float val); void newNodeOutput(QString node, float output); void newConstantBlocks(QStringList blocks); + void newGroupEntries(int box, QStringList entries); + + void on_pb_getParam_click(); + + void on_pb_setParam_click(); void on_paramSelect_currentIndexChanged(const QString &arg1); @@ -91,6 +99,13 @@ private slots: void workerConnected(); void workerDisconnected(); + void setParamGroups(QStringList groupNames); + void getGroupBoxChange(int index); + void getGroupBox2Change(int index); + void displayParamValue(QString param, float value); + void getEntryBoxChange(int index); + void getEntryBoxChange2(int index); + private: Ui::MainWindow *ui; QStandardItemModel * setpointList; diff --git a/groundStation/gui/MicroCART/mainwindow.ui b/groundStation/gui/MicroCART/mainwindow.ui index ceea28e08..6a96b514f 100644 --- a/groundStation/gui/MicroCART/mainwindow.ui +++ b/groundStation/gui/MicroCART/mainwindow.ui @@ -18,7 +18,7 @@ <item> <widget class="QTabWidget" name="tabWidget"> <property name="currentIndex"> - <number>3</number> + <number>1</number> </property> <widget class="QWidget" name="backend"> <attribute name="title"> @@ -119,6 +119,212 @@ <attribute name="title"> <string>Param</string> </attribute> + <widget class="QComboBox" name="paramGroupComboBox"> + <property name="geometry"> + <rect> + <x>420</x> + <y>100</y> + <width>201</width> + <height>25</height> + </rect> + </property> + </widget> + <widget class="QComboBox" name="paramEntriesComboBox"> + <property name="geometry"> + <rect> + <x>420</x> + <y>150</y> + <width>201</width> + <height>25</height> + </rect> + </property> + </widget> + <widget class="QLabel" name="groupLabel"> + <property name="geometry"> + <rect> + <x>350</x> + <y>100</y> + <width>54</width> + <height>31</height> + </rect> + </property> + <property name="text"> + <string>Group:</string> + </property> + </widget> + <widget class="QLabel" name="getParamLabel"> + <property name="geometry"> + <rect> + <x>480</x> + <y>40</y> + <width>71</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Get Param</string> + </property> + </widget> + <widget class="QLabel" name="label"> + <property name="geometry"> + <rect> + <x>350</x> + <y>150</y> + <width>54</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Entry:</string> + </property> + </widget> + <widget class="Line" name="line"> + <property name="geometry"> + <rect> + <x>0</x> + <y>279</y> + <width>1111</width> + <height>31</height> + </rect> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + <widget class="QLabel" name="setParamLabel"> + <property name="geometry"> + <rect> + <x>480</x> + <y>310</y> + <width>71</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Set Param</string> + </property> + </widget> + <widget class="QLabel" name="valueLabel"> + <property name="geometry"> + <rect> + <x>350</x> + <y>240</y> + <width>54</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Value:</string> + </property> + </widget> + <widget class="QLabel" name="valueVallabel"> + <property name="geometry"> + <rect> + <x>420</x> + <y>240</y> + <width>201</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string/> + </property> + </widget> + <widget class="QLabel" name="groupLabel_set"> + <property name="geometry"> + <rect> + <x>350</x> + <y>360</y> + <width>54</width> + <height>31</height> + </rect> + </property> + <property name="text"> + <string>Group:</string> + </property> + </widget> + <widget class="QLabel" name="label_5"> + <property name="geometry"> + <rect> + <x>350</x> + <y>400</y> + <width>54</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Entry:</string> + </property> + </widget> + <widget class="QLabel" name="valueLabel_2"> + <property name="geometry"> + <rect> + <x>350</x> + <y>450</y> + <width>54</width> + <height>17</height> + </rect> + </property> + <property name="text"> + <string>Value:</string> + </property> + </widget> + <widget class="QComboBox" name="paramGroupComboBox_2"> + <property name="geometry"> + <rect> + <x>420</x> + <y>360</y> + <width>201</width> + <height>25</height> + </rect> + </property> + </widget> + <widget class="QComboBox" name="paramEntriesComboBox_2"> + <property name="geometry"> + <rect> + <x>420</x> + <y>400</y> + <width>201</width> + <height>25</height> + </rect> + </property> + </widget> + <widget class="QPushButton" name="pb_getParam"> + <property name="geometry"> + <rect> + <x>480</x> + <y>200</y> + <width>80</width> + <height>25</height> + </rect> + </property> + <property name="text"> + <string>Get Param</string> + </property> + </widget> + <widget class="QPushButton" name="pb_setParam"> + <property name="geometry"> + <rect> + <x>480</x> + <y>500</y> + <width>80</width> + <height>25</height> + </rect> + </property> + <property name="text"> + <string>Set Param</string> + </property> + </widget> + <widget class="QDoubleSpinBox" name="setValueSpin"> + <property name="geometry"> + <rect> + <x>470</x> + <y>450</y> + <width>111</width> + <height>26</height> + </rect> + </property> + </widget> </widget> <widget class="QWidget" name="controller"> <attribute name="title"> @@ -489,7 +695,7 @@ </item> <item row="1" column="1"> <widget class="QLabel" name="currRActual"> - <property name="text"> + <property name="text"> <string>N/A</string> </property> </widget> @@ -557,7 +763,7 @@ <x>0</x> <y>0</y> <width>1186</width> - <height>28</height> + <height>22</height> </rect> </property> <widget class="QMenu" name="menuScripts"> @@ -578,6 +784,13 @@ <widget class="QStatusBar" name="statusBar"/> </widget> <layoutdefault spacing="6" margin="11"/> + <customwidgets> + <customwidget> + <class>QCustomPlot</class> + <extends>QWidget</extends> + <header>qcustomplot.h</header> + </customwidget> + </customwidgets> <resources/> <connections/> </ui> diff --git a/groundStation/src/backend/param.c b/groundStation/src/backend/param.c index bb0dc1a9d..b31241cef 100644 --- a/groundStation/src/backend/param.c +++ b/groundStation/src/backend/param.c @@ -129,8 +129,10 @@ ssize_t EncodeResponseParam( data[RESP_BLOCK_ID_L] = 0; data[RESP_BLOCK_ID_H] = 0; - data[RESP_PARAM_ID_L] = msg[1]; - data[RESP_PARAM_ID_H] = 0; + //data[RESP_PARAM_ID_L] = msg[1]; + //data[RESP_PARAM_ID_H] = msg[2]; + + memcpy(&data[RESP_PARAM_ID_L], &msg[1], sizeof(uint16_t)); float fl = -1; @@ -138,70 +140,70 @@ ssize_t EncodeResponseParam( case 8: { uint8_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(uint8_t)); + memcpy(&pvalue, &msg[4], sizeof(uint8_t)); fl = pvalue; break; } case 9: { uint16_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(uint16_t)); + memcpy(&pvalue, &msg[4], sizeof(uint16_t)); fl = pvalue; break; } case 10: { uint32_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(uint32_t)); + memcpy(&pvalue, &msg[4], sizeof(uint32_t)); fl = pvalue; break; } case 11: { uint64_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(uint64_t)); + memcpy(&pvalue, &msg[4], sizeof(uint64_t)); fl = pvalue; break; } case 0: { int8_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(int8_t)); + memcpy(&pvalue, &msg[4], sizeof(int8_t)); fl = pvalue; break; } case 1: { int16_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(int16_t)); + memcpy(&pvalue, &msg[4], sizeof(int16_t)); fl = pvalue; break; } case 2: { int32_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(int32_t)); + memcpy(&pvalue, &msg[4], sizeof(int32_t)); fl = pvalue; break; } case 3: { int64_t pvalue; - memcpy(&pvalue, &msg[2], sizeof(int64_t)); + memcpy(&pvalue, &msg[4], sizeof(int64_t)); fl = pvalue; break; } case 6: { float pvalue; - memcpy(&pvalue, &msg[2], sizeof(float)); + memcpy(&pvalue, &msg[4], sizeof(float)); fl = pvalue; break; } case 7: { double pvalue; - memcpy(&pvalue, &msg[2], sizeof(double)); + memcpy(&pvalue, &msg[4], sizeof(double)); fl = pvalue; break; } @@ -231,9 +233,12 @@ int DecodeResponseParam( return -1; } + uint16_t id; + memcpy(&id, &data[RESP_PARAM_ID_L], sizeof(uint16_t)); + return snprintf(msg, max_len, "getparam %" PRId16 " %" PRId16 " %f\n", BytesTo16(data[RESP_BLOCK_ID_L], data[RESP_BLOCK_ID_H]), - BytesTo16(data[RESP_PARAM_ID_L], data[RESP_PARAM_ID_H]), + id, BytesToFloat(data[RESP_VAL_1], data[RESP_VAL_2], data[RESP_VAL_3], data[RESP_VAL_4])); } -- GitLab