From 47d9be6e3457908a874b20217728a2bbae1c83a4 Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Mon, 30 Jan 2023 23:06:46 +0100 Subject: [PATCH] adding simulation device --- Makefile | 2 +- video.cc | 2 + videodev-simulation.cc | 253 +++++++++++++++++++++++++++++++++++++++++ videodev-simulation.h | 77 +++++++++++++ videodev.h | 2 + 5 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 videodev-simulation.cc create mode 100644 videodev-simulation.h diff --git a/Makefile b/Makefile index a1ae7d6..f7b5c44 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ APP = simpleskycam OBJECTS := $(OBJECTS) gui.oo main.oo error.oo \ video.oo videoframe.oo \ - videodev.oo videodev-v4l2.oo videodev-dumpfile.oo \ + videodev.oo videodev-v4l2.oo videodev-dumpfile.oo videodev-simulation.oo \ convert.oo filter.oo detect.oo histogram.oo pid.oo \ posctl.oo json.oo configuration.oo ser.oo dng.oo debayer.oo DISTNAME=simpleskycam-$(VERSION) diff --git a/video.cc b/video.cc index 3f2799b..634610c 100644 --- a/video.cc +++ b/video.cc @@ -303,6 +303,7 @@ void cb_video_btnrefreshlist (GtkWidget *widget, gpointer data) { #ifdef USE_SVBONY VideoDev_SVBCam vdef3; vdef3.GetDeviceList(&devlist); #endif + VideoDev_Simulation vdef4; vdef4.GetDeviceList(&devlist); for (iter = devlist.begin(); iter != devlist.end(); iter++) { gtk_list_store_insert_with_values(GTK_LIST_STORE(model), NULL, -1, @@ -349,6 +350,7 @@ void cb_video_btnrec (GtkWidget *widget, gpointer data) { else if (driver.compare("SVBCAM") == 0) videodev = new VideoDev_SVBCam; #endif else if (driver.compare("VIDEODUMP") == 0) videodev = new VideoDev_Dumpfile; + else if (driver.compare("SIMULATION") == 0) videodev = new VideoDev_Simulation; else videodev = new VideoDev; std::string format = gtk_entry_get_text(GTK_ENTRY(cbfmtentry)); diff --git a/videodev-simulation.cc b/videodev-simulation.cc new file mode 100644 index 0000000..a6a40c0 --- /dev/null +++ b/videodev-simulation.cc @@ -0,0 +1,253 @@ +/************************************************************************************ + * videodev-simulation: + * creates an black screen with an small white circle at a simulated movement + * needed for testing the PID functionality + * + * This is needed only for debugging. + ************************************************************************************/ + +#include +#include +#include +#include + + +#include "convert.h" +#include "configuration.h" +#include "videodev-simulation.h" + +Simulation simulation; +gpointer simulation_threadprocess_wrapper (gpointer data); + +VideoDev_Simulation::VideoDev_Simulation() { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + w = 1920; + h = 1080; + inframe = NULL; + simulation_thread = NULL; +}; + + +VideoDev_Simulation::~VideoDev_Simulation() { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + if (inframe != NULL) Close(); + inframe = NULL; +} + + + +/* + * searchs in the given path for any videodump files and present them as + * video device. + */ +int VideoDev_Simulation::GetDeviceList(std::list *list) { + list->push_back("SIMULATION"); + return 1; +} + + + +/* + * Open Device + * prepare the buffer, InitMMAP and read all controls + */ +int VideoDev_Simulation::Open() { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + if (inframe != NULL) Close(); + + conf_width = w; + conf_height = h; + conf_format = convert_from_pixelformat (V4L2_PIX_FMT_RGB24); + + simulation_thread = g_thread_new("Simulation", simulation_threadprocess_wrapper, NULL); + + inframe = (unsigned char *) malloc (w * h * 3); + + return VDEV_STATUS_OK; +}; + + +/* + * Close Device + * Free videobuffer + */ +int VideoDev_Simulation::Close() { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + if (inframe != NULL) { + free (inframe); + inframe = NULL; + } + + return VDEV_STATUS_OK; +}; + + + +/***************************************************************************************************** + * VideoGrabbing + */ + + +/* + * send the start capture signal to the cam + */ +int VideoDev_Simulation::CaptureStart() { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + if (inframe != NULL) Close(); + if (Open() != VDEV_STATUS_OK) return VDEV_STATUS_ERROR; + ConvertStart(&cdata, V4L2_PIX_FMT_RGB24); + + return VDEV_STATUS_OK; +}; + + +int VideoDev_Simulation::CaptureStop() { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + if (inframe != NULL) Close(); + ConvertStop(&cdata, V4L2_PIX_FMT_RGB24); + return VDEV_STATUS_OK; +}; + + +/* + * try to grab one frame and convert it into RGB32. + * If something goes wrong return an error code. + * Return code VDEV_STATUS_AGAIN is not an error. There was no video image ready to read. + */ +#define SIMULATION_SIZE 15 +int VideoDev_Simulation::Grab(VideoFrame *vf) { + int posx, posy, x ,y; + double r, a; + + memset (inframe, 0x0, w*h*3); + simulation.GetPos(&posx, &posy); + + for (r = 1; r < SIMULATION_SIZE; r++) for (a = 0; a < M_PI * 2.0; a += 0.1) { + x = posx + (sin(a) * r); + y = posy + (cos(a) * r); + if (x >= 0 && (unsigned int)x < w && y >= 0 && (unsigned int)y < h) { + inframe[3*(x+y*w)+0] = 200; + inframe[3*(x+y*w)+1] = 200; + inframe[3*(x+y*w)+2] = 200; + } + } + + LockMutex(); + Convert(&cdata, vf, inframe, (w*h*3), V4L2_PIX_FMT_RGB24, w, h); + UnLockMutex(); + + return VDEV_STATUS_OK; +} + + +/***************************************************************************************************** + * Controls + */ + +/* + * set video control identified by id + */ +int VideoDev_Simulation::SetDevCtrl(unsigned int id, int value) { + return VDEV_STATUS_OK; +}; + + +/* + * get video control identified by id + */ +int VideoDev_Simulation::GetDevCtrl(unsigned int id, int *value) { + return VDEV_STATUS_OK; +}; + + +/********************************************************************************************************* + * Simulation + */ + +gpointer simulation_threadprocess_wrapper (gpointer data) { + simulation.ThreadProcess(); + return NULL; +} + +Simulation::Simulation() { + posX = 900.0; + posY = 500.0; + running = 0; + + time_t t = time(NULL); + srandom (t); + dAngle = 2.0 * M_PI * (double)random() / (double) RAND_MAX; + dLen = 5.0 + 10.0 * (double)random() / (double) RAND_MAX; + printf ("%s:%d %s dAngle:%f dLen:%f\n", __FILE__, __LINE__, __FUNCTION__, dAngle, dLen); +}; + +Simulation::~Simulation() { + LockMutex (); + running = 0; + UnLockMutex (); + +}; + + +void Simulation::GetPos (int *nx, int *ny) { + LockMutex(); + if (nx != NULL) *nx = (int)posX; + if (ny != NULL) *ny = (int)posY; + UnLockMutex(); +} + + +void Simulation::ThreadProcess() { + int r = 1; + struct timeval tv; + double ms; + double dx, dy; + + get_cycletime (&tv); + running = 1; + + do { + usleep (10000); + ms = get_cycletime(&tv); + LockMutex(); + + // + // simulate rotation movement + + // add random error to values + + // calculate movement + dx = sin(dAngle) * dLen * ms; + dy = cos(dAngle) * dLen * ms; + posX += dx; + posY += dy; + + // + // simulate motor axis movement + + + + if (posX < 0) posX = 1920.0 - 1.0; + if (posY < 0) posY = 1080.0 - 1.0; + if (posX > 1920) posX = 0.0; + if (posY > 1080) posY = 0.0; + r = running; + UnLockMutex(); + } while (r); +} + +void Simulation::Start() { + +} + + +void Simulation::Stop() { + running = 0; +} + + + diff --git a/videodev-simulation.h b/videodev-simulation.h new file mode 100644 index 0000000..0b37264 --- /dev/null +++ b/videodev-simulation.h @@ -0,0 +1,77 @@ + +#ifndef _H_VIDEODEV_SIMULATION_H_ +#define _H_VIDEODEV_SIMULATION_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#include "convert.h" +#include "gui.h" +#include "videodev.h" + + +class Simulation { +private: + float posX; + float posY; + float dAngle; + float dLen; + int running; + GMutex mutex; + +public: + Simulation(); + ~Simulation(); + void GetPos (int *nx, int *ny); + void ThreadProcess(); + + void Start(); + void Stop(); + + void LockMutex() { g_mutex_lock(&mutex); }; + void UnLockMutex() { g_mutex_unlock(&mutex); }; +}; + + +class VideoDev_Simulation: public VideoDev { +private: + uint32_t w; + uint32_t h; + struct timeval starttv; + unsigned char *inframe; + ConvertData cdata; + GThread *simulation_thread; + + int Grab(VideoFrame *vf); + int Open(); + int Close(); + int CaptureStart(); + int CaptureStop(); + int SetDevCtrl(unsigned int id, int value); + int GetDevCtrl(unsigned int id, int *value); +public: + VideoDev_Simulation(); + ~VideoDev_Simulation(); + int GetDeviceList(std::list *list); + int GetDeviceFormats(string device, std::list *formats) { return VDEV_STATUS_OK; }; + int GetDeviceResolutions(string device, std::list *formats) { return VDEV_STATUS_OK; }; +}; + +#endif diff --git a/videodev.h b/videodev.h index a53ef01..7d69b10 100644 --- a/videodev.h +++ b/videodev.h @@ -121,6 +121,7 @@ private: virtual int GetDevCtrl(unsigned int id, int *value) { return VDEV_STATUS_OK; }; friend class VideoDev_Dumpfile; + friend class VideoDev_Simulation; friend class VideoDev_V4L2; #ifdef USE_SVBONY friend class VideoDev_SVBCam; @@ -156,6 +157,7 @@ public: #include "videodev-v4l2.h" #include "videodev-dumpfile.h" +#include "videodev-simulation.h" #ifdef USE_SVBONY #include "videodev-svbcam.h" #endif