diff --git a/BLDC_Logger.pro b/BLDC_Logger.pro index c8963d2..d2a4e97 100644 --- a/BLDC_Logger.pro +++ b/BLDC_Logger.pro @@ -11,6 +11,7 @@ QT += core QT += gui QT += printsupport QT += multimedia +QT += serialport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -18,34 +19,56 @@ TARGET = BLDC_Logger CONFIG += console CONFIG -= app_bundle -LIBS += -lopencv_core -lopencv_imgproc -lopencv_highgui \ - -lopencv_ml -lopencv_video -lopencv_features2d \ - -lopencv_calib3d -lopencv_objdetect -lopencv_contrib \ - -lopencv_legacy -lopencv_flann +macx: QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 + +win32 { + OPENCV_PATH = D:/Dev/Tools/opencv2/sources-build/install + INCLUDEPATH += $${OPENCV_PATH}/include + LIBS += -L$${OPENCV_PATH}/x64/mingw/lib -lopencv_core2411.dll -lopencv_highgui2411.dll +} + +macx { + OPENCV_PATH = /Users/admin/Dev/opencv-2.4.11-build/install + INCLUDEPATH += $${OPENCV_PATH}/include + LIBS += -L$${OPENCV_PATH}/lib -lopencv_core -lopencv_highgui +} + +unix:!macx { + LIBS += -lopencv_core -lopencv_imgproc -lopencv_highgui \ + -lopencv_ml -lopencv_video -lopencv_features2d \ + -lopencv_calib3d -lopencv_objdetect -lopencv_contrib \ + -lopencv_legacy -lopencv_flann +} TEMPLATE = app SOURCES += main.cpp \ packetinterface.cpp \ - serialport.cpp \ logger.cpp \ - consolereader.cpp \ utility.cpp \ MatToQImage.cpp \ qcustomplot.cpp \ videocoder.cpp \ frameplotter.cpp \ - framegrabber.cpp + framegrabber.cpp \ + argprocessor.cpp HEADERS += \ packetinterface.h \ - serialport.h \ logger.h \ - consolereader.h \ utility.h \ MatToQImage.h \ qcustomplot.h \ videocoder.h \ frameplotter.h \ - framegrabber.h + framegrabber.h \ + argprocessor.h + +win32 { + SOURCES += consolereader_win.cpp + HEADERS += consolereader_win.h +} unix { + SOURCES += consolereader.cpp + HEADERS += consolereader.h +} diff --git a/BLDC_Logger.pro.user b/BLDC_Logger.pro.user new file mode 100644 index 0000000..1e2beda --- /dev/null +++ b/BLDC_Logger.pro.user @@ -0,0 +1,316 @@ + + + + + + EnvironmentId + {9c9a211d-6c51-48b2-b120-85056f1b4a10} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop Qt 5.5.1 MinGW 32bit + Desktop Qt 5.5.1 MinGW 32bit + {033c2465-0655-4ba1-b4ce-6e508baabb5e} + 0 + 0 + 0 + + D:/Projects/builds/build-BLDC_Logger-Desktop_Qt_5_5_1_MinGW_32bit-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + D:/Projects/builds/build-BLDC_Logger-Desktop_Qt_5_5_1_MinGW_32bit-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + D:/Projects/builds/build-BLDC_Logger-Desktop_Qt_5_5_1_MinGW_32bit-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + BLDC_Logger + + Qt4ProjectManager.Qt4RunConfiguration:D:/Projects/bldc-logger/BLDC_Logger.pro + true + + BLDC_Logger.pro + false + true + + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/argprocessor.cpp b/argprocessor.cpp new file mode 100644 index 0000000..e0ab389 --- /dev/null +++ b/argprocessor.cpp @@ -0,0 +1,48 @@ +#include "argprocessor.h" + +#include + +ArgProcessor::ArgProcessor(QObject *parent) : QObject(parent) +{ + QTextStream streamOut(stdout); + QTextStream streamIn(stdin); +#ifdef Q_OS_WIN + QString defaultPort_ = "COM3"; +#elif defined(Q_OS_MAC) + QString defaultPort_ = "/dev/tty.usbmodem261"; +#else + QString defaultPort_ = "/dev/ttyACM0"; +#endif + streamOut << "Port (default is " + defaultPort_ + "): "; + streamOut.flush(); + mPort = streamIn.readLine(); + if(mPort.isEmpty()) { + mPort = defaultPort_; + } + + streamOut << "Camera index (default is 0): "; + streamOut.flush(); + mCamera = streamIn.readLine().toInt(); + + streamOut << "Camera width (default is 1280): "; + streamOut.flush(); + mWidth = streamIn.readLine().toInt(); + if(mWidth == 0) { + mWidth = 1280; + } + + streamOut << "Camera height (default is 720): "; + streamOut.flush(); + mHeight = streamIn.readLine().toInt(); + if(mHeight == 0) { + mHeight = 720; + } + + streamOut << "Camera fps (default is 25.0): "; + streamOut.flush(); + mFps = streamIn.readLine().toInt(); + if(mFps == 0) { + mFps = 25.0; + } +} + diff --git a/argprocessor.h b/argprocessor.h new file mode 100644 index 0000000..42ddacd --- /dev/null +++ b/argprocessor.h @@ -0,0 +1,52 @@ +#ifndef ARGPROCESSOR_H +#define ARGPROCESSOR_H + +#include + +class ArgProcessor : public QObject +{ + Q_OBJECT +public: + explicit ArgProcessor(QObject *parent = 0); + + QString getPort() const; + int getCamera() const; + int getWidth() const; + int getHeight() const; + double getFps() const; + +private: + QString mPort; + int mCamera; + int mWidth; + int mHeight; + double mFps; + +}; + +inline QString ArgProcessor::getPort() const +{ + return mPort; +} + +inline int ArgProcessor::getCamera() const +{ + return mCamera; +} + +inline int ArgProcessor::getWidth() const +{ + return mWidth; +} + +inline int ArgProcessor::getHeight() const +{ + return mHeight; +} + +inline double ArgProcessor::getFps() const +{ + return mFps; +} + +#endif // ARGPROCESSOR_H diff --git a/consolereader.cpp b/consolereader.cpp index f2a8c01..9de5978 100644 --- a/consolereader.cpp +++ b/consolereader.cpp @@ -16,13 +16,14 @@ */ #include "consolereader.h" + #include #include // Provides STDIN_FILENO ConsoleReader::ConsoleReader(QObject *parent) : QObject(parent) { - notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read); + notifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, this); connect(notifier, SIGNAL(activated(int)), this, SLOT(text())); } diff --git a/consolereader_win.cpp b/consolereader_win.cpp new file mode 100644 index 0000000..aa23ec7 --- /dev/null +++ b/consolereader_win.cpp @@ -0,0 +1,37 @@ +#include "consolereader_win.h" + +#include + +#include +#include + +ConsoleReader::ConsoleReader(QObject *parent) : QThread(parent) +{ + start(); +} + +ConsoleReader::~ConsoleReader() +{ + quit(); + wait(); +} + +void ConsoleReader::run() +{ + QTimer timer; + connect(&timer, SIGNAL(timeout()), this, SLOT(onCheckStdin()), Qt::DirectConnection); + timer.start(100); + QThread::exec(); +} + +void ConsoleReader::onCheckStdin() +{ + QTextStream stream(stdin); + + // Do we have a new line to be read ? + QString line = stream.readLine(); + if (!line.isEmpty()) + { + emit textReceived(line); + } +} diff --git a/consolereader_win.h b/consolereader_win.h new file mode 100644 index 0000000..3bce017 --- /dev/null +++ b/consolereader_win.h @@ -0,0 +1,25 @@ +#ifndef CONSOLEREADER_H +#define CONSOLEREADER_H + +#include + +class ConsoleReader : public QThread +{ + Q_OBJECT + +public: + explicit ConsoleReader(QObject *parent = 0); + ~ConsoleReader(); + +signals: + void textReceived(QString message); + +protected: + void run(); + +private slots: + void onCheckStdin(); + +}; + +#endif // CONSOLEREADER_H diff --git a/framegrabber.cpp b/framegrabber.cpp index e24e2e5..de3f0d1 100644 --- a/framegrabber.cpp +++ b/framegrabber.cpp @@ -14,16 +14,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ - #include "framegrabber.h" -#include + +#include FrameGrabber::FrameGrabber(int w, int h, int fps, int dev, QObject *parent) : QThread(parent) { mAbort = false; - mVideoCap.open(dev); + qDebug().nospace() << "Opening camera " << dev << "..."; + if(mVideoCap.open(dev)) { + qDebug() << "ok"; + } else { + qWarning() << "Failed!"; + } mVideoCap.set(CV_CAP_PROP_FRAME_WIDTH, w); mVideoCap.set(CV_CAP_PROP_FRAME_HEIGHT, h); @@ -66,4 +71,19 @@ void FrameGrabber::run() mLatestFrame = MatToQImage(mFrameMat); } } + + // working solution for some cameras +// while (mVideoCap.isOpened() && !mAbort) { +// int CAMERA_CHECK_ITERATIONS = 40; +// mVideoCap >> mFrameMat; +// if ( mFrameMat.total() > 0 ) { +// QMutexLocker lock(&mMutex); +// mLatestFrame = MatToQImage(mFrameMat); +// } else { +// qWarning() << "::: Accessing camera :::"; +// if ( CAMERA_CHECK_ITERATIONS > 0 ) CAMERA_CHECK_ITERATIONS--; +// if ( CAMERA_CHECK_ITERATIONS < 0 ) break; +// } +// } + } diff --git a/logger.cpp b/logger.cpp index 331e7e9..3207892 100644 --- a/logger.cpp +++ b/logger.cpp @@ -16,17 +16,22 @@ */ #include "logger.h" + #include #include +#include "argprocessor.h" + Logger::Logger(QObject *parent) : QObject(parent) { - mPort = new SerialPort(this); + ArgProcessor argProcessor; + mPort = new QSerialPort(this); mPacketInterface = new PacketInterface(this); - mValueFile = new QFile("Data/BLDC_Values"); - mPrintFile = new QFile("Data/BLDC_Print"); + QDir().mkpath(qApp->applicationDirPath() + "/Data"); + mValueFile = new QFile(qApp->applicationDirPath() + "/Data/BLDC_Values"); + mPrintFile = new QFile(qApp->applicationDirPath() + "/Data/BLDC_Print"); mValueFile->open(QIODevice::WriteOnly | QIODevice::Text); mPrintFile->open(QIODevice::WriteOnly | QIODevice::Text); @@ -34,20 +39,41 @@ Logger::Logger(QObject *parent) : mValueStream = new QTextStream(mValueFile); mPrintStream = new QTextStream(mPrintFile); - mPort->openPort("/dev/rfcomm0"); +//<<<<<<< HEAD + qDebug().nospace() << "Opening port " << argProcessor.getPort() << "..."; + mPort->setPortName(argProcessor.getPort()); + if(mPort->open(QIODevice::ReadWrite)) { + qDebug() << "ok"; + + mPort->setBaudRate(QSerialPort::Baud115200); + mPort->setDataBits(QSerialPort::Data8); //8 bits + mPort->setParity(QSerialPort::NoParity); //no parity + mPort->setStopBits(QSerialPort::OneStop); //1 stop bit + mPort->setFlowControl(QSerialPort::NoFlowControl); //no flow control + } else { + qWarning() << "Failed!"; + } +//======= +// mPort->openPort("/dev/rfcomm0"); +//>>>>>>> upstream/master // Video - mVidW = 1280; - mVidH = 720; - mVidFps = 25.0; + mVidW = argProcessor.getWidth(); + mVidH = argProcessor.getHeight(); + mVidFps = argProcessor.getFps(); mFAudioSamp = 44100; - mFrameGrabber = new FrameGrabber(mVidW, mVidH, mVidFps, 0, this); + mFrameGrabber = new FrameGrabber(mVidW, mVidH, mVidFps, argProcessor.getCamera(), this); mFrameGrabber->start(QThread::InheritPriority); mPlotter = new FramePlotter(this); mPlotter->start(QThread::InheritPriority); - mCoder = new VideoCoder(mVidW, mVidH, mVidFps, "Data/v_video.avi", this); +#ifdef Q_OS_MAC + QString ext = ".mov"; +#else + QString ext = ".avi"; +#endif + mCoder = new VideoCoder(mVidW, mVidH, mVidFps, QString(qApp->applicationDirPath() + "/Data/v_video" + ext).toLatin1().constData(), this); mCoder->start(QThread::InheritPriority); // Audio recording @@ -55,7 +81,7 @@ Logger::Logger(QObject *parent) : mAudio = 0; if (QAudioDeviceInfo::availableDevices(QAudio::AudioInput).size() > 0) { - mAudioFile.setFileName("Data/v_audio.raw"); + mAudioFile.setFileName(qApp->applicationDirPath() + "/Data/v_audio.raw"); mAudioFile.open(QIODevice::WriteOnly | QIODevice::Truncate); QAudioFormat format; @@ -73,10 +99,13 @@ Logger::Logger(QObject *parent) : format = info.nearestFormat(format); } + + mAudio = new QAudioInput(format, this); mAudio->setNotifyInterval(1000 / mVidFps); mAudio->start(&mAudioFile); } else { + qWarning() << "No audio input detected!"; mTimer = new QTimer(this); mTimer->setInterval(1000 / mVidFps); mTimer->start(); @@ -87,12 +116,10 @@ Logger::Logger(QObject *parent) : connect(mConsoleReader, SIGNAL(textReceived(QString)), this, SLOT(consoleLineReceived(QString))); - connect(mPort, SIGNAL(serial_data_available()), + connect(mPort, SIGNAL(readyRead()), this, SLOT(serialDataAvailable())); - - if (mTimer != 0) { - connect(mTimer, SIGNAL(timeout()), this, SLOT(timerSlot())); - } + connect(mPort, SIGNAL(error(QSerialPort::SerialPortError)), + this, SLOT(serialPortError(QSerialPort::SerialPortError))); if (mAudio != 0) { connect(mAudio, SIGNAL(notify()), @@ -101,6 +128,8 @@ Logger::Logger(QObject *parent) : // Lower the volume to avoid clipping. This seems to be passed to // pulseaudio. mAudio->setVolume(0.1); + } else { + connect(mTimer, SIGNAL(timeout()), this, SLOT(audioNotify())); } connect(mPacketInterface, SIGNAL(dataToSend(QByteArray&)), @@ -127,17 +156,19 @@ Logger::~Logger() mFrameGrabber->stopAndWait(); mPlotter->stopAndWait(); mCoder->stopAndWait(); + mPort->close(); if (mAudio != 0) { mAudioFile.close(); delete mAudio; - rawToWav("Data/v_audio.wav", "Data/v_audio.raw", mFAudioSamp); + rawToWav(QString(qApp->applicationDirPath() + "/Data/v_audio.wav").toLatin1().constData(), QString(qApp->applicationDirPath() + "/Data/v_audio.raw").toLatin1().constData(), mFAudioSamp); } delete mValueStream; delete mPrintStream; delete mValueFile; delete mPrintFile; + delete mPort; } void Logger::consoleLineReceived(QString line) @@ -177,6 +208,35 @@ void Logger::serialDataAvailable() } } +void Logger::serialPortError(QSerialPort::SerialPortError error) +{ + QString message; + switch (error) { + case QSerialPort::NoError: + break; + case QSerialPort::DeviceNotFoundError: + message = tr("Device not found"); + break; + case QSerialPort::OpenError: + message = tr("Can't open device"); + break; + case QSerialPort::NotOpenError: + message = tr("Not open error"); + break; + default: + message = QString::number(error); + break; + } + + if(!message.isEmpty()) { + if(mPort->isOpen()) { + mPort->close(); + } + qWarning() << "Serial port error: " << message; + } +} + + void Logger::timerSlot() { mPacketInterface->getValues(); @@ -185,7 +245,7 @@ void Logger::timerSlot() void Logger::packetDataToSend(QByteArray &data) { if (mPort->isOpen()) { - mPort->writeData(data.data(), data.size()); + mPort->write(data); } } diff --git a/logger.h b/logger.h index ff4a523..cc97d91 100644 --- a/logger.h +++ b/logger.h @@ -21,17 +21,26 @@ #include #include #include -#include + #include #include + +#include + #include "MatToQImage.h" -#include "serialport.h" #include "packetinterface.h" #include "qcustomplot.h" #include "videocoder.h" #include "frameplotter.h" #include "framegrabber.h" +#ifdef Q_OS_WIN +#include +#else +#include +#endif + + class Logger : public QObject { Q_OBJECT @@ -47,6 +56,7 @@ public slots: private slots: void consoleLineReceived(QString line); void serialDataAvailable(); + void serialPortError(QSerialPort::SerialPortError error); void timerSlot(); void packetDataToSend(QByteArray &data); void mcValuesReceived(MC_VALUES values); @@ -57,7 +67,7 @@ private slots: void audioNotify(); private: - SerialPort *mPort; + QSerialPort *mPort; QTimer *mTimer; PacketInterface *mPacketInterface; QFile *mValueFile; diff --git a/packetinterface.h b/packetinterface.h index 14389a8..651c811 100644 --- a/packetinterface.h +++ b/packetinterface.h @@ -24,6 +24,10 @@ #include #include "datatypes.h" +#ifdef Q_OS_WIN +#include "stdint.h" +#endif + class PacketInterface : public QObject { Q_OBJECT diff --git a/resources/mac/qt.conf b/resources/mac/qt.conf new file mode 100644 index 0000000..b297974 --- /dev/null +++ b/resources/mac/qt.conf @@ -0,0 +1,2 @@ +[Paths] +Plugins = ../Plugins \ No newline at end of file diff --git a/videocoder.cpp b/videocoder.cpp index afbc53e..ffb1a55 100644 --- a/videocoder.cpp +++ b/videocoder.cpp @@ -26,10 +26,20 @@ VideoCoder::VideoCoder(int w, int h, double fps, const char *file, QObject *pare mFrameReady = false; cv::Size S = cv::Size(w, h); -// mVideoWriter.open(file, CV_FOURCC('H','2','6','4'), fps, S); +#ifdef Q_OS_WIN + // -1 open dialog with codec manual choose + mVideoWriter.open(file, -1, fps, S, true); +#elif defined(Q_OS_MAC) + mVideoWriter.open(file, CV_FOURCC('m', 'p', '4', 'v'), fps, S); +#else mVideoWriter.open(file, CV_FOURCC('X','V','I','D'), fps, S); +#endif +// mVideoWriter.open(file, CV_FOURCC('H','2','6','4'), fps, S); // mVideoWriter.open(file, CV_FOURCC('M','J','P','G'), fps, S); // mVideoWriter.open(file, CV_FOURCC('I','Y','U','V'), fps, S); + if(!mVideoWriter.isOpened()) { + qWarning() << "Can't open video writer" << file; + } } void VideoCoder::setNextFrame(QImage img)