58#include <imgui_internal.h>
62#ifndef V4L2_CTRL_CLASS_DETECT
63#define V4L2_CTRL_CLASS_DETECT 0x00a30000
69 struct shortcontrol {
unsigned int id;
char const *
const shortname; };
74 static shortcontrol camcontrols[] = {
76 { V4L2_CID_BRIGHTNESS,
"brightness" },
77 { V4L2_CID_CONTRAST,
"contrast" },
78 { V4L2_CID_SATURATION,
"saturation" },
79 { V4L2_CID_HUE,
"hue" },
80 { V4L2_CID_AUDIO_VOLUME,
"audiovol" },
81 { V4L2_CID_AUDIO_BALANCE,
"audiobal" },
82 { V4L2_CID_AUDIO_BASS,
"audiobass" },
83 { V4L2_CID_AUDIO_TREBLE,
"audiotreble" },
84 { V4L2_CID_AUDIO_MUTE,
"audiomute" },
85 { V4L2_CID_AUDIO_LOUDNESS,
"audioloudness" },
86 { V4L2_CID_BLACK_LEVEL,
"blacklevel" },
87 { V4L2_CID_AUTO_WHITE_BALANCE,
"autowb" },
88 { V4L2_CID_DO_WHITE_BALANCE,
"dowb" },
89 { V4L2_CID_RED_BALANCE,
"redbal" },
90 { V4L2_CID_BLUE_BALANCE,
"bluebal" },
91 { V4L2_CID_GAMMA,
"gamma" },
92 { V4L2_CID_WHITENESS,
"whiteness" },
93 { V4L2_CID_EXPOSURE,
"exposure" },
94 { V4L2_CID_AUTOGAIN,
"autogain" },
95 { V4L2_CID_GAIN,
"gain" },
96 { V4L2_CID_HFLIP,
"hflip" },
97 { V4L2_CID_VFLIP,
"vflip" },
98 { V4L2_CID_POWER_LINE_FREQUENCY,
"powerfreq" },
99 { V4L2_CID_HUE_AUTO,
"autohue" },
100 { V4L2_CID_WHITE_BALANCE_TEMPERATURE,
"wbtemp" },
101 { V4L2_CID_SHARPNESS,
"sharpness" },
102 { V4L2_CID_BACKLIGHT_COMPENSATION,
"backlight" },
103 { V4L2_CID_CHROMA_AGC,
"chromaagc" },
104 { V4L2_CID_COLOR_KILLER,
"colorkiller" },
105 { V4L2_CID_COLORFX,
"colorfx" },
106 { V4L2_CID_AUTOBRIGHTNESS,
"autobrightness" },
107 { V4L2_CID_BAND_STOP_FILTER,
"bandfilter" },
108 { V4L2_CID_ROTATE,
"rotate" },
109 { V4L2_CID_BG_COLOR,
"bgcolor" },
110 { V4L2_CID_CHROMA_GAIN,
"chromagain" },
111 { V4L2_CID_ILLUMINATORS_1,
"illum1" },
112 { V4L2_CID_ILLUMINATORS_2,
"illum2" },
113 { V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
"mincapbuf" },
114 { V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
"minoutbuf" },
115 { V4L2_CID_ALPHA_COMPONENT,
"alphacompo" },
120 { V4L2_CID_EXPOSURE_AUTO,
"autoexp" },
121 { V4L2_CID_EXPOSURE_ABSOLUTE,
"absexp" },
122 { V4L2_CID_EXPOSURE_AUTO_PRIORITY,
"exppri" },
123 { V4L2_CID_PAN_RELATIVE,
"panrel" },
124 { V4L2_CID_TILT_RELATIVE,
"tiltrel" },
125 { V4L2_CID_PAN_RESET,
"panreset" },
126 { V4L2_CID_TILT_RESET,
"tiltreset" },
127 { V4L2_CID_PAN_ABSOLUTE,
"panabs" },
128 { V4L2_CID_TILT_ABSOLUTE,
"tiltabs" },
129 { V4L2_CID_FOCUS_ABSOLUTE,
"focusabs" },
130 { V4L2_CID_FOCUS_RELATIVE,
"focusrel" },
131 { V4L2_CID_FOCUS_AUTO,
"focusauto" },
132 { V4L2_CID_ZOOM_ABSOLUTE,
"zoomabs" },
133 { V4L2_CID_ZOOM_RELATIVE,
"zoomrel" },
134 { V4L2_CID_ZOOM_CONTINUOUS,
"zoomcontinuous" },
135 { V4L2_CID_PRIVACY,
"privacy" },
136 { V4L2_CID_IRIS_ABSOLUTE,
"irisabs" },
137 { V4L2_CID_IRIS_RELATIVE,
"irisrel" },
140#ifndef V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
141#define V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE (V4L2_CID_CAMERA_CLASS_BASE+20)
162 { V4L2_CID_FLASH_LED_MODE,
"flashled" },
163 { V4L2_CID_FLASH_STROBE_SOURCE,
"flashstrobesrc" },
164 { V4L2_CID_FLASH_STROBE,
"flashstrobe" },
165 { V4L2_CID_FLASH_STROBE_STOP,
"flashstrobestop" },
166 { V4L2_CID_FLASH_STROBE_STATUS,
"flashstrovestat" },
167 { V4L2_CID_FLASH_TIMEOUT,
"flashtimeout" },
168 { V4L2_CID_FLASH_INTENSITY,
"flashintens" },
169 { V4L2_CID_FLASH_TORCH_INTENSITY,
"flashtorch" },
170 { V4L2_CID_FLASH_INDICATOR_INTENSITY,
"flashindintens" },
171 { V4L2_CID_FLASH_FAULT,
"flashfault" },
172 { V4L2_CID_FLASH_CHARGE,
"flashcharge" },
173 { V4L2_CID_FLASH_READY,
"flashready" },
176 { V4L2_CID_JPEG_CHROMA_SUBSAMPLING,
"jpegchroma" },
177 { V4L2_CID_JPEG_RESTART_INTERVAL,
"jpegrestartint" },
178 { V4L2_CID_JPEG_COMPRESSION_QUALITY,
"jpegcompression" },
179 { V4L2_CID_JPEG_ACTIVE_MARKER,
"jpegmarker" },
204 std::string abbreviate(std::string
const & longname)
206 std::string name(longname);
207 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
208 name.erase(std::remove_if(name.begin(), name.end(), [](
int c) { return !std::isalnum(c); }), name.end());
215namespace jevois {
namespace engine {
static std::atomic<size_t> frameNumber(0); } }
217size_t jevois::frameNum()
218{
return jevois::engine::frameNumber.load(); }
222 jevois::
Manager(instance), itsMappings(), itsRunning(false), itsStreaming(false), itsStopMainLoop(false),
223 itsShellMode(false), itsTurbo(false), itsManualStreamon(false), itsVideoErrors(false),
224 itsNumSerialSent(0), itsRequestedFormat(-2)
228#ifdef JEVOIS_PLATFORM_A33
230 itsCheckingMassStorage.store(
false); itsMassStorageMode.store(
false);
232 while (itsCheckingMassStorage.load() ==
false) std::this_thread::sleep_for(std::chrono::milliseconds(5));
235 jevois::engine::frameNumber.store(0);
240 jevois::
Manager(argc, argv, instance), itsMappings(), itsRunning(false), itsStreaming(false),
241 itsStopMainLoop(false), itsShellMode(false), itsTurbo(false), itsManualStreamon(false), itsVideoErrors(false),
242 itsNumSerialSent(0), itsRequestedFormat(-2)
246#ifdef JEVOIS_PLATFORM_A33
248 itsCheckingMassStorage.store(
false); itsMassStorageMode.store(
false);
250 while (itsCheckingMassStorage.load() ==
false) std::this_thread::sleep_for(std::chrono::milliseconds(5));
253 jevois::engine::frameNumber.store(0);
262 for (std::list<std::shared_ptr<UserInterface> >::iterator itr = itsSerials.begin(); itr != itsSerials.end(); ++itr)
263 if ((*itr)->instanceName() ==
"serial") itr = itsSerials.erase(itr);
264 removeComponent(
"serial",
false);
267 if (newval.empty() ==
false)
270 std::shared_ptr<jevois::UserInterface> s;
271 if (newval ==
"stdio")
272 s = addComponent<jevois::StdioInterface>(
"serial");
279 if (serialmonitors::get())
286 s->setParamVal(
"devname", newval);
289 itsSerials.push_back(s);
290 LINFO(
"Using [" << newval <<
"] hardware (4-pin connector) serial port");
293 else LINFO(
"No hardware (4-pin connector) serial port used");
302 for (std::list<std::shared_ptr<UserInterface> >::iterator itr = itsSerials.begin(); itr != itsSerials.end(); ++itr)
303 if ((*itr)->instanceName() ==
"usbserial") itr = itsSerials.erase(itr);
304 removeComponent(
"usbserial",
false);
307 if (newval.empty() ==
false)
314 std::shared_ptr<jevois::UserInterface> s;
315 if (serialmonitors::get())
320 std::shared_ptr<jevois::UserInterface> s =
323 s->setParamVal(
"devname", newval);
324 itsSerials.push_back(s);
325 LINFO(
"Using [" << newval <<
"] USB serial port");
328 else LINFO(
"No USB serial port used");
335 std::ofstream ofs(
"/sys/devices/system/cpu/cpu2/cpufreq/scaling_governor");
337 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor");
339 if (ofs.is_open() ==
false)
341#ifdef JEVOIS_PLATFORM
342 LERROR(
"Cannot set cpu frequency governor mode -- IGNORED");
349 case engine::CPUmode::PowerSave: ofs <<
"powersave" << std::endl;
break;
350 case engine::CPUmode::Conservative: ofs <<
"conservative" << std::endl;
break;
351 case engine::CPUmode::OnDemand: ofs <<
"ondemand" << std::endl;
break;
352 case engine::CPUmode::Interactive: ofs <<
"interactive" << std::endl;
break;
353 case engine::CPUmode::Performance: ofs <<
"performance" << std::endl;
break;
361 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor");
362 if (ofs.is_open() ==
false)
364#ifdef JEVOIS_PLATFORM
365 LERROR(
"Cannot set cpu frequency governor mode -- IGNORED");
372 case engine::CPUmode::PowerSave: ofs <<
"powersave" << std::endl;
break;
373 case engine::CPUmode::Conservative: ofs <<
"conservative" << std::endl;
break;
374 case engine::CPUmode::OnDemand: ofs <<
"ondemand" << std::endl;
break;
375 case engine::CPUmode::Interactive: ofs <<
"interactive" << std::endl;
break;
376 case engine::CPUmode::Performance: ofs <<
"performance" << std::endl;
break;
385 std::ofstream ofs(
"/sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq");
387 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
390 if (ofs.is_open() ==
false)
392#ifdef JEVOIS_PLATFORM
393 LERROR(
"Cannot set cpu max frequency -- IGNORED");
398 ofs << newval * 1000U << std::endl;
404 itsVideoErrors.store(newval);
416 itsGUIhelper = addComponent<jevois::GUIhelper>(
"gui", conslock::get());
417 auto s = addComponent<jevois::GUIconsole>(
"guiconsole");
418 itsSerials.push_back(s);
419 LINFO(
"GUI enabled.");
422 else if (itsGUIhelper)
424 for (
auto itr = itsSerials.begin(); itr != itsSerials.end(); ++itr)
425 if ((*itr)->instanceName() ==
"guiconsole") { itsSerials.erase(itr);
break; }
426 removeComponent(
"guiconsole",
false);
427 removeComponent(itsGUIhelper);
428 itsGUIhelper.reset();
429 LINFO(
"GUI disabled.");
436 std::ofstream ofs(
"/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
438 if (ofs.is_open() ==
false)
440#ifdef JEVOIS_PLATFORM
441 LERROR(
"Cannot set cpu max frequency -- IGNORED");
446 ofs << newval * 1000U << std::endl;
453 if (newval == 0.0F) itsDemoReset =
true;
457void jevois::Engine::runDemoStep()
459 if (! itsGUIhelper)
return;
461 int constexpr fade = 30;
462 int constexpr msg = 90;
463 int constexpr tmax = 15;
472 static size_t modidx = 0;
473 static int fade_out = 0, show_msg = 0, fade_in = 0;
474 static std::chrono::time_point<std::chrono::steady_clock> mod_load_time;
475 std::chrono::time_point<std::chrono::steady_clock>
const now = std::chrono::steady_clock::now();
482 if (fs.isOpened() ==
false)
485 cv::FileNode fn = fs.root();
486 for (cv::FileNodeIterator gfit = fn.begin(); gfit != fn.end(); ++gfit)
488 cv::FileNode item = *gfit;
489 if (! item.isMap())
continue;
492 for(cv::FileNodeIterator fit = item.begin(); fit != item.end(); ++fit)
494 cv::FileNode param = *fit;
496 std::string k = param.name();
497 if (k ==
"demomapping")
499 std::string
const vmstr = (std::string)param;
501 int idx = 0; dd.mapping_idx = -1;
503 {
if (vm.
isSameAs(m)) dd.mapping_idx = idx;
else ++idx; });
504 if (dd.mapping_idx == -1) {
LERROR(
"Video mapping not found for [" << vmstr <<
"] -- SKIPPED");
break; }
506 else if (k ==
"demotitle")
507 dd.title = (std::string)param;
508 else if (k ==
"demomsg")
509 dd.msg = (std::string)param;
513 switch (param.type())
515 case cv::FileNode::INT: v = std::to_string((
int)param);
break;
516 case cv::FileNode::REAL: v = std::to_string((
float)param);
break;
517 case cv::FileNode::STRING: v = (std::string)param;
break;
518 default:
LERROR(
"Invalid demo parameter for [" << item.name() <<
"]: " << k <<
" type " << param.type());
521 if (dd.mapping_idx != -1) dd.params.emplace_back(std::make_pair(k, v));
525 itsDemoData.emplace_back(std::move(dd));
528 if (itsDemoData.empty())
530 else LINFO(
"Loaded demo information with " << itsDemoData.size() <<
" demo modules.");
533 fade_out = 0; show_msg = msg * 3; fade_in = 0; mod_load_time = now; modidx = 0;
534 itsGUIhelper->demoBanner(
"Welcome to JeVois-Pro!",
"This demo will cycle through a few machine vision algorithms.");
535 itsDemoReset =
false;
540 if (itsNextDemoRequested)
542 ++modidx;
if (modidx >= itsDemoData.size()) modidx = 0;
543 fade_out = 0; show_msg = msg; fade_in = 0; mod_load_time = now;
544 itsNextDemoRequested =
false;
548 if (show_msg == msg || itsGUIhelper->idle() ==
false)
549 itsGUIhelper->demoBanner(itsDemoData[modidx].title, itsDemoData[modidx].msg);
553 itsGUIhelper->twirl::set(tmax);
557 LINFO(
"Loading demo: " << itsDemoData[modidx].title);
558 requestSetFormat(itsDemoData[modidx].mapping_idx);
564 if (show_msg == 0) fade_in = fade;
570 for (
auto const & pp : itsDemoData[modidx].params)
571 try { setParamString(pp.first, pp.second); }
572 catch (...) {
LERROR(
"Failed to set param [" << pp.first <<
"] to [" << pp.second <<
"] -- IGNORED"); }
577 itsGUIhelper->twirl::set(
float(tmax * fade_in - tmax) /
float(fade));
578 if (--fade_in == 0 && itsGUIhelper->idle()) itsGUIhelper->demoBanner();
585 itsGUIhelper->twirl::set(tmax -
float(tmax * fade_out - tmax) /
float(fade));
586 if (--fade_out == 0) show_msg = msg;
591 std::chrono::duration<float>
const elapsed = now - mod_load_time;
592 if (elapsed.count() > demomode::get())
595 ++modidx;
if (modidx >= itsDemoData.size()) modidx = 0;
601{ itsNextDemoRequested =
true; }
608 if (! itsGUIhelper)
return;
610 itsGUIhelper->twirl::set(0.0F);
611 itsGUIhelper->demoBanner();
621 std::ifstream ifs(paramcfg);
if (ifs.is_open()) setParamsFromStream(ifs, paramcfg);
636 itsMappings = jevois::loadVideoMappings(camerasens::get(), itsDefaultMappingIdx,
true, usegui);
637 LINFO(
"Loaded " << itsMappings.size() <<
" vision processing modes.");
652 serialmonitors::freeze(
true);
654 serialdev::freeze(
true);
655 usbserialdev::freeze(
true);
656 for (
auto & s : itsSerials) s->freezeAllParams(
true);
657 cameradev::freeze(
true);
658 imudev::freeze(
true);
659 cameranbuf::freeze(
true);
660 camturbo::freeze(
true);
661 gadgetdev::freeze(
true);
662 gadgetnbuf::freeze(
true);
663 itsTurbo = camturbo::get();
664 multicam::freeze(
true);
665 quietcmd::freeze(
true);
666 python::freeze(
true);
670 jevois::CameraSensor camsens = camerasens::get();
671#ifdef JEVOIS_PLATFORM_PRO
672 if (camsens == jevois::CameraSensor::any)
675 size_t idx = 0;
while (idx < str.length() && std::isalnum(str[idx])) ++idx;
676 str = str.substr(0, idx);
677 camerasens::strset(str);
678 camsens = camerasens::get();
679 LINFO(
"Camera sensor selected from device tree: " << camsens);
682 camerasens::freeze(
true);
683 LINFO(
"Using camera sensor: " << camsens);
690 conslock::freeze(
true);
691 watchdog::freeze(
true);
698 reloadVideoMappings();
706 LINFO(
"Initalizing Python...");
711 std::string
const camdev = cameradev::get();
714 LINFO(
"Starting camera device " << camdev);
716#ifdef JEVOIS_PLATFORM_A33
718 std::ofstream ofs(
"/sys/module/vfe_v4l2/parameters/turbo");
721 if (itsTurbo) ofs <<
"1" << std::endl;
else ofs <<
"0" << std::endl;
724 else LERROR(
"Could not access VFE turbo parameter -- IGNORED");
728 itsCamera.reset(
new jevois::Camera(camdev, camsens, cameranbuf::get()));
730#ifndef JEVOIS_PLATFORM
732 camreg::set(
false); camreg::freeze(
true);
733 imureg::set(
false); imureg::freeze(
true);
739#ifdef JEVOIS_PLATFORM_A33
741 itsIMU.reset(
new jevois::IMUi2c(std::dynamic_pointer_cast<jevois::Camera>(itsCamera)));
745#ifdef JEVOIS_PLATFORM_PRO
749 }
catch (...) {
LERROR(
"Sensor should have an IMU but we failed to initialize it."); }
753 LINFO(
"Using movie input " << camdev <<
" -- issue a 'streamon' to start processing.");
758 camreg::freeze(
true);
763 int midx = videomapping::get();
766 videomapping::freeze(
true);
768 if (midx >=
int(itsMappings.size()))
769 {
LERROR(
"Mapping index " << midx <<
" out of range -- USING DEFAULT"); midx = -1; }
771 if (midx < 0) midx = itsDefaultMappingIdx;
774 std::string
const gd = gadgetdev::get();
777 LINFO(
"Using no USB video output.");
780 itsManualStreamon =
true;
784 LINFO(
"Loading USB video driver " << gd);
786 itsGadget.reset(
new jevois::Gadget(gd, itsCamera.get(),
this, gadgetnbuf::get(), multicam::get()));
788 else if (gd.empty() ==
false)
790 LINFO(
"Saving output video to file " << gd);
793 itsManualStreamon =
true;
802 LINFO(
"Using OpenGL + ImGui display for video output");
807 LINFO(
"Using OpenGL display for video output");
812 LINFO(
"Using OpenCV display for video output");
816 itsManualStreamon =
true;
820 itsRunning.store(
true);
838 itsRunning.store(
false);
840#ifdef JEVOIS_PLATFORM_A33
842 itsCheckingMassStorage.store(
false);
848 if (itsModule) removeComponent(itsModule);
859#ifdef JEVOIS_PLATFORM_A33
861 if (itsCheckMassStorageFut.valid())
870#ifdef JEVOIS_PLATFORM_A33
871void jevois::Engine::checkMassStorage()
873 itsCheckingMassStorage.store(
true);
875 while (itsCheckingMassStorage.load())
881 std::ifstream ifs(
"/sys/devices/platform/sunxi_usb_udc/gadget/lun0/mass_storage_in_use");
884 int inuse; ifs >> inuse;
885 if (itsMassStorageMode.load())
887 if (inuse == 0) stopMassStorageMode();
894 std::this_thread::sleep_for(std::chrono::milliseconds(500));
905 if (itsCamera) itsCamera->streamOn();
906 if (itsGadget) itsGadget->streamOn();
907 itsStreaming.store(
true);
916 if (itsGadget) itsGadget->abortStream();
917 if (itsCamera) itsCamera->abortStream();
920 LDEBUG(
"Stopping main loop...");
921 itsStopMainLoop.store(
true);
922 while (itsStopMainLoop.load() && itsRunning.load()) std::this_thread::sleep_for(std::chrono::milliseconds(10));
923 LDEBUG(
"Main loop stopped.");
927 if (itsGadget) itsGadget->streamOff();
928 if (itsCamera) itsCamera->streamOff();
935 itsRequestedFormat.store(idx);
943 LDEBUG(
"Set format number " << idx <<
" start...");
945 if (idx >= itsMappings.size())
946 LFATAL(
"Requested mapping index " << idx <<
" out of range [0 .. " << itsMappings.size()-1 <<
']');
949 setFormatInternal(idx);
950 LDEBUG(
"Set format number " << idx <<
" done");
954void jevois::Engine::setFormatInternal(
size_t idx)
960 setFormatInternal(m);
970 itsModuleConstructionError =
"Unknown error while starting module " + m.
modulename +
" ...";
972#ifdef JEVOIS_PLATFORM_A33
973 if (itsMassStorageMode.load())
974 LFATAL(
"Cannot setup video streaming while in mass-storage mode. Eject the USB drive on your host computer first.");
982 LDEBUG(
"Removing current module " << itsModule->className() <<
": " << itsModule->descriptor());
983 try { removeComponent(itsModule); itsModule.reset();
LDEBUG(
"Current module removed."); }
991 try { itsCamera->setFormat(m); }
995 itsModuleConstructionError =
"Camera did not accept format:\n\n" + m.
cstrall() +
996 "\n\nCheck videomappings.cfg and camera sensor specifications.";
1000 LDEBUG(
"Setting gadget format: " << m.
ostr());
1001 try { itsGadget->setFormat(m); }
1005 itsModuleConstructionError =
"Gadget did not accept format:\n\n" + m.
ostr() +
1006 "\n\nCheck videomappings.cfg for any unsupported output formats.";
1012 itsCurrentMapping = m;
1015 jevois::engine::frameNumber.store(0);
1023 std::string
const sopath = m.
sopath(
true);
1026 if (python::get() ==
false)
LFATAL(
"Python disabled, delete BOOT:nopython and restart to enable python");
1037 if (itsLoader.get() ==
nullptr || itsLoader->sopath() != sopath)
1039 LINFO(
"Instantiating dynamic loader for " << sopath);
1045 auto version_major = itsLoader->load<int()>(m.
modulename +
"_version_major");
1046 auto version_minor = itsLoader->load<int()>(m.
modulename +
"_version_minor");
1048 LERROR(
"Module " << m.
modulename <<
" in file " << sopath <<
" was build for JeVois v" << version_major() <<
'.'
1049 << version_minor() <<
", but running framework is v" <<
JEVOIS_VERSION_STRING <<
" -- TRYING ANYWAY");
1052 auto create = itsLoader->load<std::shared_ptr<jevois::Module>(std::string
const &)>(m.
modulename +
"_create");
1059 boost::unique_lock<boost::shared_mutex> ulck(itsSubMtx);
1062 itsSubComponents.push_back(itsModule);
1063 itsModule->itsParent =
this;
1064 itsModule->setPath(sopath.substr(0, sopath.rfind(
'/')));
1068 if (itsInitialized) itsModule->runPreInit();
1071 std::ifstream ifs(paramcfg);
if (ifs.is_open()) itsModule->setParamsFromStream(ifs, paramcfg);
1073 if (itsInitialized) { itsModule->setInitialized(); itsModule->runPostInit(); }
1076 std::shared_ptr<jevois::UserInterface> ser;
1077 for (
auto & s : itsSerials)
1078 if (s->type() ==
jevois::UserInterface::Type::USB || s->type() ==
jevois::UserInterface::Type::GUI)
1083 LINFO(
"Module [" << m.
modulename <<
"] loaded, initialized, and ready.");
1084 itsModuleConstructionError.clear();
1090 LERROR(
"Module [" << m.
modulename <<
"] startup error and not operational.");
1109 for (
auto & s : itsSerials)
1114 while (itsRunning.load())
1116 bool dosleep =
true;
1120 itsWatchdog->reset();
1125 int rf = itsRequestedFormat.load();
1129 itsRequestedFormat.store(-2);
1134 if (rf != -1 && itsStreaming.load())
1137 if (itsGadget) itsGadget->abortStream();
1138 if (itsCamera) itsCamera->abortStream();
1140 if (itsGadget) itsGadget->streamOff();
1141 if (itsCamera) itsCamera->streamOff();
1142 itsStreaming.store(
false);
1150 setFormatInternal(itsCurrentMapping,
true);
1156 if (itsGUIhelper) itsGUIhelper->resetstate( (rf != -1) );
1160 if (rf != -1 && itsCurrentMapping.ofmt != 0)
1164 if (itsCamera) itsCamera->streamOn();
1165 if (itsGadget) itsGadget->streamOn();
1166 itsStreaming.store(
true);
1172 if (itsGUIhelper && itsStreaming.load() ==
false)
1176 if (itsCamera) itsCamera->streamOn();
1177 if (itsGadget) itsGadget->streamOn();
1178 itsStreaming.store(
true);
1184 reportErrorInternal();
1189 if (itsGadget) itsGadget->abortStream();
1190 if (itsCamera) itsCamera->abortStream();
1192 if (itsGadget) itsGadget->streamOff();
1193 if (itsCamera) itsCamera->streamOff();
1194 itsStreaming.store(
false);
1202 if (demomode::get()) runDemoStep();
1206 if (itsStreaming.load())
1211 if (itsModuleConstructionError.empty() ==
false)
1214 reportErrorInternal(itsModuleConstructionError);
1229 switch (itsCurrentMapping.ofmt)
1238 if (itsGUIhelper) itsGUIhelper->headlessDisplay();
1262 catch (...) { reportErrorInternal(); }
1268 ++ jevois::engine::frameNumber;
1269 itsNumSerialSent.store(0);
1273 if (itsStopMainLoop.load())
1275 itsStreaming.store(
false);
1276 LDEBUG(
"-- Main loop stopped --");
1277 itsStopMainLoop.store(
false);
1282 LDEBUG(
"No processing module loaded or not streaming... Sleeping...");
1283 std::this_thread::sleep_for(std::chrono::milliseconds(25));
1288 for (
auto & s : itsSerials)
1292 std::string str;
int received = 0;
1294 while (s->readSome(str))
1296 bool parsed =
false;
bool success =
false;
1299 if ((++received % 10) == 0)
1300 reportError(
"Warning: high rate of serial inputs on port: " + s->instanceName() +
". \n\n"
1301 "This may adversely affect JeVois framerate.");
1309 pfx = JEVOIS_JVINV_PREFIX;
1310 str = str.substr(pfx.length());
1317 try { parsed = parseCommand(str, s, pfx);
success = parsed; }
1318 catch (std::exception
const & e)
1319 { s->writeString(pfx, std::string(
"ERR ") + e.what()); parsed =
true; }
1321 { s->writeString(pfx,
"ERR Unknown error"); parsed =
true; }
1323 if (parsed ==
false)
1328 try { itsModule->parseSerial(str, s);
success =
true; }
1329 catch (std::exception
const & me) { s->writeString(pfx, std::string(
"ERR ") + me.what()); }
1330 catch (...) { s->writeString(pfx,
"ERR Command [" + str +
"] not recognized by Engine or Module"); }
1332 else s->writeString(pfx,
"ERR Unsupported command [" + str +
"] and no module");
1336 if (
success && quietcmd::get() ==
false && itsShellMode ==
false) s->writeString(pfx,
"OK");
1349 size_t slim = serlimit::get();
1350 if (islog ==
false && slim)
1352 if (itsNumSerialSent.load() >= slim)
return;
1357 jevois::engine::SerPort p = islog ? serlog::get() : serout::get();
1360 case jevois::engine::SerPort::None:
1363 case jevois::engine::SerPort::All:
1364 for (
auto & s : itsSerials)
1368 case jevois::engine::SerPort::Hard:
1369 for (
auto & s : itsSerials)
1374 case jevois::engine::SerPort::USB:
1375 for (
auto & s : itsSerials)
1383 if (itsGUIhelper && ((islog && itsGUIhelper->serlogEnabled()) || (!islog && itsGUIhelper->seroutEnabled())))
1384 for (
auto & s : itsSerials)
1394 if (itsGUIhelper) itsGUIhelper->reportError(err);
1404 if (itsGUIhelper) itsGUIhelper->clearErrors();
1410void jevois::Engine::reportErrorInternal(std::string
const & err)
1416 if (itsGUIhelper->frameStarted() ==
false) {
unsigned short w,
h; itsGUIhelper->startFrame(w,
h); }
1418 else itsGUIhelper->reportError(err);
1419 itsGUIhelper->endFrame();
1426 if (itsCurrentMapping.ofmt != 0 && itsCurrentMapping.ofmt !=
JEVOISPRO_FMT_GUI && itsVideoErrors.load())
1431 if (itsVideoErrorImage.valid() ==
false) itsGadget->get(itsVideoErrorImage);
1442 if (itsVideoErrorImage.valid()) itsGadget->send(itsVideoErrorImage);
1447 itsVideoErrorImage.invalidate();
1459{
return itsModule; }
1462std::shared_ptr<jevois::IMU> jevois::Engine::imu()
const
1467{
return std::dynamic_pointer_cast<jevois::Camera>(itsCamera); }
1476 if (itsCurrentMapping.c2fmt) { w = itsCurrentMapping.c2w;
h = itsCurrentMapping.c2h; }
1477 else { w = itsCurrentMapping.cw;
h = itsCurrentMapping.ch; }
1480 '-' + camerasens::strget() +
'-' + std::to_string(w) +
'x' + std::to_string(
h) +
1481 '-' + cameralens::strget() +
".yaml";
1488 LINFO(
"Camera calibration loaded from [" << fname <<
']');
1493 LFATAL(
"Failed to read camera parameters from file [" << fname <<
']');
1496 reportError(
"Failed to read camera parameters from file [" + fname +
"] -- IGNORED");
1499 calib.
sensor = camerasens::get();
1500 calib.
lens = cameralens::get();
1501 calib.
w = w; calib.
h =
h;
1518 LINFO(
"Camera calibration saved to [" << fname <<
']');
1523{
return itsCurrentMapping; }
1527{
return itsMappings.size(); }
1532 if (idx >= itsMappings.size())
1533 LFATAL(
"Index " << idx <<
" out of range [0 .. " << itsMappings.size()-1 <<
']');
1535 return itsMappings[idx];
1542 if (iformat == 0 || iframe == 0)
return itsDefaultMappingIdx;
1555 LFATAL(
"No video mapping for iformat=" << iformat <<
", iframe=" << iframe <<
", interval=" << interval);
1565 LFATAL(
"No video mapping for iformat=" << iformat <<
", iframe=" << iframe <<
", interval=" << interval);
1571{
return itsMappings[itsDefaultMappingIdx]; }
1575{
return itsDefaultMappingIdx; }
1587 float oframespersec)
const
1590 if (m.
match(oformat, owidth, oheight, oframespersec))
return m;
1593 owidth <<
'x' << oheight <<
" @ " << oframespersec <<
" fps");
1597void jevois::Engine::foreachCamCtrl(std::function<
void(
struct v4l2_queryctrl & qc, std::set<int> & doneids)> && func)
1599 struct v4l2_queryctrl qc = { }; std::set<int> doneids;
1605 qc.id = cls | 0x900;
unsigned int old_id;
1608 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL; old_id = qc.id;
bool failed =
false;
1609 try { func(qc, doneids); }
catch (...) { failed =
true; }
1613 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
1614 if (qc.id == old_id) { ++qc.id;
if (qc.id > 100 + (cls | 0x900 | V4L2_CTRL_FLAG_NEXT_CTRL))
break; }
1615 else if (failed)
break;
1621std::string jevois::Engine::camctrlname(
unsigned int id,
char const * longname)
const
1623 for (
size_t i = 0; i <
sizeof camcontrols /
sizeof camcontrols[0]; ++i)
1624 if (camcontrols[i].
id ==
id)
return camcontrols[i].shortname;
1627 return abbreviate(longname);
1631unsigned int jevois::Engine::camctrlid(std::string
const & shortname)
1633 for (
size_t i = 0; i <
sizeof camcontrols /
sizeof camcontrols[0]; ++i)
1634 if (shortname.compare(camcontrols[i].shortname) == 0)
return camcontrols[i].id;
1637 struct v4l2_queryctrl qc = { };
1643 qc.id = cls | 0x900;
1646 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
unsigned int old_id = qc.id;
bool failed =
false;
1649 itsCamera->queryControl(qc);
1650 if (abbreviate(
reinterpret_cast<char const *
>(qc.name)) == shortname)
return qc.id;
1652 catch (...) { failed =
true; }
1657 qc.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
1658 if (qc.id == old_id) { ++qc.id;
if (qc.id > 100 + (cls | 0x900 | V4L2_CTRL_FLAG_NEXT_CTRL))
break; }
1659 else if (failed)
break;
1663 LFATAL(
"Could not find control [" << shortname <<
"] in the camera");
1667std::string jevois::Engine::camCtrlHelp(
struct v4l2_queryctrl & qc, std::set<int> & doneids)
1670 itsCamera->queryControl(qc);
1671 qc.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
1674 if (doneids.find(qc.id) != doneids.end())
return std::string();
else doneids.insert(qc.id);
1677 struct v4l2_control ctrl = { }; ctrl.id = qc.id;
1678 itsCamera->getControl(ctrl);
1681 std::ostringstream ss;
1682 ss <<
"- " << camctrlname(qc.id,
reinterpret_cast<char const *
>(qc.name));
1686 case V4L2_CTRL_TYPE_INTEGER:
1687 ss <<
" [int] min=" << qc.minimum <<
" max=" << qc.maximum <<
" step=" << qc.step
1688 <<
" def=" << qc.default_value <<
" curr=" << ctrl.value;
1700 case V4L2_CTRL_TYPE_BOOLEAN:
1701 ss <<
" [bool] default=" << qc.default_value <<
" curr=" << ctrl.value;
1710 case V4L2_CTRL_TYPE_BUTTON:
1714 case V4L2_CTRL_TYPE_BITMASK:
1715 ss <<
" [bitmask] max=" << qc.maximum <<
" def=" << qc.default_value <<
" curr=" << ctrl.value;
1718 case V4L2_CTRL_TYPE_MENU:
1720 struct v4l2_querymenu querymenu = { };
1721 querymenu.id = qc.id;
1722 ss <<
" [menu] values ";
1723 for (querymenu.index = qc.minimum; querymenu.index <= (
unsigned int)qc.maximum; ++querymenu.index)
1725 try { itsCamera->queryMenu(querymenu); }
catch (...) { strcpy((
char *)(querymenu.name),
"fixme"); }
1726 ss << querymenu.index <<
':' << querymenu.name <<
' ';
1728 ss <<
"curr=" << ctrl.value;
1733 ss <<
"[unknown type]";
1736 if (qc.flags & V4L2_CTRL_FLAG_DISABLED) ss <<
" [DISABLED]";
1742std::string jevois::Engine::camCtrlInfo(
struct v4l2_queryctrl & qc, std::set<int> & doneids)
1745 itsCamera->queryControl(qc);
1746 qc.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
1749 if (doneids.find(qc.id) != doneids.end())
return std::string();
else doneids.insert(qc.id);
1752 struct v4l2_control ctrl = { }; ctrl.id = qc.id;
1753 itsCamera->getControl(ctrl);
1756 std::ostringstream ss;
1757 ss << camctrlname(qc.id,
reinterpret_cast<char const *
>(qc.name));
1759 if (qc.flags & V4L2_CTRL_FLAG_DISABLED) ss <<
" D ";
1763 case V4L2_CTRL_TYPE_INTEGER:
1764 ss <<
" I " << qc.minimum <<
' ' << qc.maximum <<
' ' << qc.step
1765 <<
' ' << qc.default_value <<
' ' << ctrl.value;
1776 case V4L2_CTRL_TYPE_BOOLEAN:
1777 ss <<
" B " << qc.default_value <<
' ' << ctrl.value;
1785 case V4L2_CTRL_TYPE_BUTTON:
1789 case V4L2_CTRL_TYPE_BITMASK:
1790 ss <<
" K " << qc.maximum <<
' ' << qc.default_value <<
' ' << ctrl.value;
1793 case V4L2_CTRL_TYPE_MENU:
1795 struct v4l2_querymenu querymenu = { };
1796 querymenu.id = qc.id;
1797 ss <<
" M " << qc.default_value <<
' ' << ctrl.value;
1798 for (querymenu.index = qc.minimum; querymenu.index <= (
unsigned int)qc.maximum; ++querymenu.index)
1800 try { itsCamera->queryMenu(querymenu); }
catch (...) { strcpy((
char *)(querymenu.name),
"fixme"); }
1801 ss <<
' ' << querymenu.index <<
':' << querymenu.name <<
' ';
1813#ifdef JEVOIS_PLATFORM_A33
1815void jevois::Engine::startMassStorageMode()
1819 if (itsMassStorageMode.load()) {
LERROR(
"Already in mass-storage mode -- IGNORED");
return; }
1822 if (itsModule) { removeComponent(itsModule); itsModule.reset(); }
1823 if (itsLoader) itsLoader.reset();
1826 if (std::system(
"sync"))
LERROR(
"Disk sync failed -- IGNORED");
1827 if (std::system(
"mount -o remount,ro /jevois"))
LERROR(
"Failed to remount /jevois read-only -- IGNORED");
1834 LINFO(
"Exported JEVOIS partition of microSD to host computer as virtual flash drive.");
1835 itsMassStorageMode.store(
true);
1839void jevois::Engine::stopMassStorageMode()
1842 LINFO(
"JeVois virtual USB drive ejected by host -- REBOOTING");
1850 if (std::system(
"sync"))
LERROR(
"Disk sync failed -- IGNORED");
1851 if (std::system(
"sync"))
LERROR(
"Disk sync failed -- IGNORED");
1852#ifdef JEVOIS_PLATFORM_A33
1853 itsCheckingMassStorage.store(
false);
1855 itsRunning.store(
false);
1857#ifdef JEVOIS_PLATFORM_A33
1859 if ( ! std::ofstream(
"/proc/sys/kernel/sysrq").put(
'1'))
LERROR(
"Cannot trigger hard reset -- please unplug me!");
1860 if ( ! std::ofstream(
"/proc/sysrq-trigger").put(
's'))
LERROR(
"Cannot trigger hard reset -- please unplug me!");
1861 if ( ! std::ofstream(
"/proc/sysrq-trigger").put(
'b'))
LERROR(
"Cannot trigger hard reset -- please unplug me!");
1872 itsGadget->abortStream();
1873 itsCamera->abortStream();
1874 itsStreaming.store(
false);
1875 itsGadget->streamOff();
1876 itsCamera->streamOff();
1877 itsRunning.store(
false);
1883void jevois::Engine::cmdInfo(std::shared_ptr<UserInterface> s,
bool showAll, std::string
const & pfx)
1885 s->writeString(pfx,
"help - print this help message");
1886 s->writeString(pfx,
"help2 - print compact help message about current vision module only");
1887 s->writeString(pfx,
"info - show system information including CPU speed, load and temperature");
1888 s->writeString(pfx,
"setpar <name> <value> - set a parameter value");
1889 s->writeString(pfx,
"getpar <name> - get a parameter value(s)");
1890 s->writeString(pfx,
"runscript <filename> - run script commands in specified file");
1891 s->writeString(pfx,
"setcam <ctrl> <val> - set camera control <ctrl> to value <val>");
1892 s->writeString(pfx,
"getcam <ctrl> - get value of camera control <ctrl>");
1894 if (showAll || camreg::get())
1896 s->writeString(pfx,
"setcamreg <reg> <val> - set raw camera register <reg> to value <val>");
1897 s->writeString(pfx,
"getcamreg <reg> - get value of raw camera register <reg>");
1898 s->writeString(pfx,
"setimureg <reg> <val> - set raw IMU register <reg> to value <val>");
1899 s->writeString(pfx,
"getimureg <reg> - get value of raw IMU register <reg>");
1900 s->writeString(pfx,
"setimuregs <reg> <num> <val1> ... <valn> - set array of raw IMU register values");
1901 s->writeString(pfx,
"getimuregs <reg> <num> - get array of raw IMU register values");
1902 s->writeString(pfx,
"setdmpreg <reg> <val> - set raw DMP register <reg> to value <val>");
1903 s->writeString(pfx,
"getdmpreg <reg> - get value of raw DMP register <reg>");
1904 s->writeString(pfx,
"setdmpregs <reg> <num> <val1> ... <valn> - set array of raw DMP register values");
1905 s->writeString(pfx,
"getdmpregs <reg> <num> - get array of raw DMP register values");
1908 s->writeString(pfx,
"listmappings - list all available video mappings");
1909 s->writeString(pfx,
"setmapping <num> - select video mapping <num>, only possible while not streaming");
1910 s->writeString(pfx,
"setmapping2 <CAMmode> <CAMwidth> <CAMheight> <CAMfps> <Vendor> <Module> - set no-USB-out "
1911 "video mapping defined on the fly, while not streaming");
1912 s->writeString(pfx,
"reload - reload and reset the current module");
1914 if (showAll || itsCurrentMapping.ofmt == 0 || itsManualStreamon)
1916 s->writeString(pfx,
"streamon - start camera video streaming");
1917 s->writeString(pfx,
"streamoff - stop camera video streaming");
1920 s->writeString(pfx,
"ping - returns 'ALIVE'");
1921 s->writeString(pfx,
"serlog <string> - forward string to the serial port(s) specified by the serlog parameter");
1922 s->writeString(pfx,
"serout <string> - forward string to the serial port(s) specified by the serout parameter");
1927 s->writeString(pfx,
"caminfo - returns machine-readable info about camera parameters");
1928 s->writeString(pfx,
"cmdinfo [all] - returns machine-readable info about Engine commands");
1929 s->writeString(pfx,
"modcmdinfo - returns machine-readable info about Module commands");
1930 s->writeString(pfx,
"paraminfo [hot|mod|modhot] - returns machine-readable info about parameters");
1931 s->writeString(pfx,
"serinfo - returns machine-readable info about serial settings (serout serlog serstyle serprec serstamp)");
1932 s->writeString(pfx,
"fileget <filepath> - get a file from JeVois to the host. Use with caution!");
1933 s->writeString(pfx,
"fileput <filepath> - put a file from the host to JeVois. Use with caution!");
1936#ifdef JEVOIS_PLATFORM_A33
1937 s->writeString(pfx,
"usbsd - export the JEVOIS partition of the microSD card as a virtual USB drive");
1939 s->writeString(pfx,
"sync - commit any pending data write to microSD");
1940 s->writeString(pfx,
"date [date and time] - get or set the system date and time");
1942 s->writeString(pfx,
"!<string> - execute <string> as a Linux shell command. Use with caution!");
1943 s->writeString(pfx,
"shell <string> - execute <string> as a Linux shell command. Use with caution!");
1944 s->writeString(pfx,
"shellstart - execute all subsequent commands as Linux shell commands. Use with caution!");
1945 s->writeString(pfx,
"shellstop - stop executing all subsequent commands as Linux shell commands.");
1948 s->writeString(pfx,
"dnnget <key> - download and install a DNN from JeVois Model Converter");
1951#ifdef JEVOIS_PLATFORM
1952 s->writeString(pfx,
"restart - restart the JeVois smart camera");
1955#ifndef JEVOIS_PLATFORM_A33
1956 s->writeString(pfx,
"quit - quit this program");
1961void jevois::Engine::modCmdInfo(std::shared_ptr<UserInterface> s, std::string
const & pfx)
1965 std::stringstream css; itsModule->supportedCommands(css);
1966 for (std::string line; std::getline(css, line); ) s->writeString(pfx, line);
1980 if (str ==
"shellstop") { itsShellMode =
false;
return true; }
1984 for (std::string
const & r : rvec) s->writeString(pfx, r);
2000 switch (str.length())
2003 LDEBUG(
"Ignoring empty string");
return true;
2007 if (str[0] ==
'~') {
LDEBUG(
"Ignoring modem config command [~]");
return true; }
2011 if (str[0] ==
'#') { sendSerial(str,
true);
return true; }
2017 if (str[0] ==
'~') {
LDEBUG(
"Ignoring modem config command [" << str <<
']');
return true; }
2020 if (str[0] ==
'A' && str[1] ==
'T') {
LDEBUG(
"Ignoring AT command [" << str <<
']');
return true; }
2024 if (str[0] ==
'#') { sendSerial(str,
true);
return true; }
2027 std::string cmd, rem;
2030 cmd =
"shell"; rem = str.substr(1);
2035 size_t const idx = str.find(
' ');
2036 if (idx == str.npos) cmd = str;
2037 else { cmd = str.substr(0, idx);
if (idx < str.length()) rem = str.substr(idx+1); }
2044 s->writeString(pfx,
"GENERAL COMMANDS:");
2045 s->writeString(pfx,
"");
2046 cmdInfo(s,
false, pfx);
2047 s->writeString(pfx,
"");
2052 s->writeString(pfx,
"MODULE-SPECIFIC COMMANDS:");
2053 s->writeString(pfx,
"");
2055 s->writeString(pfx,
"");
2059 std::stringstream pss; constructHelpMessage(pss);
2060 for (std::string line; std::getline(pss, line); ) s->writeString(pfx, line);
2063 s->writeString(pfx,
"AVAILABLE CAMERA CONTROLS:");
2064 s->writeString(pfx,
"");
2066 foreachCamCtrl([
this,&pfx,&s](
struct v4l2_queryctrl & qc, std::set<int> & doneids)
2070 std::string hlp = camCtrlHelp(qc, doneids);
2071 if (hlp.empty() ==
false) s->writeString(pfx, hlp);
2078 if (cmd ==
"caminfo")
2081 foreachCamCtrl([
this,&pfx,&s](
struct v4l2_queryctrl & qc, std::set<int> & doneids)
2085 std::string hlp = camCtrlInfo(qc, doneids);
2086 if (hlp.empty() ==
false) s->writeString(pfx, hlp);
2093 if (cmd ==
"cmdinfo")
2095 bool showAll = (rem ==
"all") ?
true :
false;
2096 cmdInfo(s, showAll, pfx);
2101 if (cmd ==
"modcmdinfo")
2108 if (cmd ==
"paraminfo")
2110 std::map<std::string, std::string> categs;
2111 bool skipFrozen = (rem ==
"hot" || rem ==
"modhot") ?
true :
false;
2113 if (rem ==
"mod" || rem ==
"modhot")
2116 if (itsModule) itsModule->paramInfo(s, categs, skipFrozen, instanceName(), pfx);
2121 paramInfo(s, categs, skipFrozen,
"", pfx);
2128 if (cmd ==
"serinfo")
2130 std::string info = getParamStringUnique(
"serout") +
' ' + getParamStringUnique(
"serlog");
2132 info +=
' ' + mod->getParamStringUnique(
"serstyle") +
' ' + mod->getParamStringUnique(
"serprec") +
2133 ' ' + mod->getParamStringUnique(
"serstamp");
2134 else info +=
" - - -";
2136 s->writeString(pfx, info);
2147 std::stringstream css; itsModule->supportedCommands(css);
2148 s->writeString(pfx,
"MODULE-SPECIFIC COMMANDS:");
2149 s->writeString(pfx,
"");
2150 for (std::string line; std::getline(css, line); ) s->writeString(pfx, line);
2151 s->writeString(pfx,
"");
2154 s->writeString(pfx,
"MODULE PARAMETERS:");
2155 s->writeString(pfx,
"");
2158 std::unordered_map<std::string,
2159 std::unordered_map<std::string,
2160 std::vector<std::pair<std::string,
2163 itsModule->populateHelpMessage(
"", helplist);
2165 if (helplist.empty())
2166 s->writeString(pfx,
"None.");
2169 for (
auto const & c : helplist)
2172 s->writeString(pfx, c.first);
2175 for (
auto const & n : c.second)
2177 std::vector<std::string> tok =
jevois::split(n.first,
"[\\r\\n]+");
2179 for (
auto const & t : tok)
2184 auto const & v = n.second;
2187 if (v[0].second.empty())
2188 s->writeString(pfx, t);
2190 s->writeString(pfx, t +
" current=[" + v[0].second +
']');
2192 else if (v.size() > 1)
2194 std::string sss = t +
" current=";
2195 for (
auto const & pp : v)
2196 if (pp.second.empty() ==
false) sss +=
'[' + pp.first +
':' + pp.second +
"] ";
2197 s->writeString(pfx, sss);
2199 else s->writeString(pfx, t);
2205 s->writeString(pfx, t);
2208 s->writeString(pfx,
"");
2213 s->writeString(pfx,
"No module loaded.");
2225 if (itsModule) s->writeString(pfx,
"INFO: " + itsCurrentMapping.str());
2231 if (cmd ==
"setpar")
2233 size_t const remidx = rem.find(
' ');
2234 if (remidx != rem.npos)
2236 std::string
const desc = rem.substr(0, remidx);
2237 if (remidx < rem.length())
2239 std::string
const val = rem.substr(remidx+1);
2240 setParamString(desc, val);
2244 errmsg =
"Need to provide a parameter name and a parameter value in setpar";
2248 if (cmd ==
"getpar")
2250 auto vec = getParamString(rem);
2251 for (
auto const & p : vec) s->writeString(pfx, p.first +
' ' + p.second);
2256 if (cmd ==
"setcam")
2258 std::istringstream ss(rem); std::string ctrl;
int val; ss >> ctrl >> val;
2259 struct v4l2_control c = { }; c.id = camctrlid(ctrl); c.value = val;
2262 if (val == 0 && ctrl ==
"ispsensorpreset")
2264 c.value = 1; itsCamera->setControl(c);
2265 c.value = 0; itsCamera->setControl(c);
2267 else itsCamera->setControl(c);
2273 if (cmd ==
"getcam")
2275 struct v4l2_control c = { }; c.id = camctrlid(rem);
2276 itsCamera->getControl(c);
2277 s->writeString(pfx, rem +
' ' + std::to_string(c.value));
2282 if (cmd ==
"setcamreg")
2286 auto cam = std::dynamic_pointer_cast<jevois::Camera>(itsCamera);
2290 std::istringstream ss(rem); std::string reg, val; ss >> reg >> val;
2291 cam->writeRegister(std::stoi(reg,
nullptr, 0), std::stoi(val,
nullptr, 0));
2294 else errmsg =
"Not using a camera for video input";
2296 else errmsg =
"Access to camera registers is disabled, enable with: setpar camreg true";
2300 if (cmd ==
"getcamreg")
2304 auto cam = std::dynamic_pointer_cast<jevois::Camera>(itsCamera);
2307 unsigned int val = cam->readRegister(std::stoi(rem,
nullptr, 0));
2308 std::ostringstream os; os << std::hex << val;
2309 s->writeString(pfx, os.str());
2312 else errmsg =
"Not using a camera for video input";
2314 else errmsg =
"Access to camera registers is disabled, enable with: setpar camreg true";
2318 if (cmd ==
"setimureg")
2325 std::istringstream ss(rem); std::string reg, val; ss >> reg >> val;
2326 itsIMU->writeRegister(std::stoi(reg,
nullptr, 0), std::stoi(val,
nullptr, 0));
2329 else errmsg =
"No IMU driver loaded";
2331 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2335 if (cmd ==
"getimureg")
2341 unsigned int val = itsIMU->readRegister(std::stoi(rem,
nullptr, 0));
2342 std::ostringstream os; os << std::hex << val;
2343 s->writeString(pfx, os.str());
2346 else errmsg =
"No IMU driver loaded";
2348 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2352 if (cmd ==
"setimuregs")
2360 if (v.size() < 3) errmsg =
"Malformed arguments, need at least 3";
2363 unsigned short reg = std::stoi(v[0],
nullptr, 0);
2364 size_t num = std::stoi(v[1],
nullptr, 0);
2365 if (num > 32) errmsg =
"Maximum transfer size is 32 bytes";
2366 else if (num != v.size() - 2) errmsg =
"Incorrect number of data bytes, should pass " + v[1] +
" values.";
2369 unsigned char data[32];
2370 for (
size_t i = 2; i < v.size(); ++i) data[i-2] = std::stoi(v[i],
nullptr, 0) & 0xff;
2372 itsIMU->writeRegisterArray(reg, data, num);
2377 else errmsg =
"No IMU driver loaded";
2379 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2383 if (cmd ==
"getimuregs")
2389 std::istringstream ss(rem); std::string reg, num; ss >> reg >> num;
2390 int n = std::stoi(num,
nullptr, 0);
2392 if (n > 32) errmsg =
"Maximum transfer size is 32 bytes";
2395 unsigned char data[32];
2396 itsIMU->readRegisterArray(std::stoi(reg,
nullptr, 0), data, n);
2398 std::ostringstream os; os << std::hex;
2399 for (
int i = 0; i < n; ++i) os << (
unsigned int)(data[i]) <<
' ';
2400 s->writeString(pfx, os.str());
2404 else errmsg =
"No IMU driver loaded";
2406 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2410 if (cmd ==
"setdmpreg")
2417 std::istringstream ss(rem); std::string reg, val; ss >> reg >> val;
2418 itsIMU->writeDMPregister(std::stoi(reg,
nullptr, 0), std::stoi(val,
nullptr, 0));
2421 else errmsg =
"No IMU driver loaded";
2423 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2427 if (cmd ==
"getdmpreg")
2433 unsigned int val = itsIMU->readDMPregister(std::stoi(rem,
nullptr, 0));
2434 std::ostringstream os; os << std::hex << val;
2435 s->writeString(pfx, os.str());
2438 else errmsg =
"No IMU driver loaded";
2440 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2444 if (cmd ==
"setdmpregs")
2452 if (v.size() < 3) errmsg =
"Malformed arguments, need at least 3";
2455 unsigned short reg = std::stoi(v[0],
nullptr, 0);
2456 size_t num = std::stoi(v[1],
nullptr, 0);
2457 if (num > 32) errmsg =
"Maximum transfer size is 32 bytes";
2458 else if (num != v.size() - 2) errmsg =
"Incorrect number of data bytes, should pass " + v[1] +
" values.";
2461 unsigned char data[32];
2462 for (
size_t i = 2; i < v.size(); ++i) data[i-2] = std::stoi(v[i],
nullptr, 0) & 0xff;
2464 itsIMU->writeDMPregisterArray(reg, data, num);
2469 else errmsg =
"No IMU driver loaded";
2471 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2475 if (cmd ==
"getdmpregs")
2481 std::istringstream ss(rem); std::string reg, num; ss >> reg >> num;
2482 int n = std::stoi(num,
nullptr, 0);
2484 if (n > 32) errmsg =
"Maximum transfer size is 32 bytes";
2487 unsigned char data[32];
2488 itsIMU->readDMPregisterArray(std::stoi(reg,
nullptr, 0), data, n);
2490 std::ostringstream os; os << std::hex;
2491 for (
int i = 0; i < n; ++i) os << (
unsigned int)(data[i]) <<
' ';
2492 s->writeString(pfx, os.str());
2496 else errmsg =
"No IMU driver loaded";
2498 else errmsg =
"Access to IMU registers is disabled, enable with: setpar imureg true";
2502 if (cmd ==
"listmappings")
2504 s->writeString(pfx,
"AVAILABLE VIDEO MAPPINGS:");
2505 s->writeString(pfx,
"");
2506 for (
size_t idx = 0; idx < itsMappings.size(); ++idx)
2508 std::string idxstr = std::to_string(idx);
2509 if (idxstr.length() < 5) idxstr = std::string(5 - idxstr.length(),
' ') + idxstr;
2510 s->writeString(pfx, idxstr +
" - " + itsMappings[idx].str());
2516 if (cmd ==
"setmapping")
2518 size_t const idx = std::stoi(rem);
2520 if (itsStreaming.load() && itsCurrentMapping.ofmt)
2521 errmsg =
"Cannot set mapping while streaming: Stop your webcam program on the host computer first.";
2522 else if (idx >= itsMappings.size())
2523 errmsg =
"Requested mapping index " + std::to_string(idx) +
" out of range [0 .. " +
2524 std::to_string(itsMappings.size()-1) +
']';
2529 setFormatInternal(idx);
2532 catch (std::exception
const & e) { errmsg =
"Error parsing or setting mapping [" + rem +
"]: " + e.what(); }
2533 catch (...) { errmsg =
"Error parsing or setting mapping [" + rem +
']'; }
2538 if (cmd ==
"setmapping2")
2540 if (itsStreaming.load() && itsCurrentMapping.ofmt)
2541 errmsg =
"Cannot set mapping while streaming: Stop your webcam program on the host computer first.";
2547 setFormatInternal(m);
2550 catch (std::exception
const & e) { errmsg =
"Error parsing or setting mapping [" + rem +
"]: " + e.what(); }
2551 catch (...) { errmsg =
"Error parsing or setting mapping [" + rem +
']'; }
2556 if (cmd ==
"reload")
2558 setFormatInternal(itsCurrentMapping,
true);
2563 if (itsCurrentMapping.ofmt == 0 || itsCurrentMapping.ofmt ==
JEVOISPRO_FMT_GUI || itsManualStreamon)
2565 if (cmd ==
"streamon")
2568 itsCamera->streamOn();
2569 itsGadget->streamOn();
2570 itsStreaming.store(
true);
2574 if (cmd ==
"streamoff")
2577 itsGadget->abortStream();
2578 itsCamera->abortStream();
2580 itsStreaming.store(
false);
2582 itsGadget->streamOff();
2583 itsCamera->streamOff();
2591 s->writeString(pfx,
"ALIVE");
2596 if (cmd ==
"serlog")
2598 sendSerial(rem,
true);
2603 if (cmd ==
"serout")
2605 sendSerial(rem,
false);
2610#ifdef JEVOIS_PLATFORM_A33
2613 if (itsStreaming.load())
2615 errmsg =
"Cannot export microSD over USB while streaming: ";
2616 if (itsCurrentMapping.ofmt) errmsg +=
"Stop your webcam program on the host computer first.";
2617 else errmsg +=
"Issue a 'streamoff' command first.";
2621 startMassStorageMode();
2630 if (std::system(
"sync")) errmsg =
"Disk sync failed";
2638 s->writeString(pfx,
"date now " + dat.substr(0, dat.size()-1));
2643 if (cmd ==
"runscript")
2645 std::string
const fname = itsModule ? itsModule->absolutePath(rem).string() : rem;
2647 try { runScriptFromFile(fname, s,
true);
return true; }
2648 catch (...) { errmsg =
"Script " + fname +
" execution failed"; }
2656 for (std::string
const & r : rvec) s->writeString(pfx, r);
2661 if (cmd ==
"shellstart")
2663 itsShellMode =
true;
2670 if (cmd ==
"dnnget")
2672 if (rem.length() != 4 || std::regex_match(rem, std::regex(
"^[a-zA-Z0-9]+$")) ==
false)
2673 errmsg =
"Key must be a 4-character alphanumeric string, as emailed to you by the model converter.";
2677 s->writeString(pfx,
"Downloading custom DNN model " + rem +
" ...");
2678 std::string
const zip = rem +
".zip";
2682 for (std::string
const & r : rvec) s->writeString(pfx, r);
2686 if (ifs.is_open() ==
false)
2687 errmsg =
"Failed to download. Check network connectivity and available disk space.";
2691 s->writeString(pfx,
"Unpacking custom DNN model " + rem +
" ...");
2694 rvec =
jevois::split(ret,
"\n");
for (std::string
const & r : rvec) s->writeString(pfx, r);
2697 rvec =
jevois::split(ret,
"\n");
for (std::string
const & r : rvec) s->writeString(pfx, r);
2699 s->writeString(pfx,
"Reload your model zoo for changes to take effect.");
2708 if (cmd ==
"fileget")
2710 std::shared_ptr<jevois::Serial> ser = std::dynamic_pointer_cast<jevois::Serial>(s);
2712 errmsg =
"File transfer only supported over USB or Hard serial ports";
2715 std::string
const abspath = itsModule ? itsModule->absolutePath(rem).string() : rem;
2716 ser->fileGet(abspath);
2722 if (cmd ==
"fileput")
2724 std::shared_ptr<jevois::Serial> ser = std::dynamic_pointer_cast<jevois::Serial>(s);
2726 errmsg =
"File transfer only supported over USB or Hard serial ports";
2729 std::string
const abspath = itsModule ? itsModule->absolutePath(rem).string() : rem;
2730 ser->filePut(abspath);
2731 if (std::system(
"sync")) { }
2736#ifdef JEVOIS_PLATFORM
2738 if (cmd ==
"restart")
2740 s->writeString(pfx,
"Restart command received - bye-bye!");
2742 if (itsStreaming.load())
2743 s->writeString(pfx,
"ERR Video streaming is on - you should quit your video viewer before rebooting");
2745 if (std::system(
"sync")) s->writeString(pfx,
"ERR Disk sync failed -- IGNORED");
2747#ifdef JEVOIS_PLATFORM_A33
2751 if (std::system(
"sync")) s->writeString(pfx,
"ERR Disk sync failed -- IGNORED");
2761#ifndef JEVOIS_PLATFORM_A33
2765 s->writeString(pfx,
"Quit command received - bye-bye!");
2776 if (errmsg.size())
throw std::runtime_error(
"Command error [" + str +
"]: " + errmsg);
2787 std::ifstream ifs(filename);
2788 if (!ifs) {
if (throw_no_file)
LFATAL(
"Could not open file " << filename);
else return; }
2794 if (itsSerials.empty())
LFATAL(
"Need at least one active serial to run script");
2796 switch (serlog::get())
2798 case jevois::engine::SerPort::Hard:
2802 case jevois::engine::SerPort::USB:
2814 if (!ser) ser = itsSerials.front();
2819 for (std::string line; std::getline(ifs, line); )
2827 if (line.length() == 0 || line[0] ==
'#')
continue;
2832 bool parsed =
false;
2833 try { parsed = parseCommand(line, ser); }
2834 catch (std::exception
const & e)
2835 { ser->writeString(
"ERR " + filename +
':' + std::to_string(linenum) +
": " + e.what()); }
2837 { ser->writeString(
"ERR " + filename +
':' + std::to_string(linenum) +
": Bogus command ["+line+
"] ignored"); }
2839 if (parsed ==
false)
2843 try { itsModule->parseSerial(line, ser); }
2844 catch (std::exception
const & me)
2845 { ser->writeString(
"ERR " + filename +
':' + std::to_string(linenum) +
": " + me.what()); }
2847 { ser->writeString(
"ERR " + filename +
':' + std::to_string(linenum)+
": Bogus command ["+line+
"] ignored"); }
2849 else ser->writeString(
"ERR Unsupported command [" + line +
"] and no module");
2861 ImGui::Columns(2,
"camctrl");
2863 foreachCamCtrl([
this](
struct v4l2_queryctrl & qc, std::set<int> & doneids)
2865 try { camCtrlGUI(qc, doneids); }
catch (...) { }
2872void jevois::Engine::camCtrlGUI(
struct v4l2_queryctrl & qc, std::set<int> & doneids)
2875 itsCamera->queryControl(qc);
2876 qc.id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
2879 if (doneids.find(qc.id) != doneids.end())
return;
else doneids.insert(qc.id);
2882 struct v4l2_control ctrl = { }; ctrl.id = qc.id;
2883 itsCamera->getControl(ctrl);
2886 ImGui::AlignTextToFramePadding();
2887 ImGui::TextUnformatted(
reinterpret_cast<char const *
>(qc.name));
2888 ImGui::NextColumn();
2891 if (qc.flags & V4L2_CTRL_FLAG_DISABLED)
2893 ImGui::PushItemFlag(ImGuiItemFlags_Disabled,
true);
2894 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
2898 static char wname[16]; snprintf(wname, 16,
"##c%d", ctrl.id);
2903 case V4L2_CTRL_TYPE_INTEGER:
2904 case V4L2_CTRL_TYPE_INTEGER_MENU:
2907 long range = long(qc.maximum) - long(qc.minimum);
2908 if (range > 1 && range < 5000)
2910 if (ImGui::SliderInt(wname, &ctrl.value, qc.minimum, qc.maximum)) itsCamera->setControl(ctrl);
2915 if (ImGui::InputInt(wname, &ctrl.value, qc.step, qc.step * 2)) itsCamera->setControl(ctrl);
2932 case V4L2_CTRL_TYPE_BOOLEAN:
2934 bool checked = (ctrl.value != 0);
2935 if (ImGui::Checkbox(wname, &checked)) { ctrl.value = checked ? 1 : 0; itsCamera->setControl(ctrl); }
2940 case V4L2_CTRL_TYPE_BUTTON:
2941 static char bname[16]; snprintf(bname, 16,
"Go##%d", ctrl.id);
2942 if (ImGui::Button(bname)) { ctrl.value = 1; itsCamera->setControl(ctrl); }
2945 case V4L2_CTRL_TYPE_BITMASK:
2949 case V4L2_CTRL_TYPE_MENU:
2951 struct v4l2_querymenu querymenu = { };
2952 querymenu.id = qc.id;
2953 char * items[qc.maximum - qc.minimum + 1];
2955 for (querymenu.index = qc.minimum; querymenu.index <= (
unsigned int)qc.maximum; ++querymenu.index)
2957 try { itsCamera->queryMenu(querymenu); }
catch (...) { strncpy((
char *)querymenu.name,
"fixme", 32); }
2958 items[querymenu.index] =
new char[32];
2959 strncpy(items[querymenu.index], (
char const *)querymenu.name, 32);
2962 int idx = ctrl.value - qc.minimum;
2963 if (ImGui::Combo(wname, &idx, items, qc.maximum - qc.minimum + 1))
2964 { ctrl.value = qc.minimum + idx; itsCamera->setControl(ctrl); }
2966 for (
int i = qc.minimum; i <= qc.maximum; ++i)
delete [] items[i];
2976 static char rname[16]; snprintf(rname, 16,
"Reset##%d", ctrl.id);
2978 if (ImGui::Button(rname)) { ctrl.value = qc.default_value; itsCamera->setControl(ctrl); }
2982 if (qc.flags & V4L2_CTRL_FLAG_DISABLED)
2984 ImGui::PopItemFlag();
2985 ImGui::PopStyleVar();
2989 ImGui::NextColumn();
2999 std::lock_guard<std::mutex> _(itsPyRegMtx);
3000 auto itr = itsPythonRegistry.find(pyinst);
3001 if (itr != itsPythonRegistry.end())
LFATAL(
"Trying to register twice -- ABORT");
3002 itsPythonRegistry.insert(std::make_pair(pyinst, comp));
3009 std::lock_guard<std::mutex> _(itsPyRegMtx);
3010 auto itr = itsPythonRegistry.begin(), stop = itsPythonRegistry.end();
3011 while (itr != stop)
if (itr->second == comp) itr = itsPythonRegistry.erase(itr);
else ++itr;
3017 LDEBUG(std::hex << pyinst);
3018 std::lock_guard<std::mutex> _(itsPyRegMtx);
3019 auto itr = itsPythonRegistry.find(pyinst);
3020 if (itr == itsPythonRegistry.end())
LFATAL(
"Python instance not registered -- ABORT");
#define JEVOIS_USBSD_FILE
Disk partition or file that we can export over USB using Engine command 'usbsd'.
#define JEVOIS_CUSTOM_DNN_URL
URL where custom converted DNN models can be downloaded:
#define JEVOIS_MODULE_PARAMS_FILENAME
Relative name of optinal default parameters to load for each Module.
#define JEVOIS_VERSION_STRING
Software version, as string.
#define JEVOIS_USBSD_SYS
Sysfs location to change the exported partition or file over USB using Engine command 'usbsd".
#define JEVOIS_CUSTOM_DNN_PATH
Directory where custom DNN models are stored:
#define JEVOIS_VERSION_MINOR
#define JEVOIS_CONFIG_PATH
Base path for config files.
#define JEVOIS_SHARE_PATH
Base path for shared files (e.g., neural network weights, etc)
#define JEVOIS_VERSION_MAJOR
Variables set by CMake.
#define JEVOISPRO_DEMO_DATA_FILE
Location of the jevois-pro demo data definition file.
#define JEVOIS_ENGINE_INIT_SCRIPT
Location of the engine init script file.
#define JEVOIS_MODULE_SCRIPT_FILENAME
Relative name of an Engine script to load for each Module.
#define V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE
#define V4L2_CTRL_CLASS_DETECT
#define JEVOISPRO_FMT_GUI
JeVois-Pro zero-copy display of camera input frame (to be used as output mode in VideoMapping)
Helper class for camera calibration, which allows some modules to compute 3D locations of objects.
void save(std::string const &fname) const
Save to file.
jevois::CameraLens lens
Camera lens.
int h
Image width and height (camera resolution)
jevois::CameraSensor sensor
Camera sensor.
void load(std::string const &fname)
Load from file.
JeVois camera driver class - grabs frames from a Video4Linux camera sensor.
A component of a model hierarchy.
std::string const & instanceName() const
The instance name of this component.
Class to open shared object (.so) files and load functions contained in them.
Component * getPythonComponent(void *pyinst) const
Get the component registered with a given python instance.
void requestSetFormat(int idx)
Use this to request a format change from within process()
void streamOn()
Start streaming on video from camera, processing, and USB.
void drawCameraGUI()
Draw all camera controls into our GUI.
void nextDemo()
When in demo mode, switch to next demo.
void reboot()
Request a reboot.
void preInit() override
Override of Manager::preInit()
void onParamChange(engine::serialdev const ¶m, std::string const &newval) override
Parameter callback.
void saveCameraCalibration(CameraCalibration const &calib, std::string const &stem="calibration")
Helper to save an OpenCV camera matrix and distortion coeffs for the current running module.
size_t numVideoMappings() const
Return the number of video mappings.
std::shared_ptr< Module > module() const
Get a pointer to our current module (may be null)
void abortDemo()
When in demo mode, abort demo mode.
size_t getDefaultVideoMappingIdx() const
Allow access to the default video mapping index.
void setFormat(size_t idx)
Callback for when the user selects a new output video format.
void unRegisterPythonComponent(Component *comp)
Unregister a component as linked to some python code, used by dynamic params created in python.
void sendSerial(std::string const &str, bool islog=false)
Send a string to all serial ports.
void streamOff()
Stop streaming on video from camera, processing, and USB.
void runScriptFromFile(std::string const &filename, std::shared_ptr< UserInterface > ser, bool throw_no_file)
Run a script from file.
void quit()
Terminate the program.
bool parseCommand(std::string const &str, std::shared_ptr< UserInterface > s, std::string const &pfx="")
Parse a user command received over serial port.
int mainLoop()
Main loop: grab, process, send over USB. Should be called by main application thread.
VideoMapping const & getVideoMapping(size_t idx) const
Allow access to our video mappings which are parsed from file at construction.
size_t getVideoMappingIdx(unsigned int iformat, unsigned int iframe, unsigned int interval) const
Get the video mapping index for a given UVC iformat, iframe and interval.
VideoMapping const & getCurrentVideoMapping() const
Get the current video mapping.
void registerPythonComponent(Component *comp, void *pyinst)
Register a component as linked to some python code, used by dynamic params created in python.
CameraCalibration loadCameraCalibration(std::string const &stem="calibration", bool do_throw=false)
Helper to load an OpenCV camera matrix and distortion coeffs for the current running module.
VideoMapping const & findVideoMapping(unsigned int oformat, unsigned int owidth, unsigned int oheight, float oframespersec) const
Find the VideoMapping that has the given output specs, or throw if not found.
void reloadVideoMappings()
Re-load video mappings from videomappings.cfg.
void postInit() override
Override of Manager::postInit()
std::shared_ptr< Camera > camera() const
Get a pointer to our Camera (may be null, especially if not using a camera but, eg,...
VideoMapping const & getDefaultVideoMapping() const
Allow access to the default video mapping.
void clearErrors()
Clear all errors currently displayed in the JeVois-Pro GUI.
void foreachVideoMapping(std::function< void(VideoMapping const &m)> &&func)
Run a function on every video mapping.
void reportError(std::string const &err)
JeVois gadget driver - exposes a uvcvideo interface to host computer connected over USB.
IMU with I2C interface shared with camera sensor, such as ICM20948 on JeVois-A33 AR0135 camera sensor...
IMU with SPI interface, such as the ICM20948 IMU on the JeVois-Pro IMX290 camera sensor board.
Manager of a hierarchy of Component objects.
void postInit() override
Checks for the –help flag.
void preInit() override
Calls parseCommandLine()
Video output to a movie file, using OpenCV video encoding.
Exception-safe wrapper around a raw image to be sent over USB.
Wrapper module to allow users to develop new modules written in Python.
Base class for a module that supports standardized serial messages.
void sendSerialMarkStop()
Send a message MARK STOP to indicate the end of processing.
void sendSerialMarkStart()
Send a message MARK START to indicate the beginning of processing.
Video output to local screen.
Video output to local screen with basic GUI.
Video output to local screen.
No-op VideoOutput derivative for when there is no video output.
bool sensorHasIMU(CameraSensor s)
Check whether sensor has an IMU (inertial measurement unit)
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level.
#define LDEBUG(msg)
Convenience macro for users to print out console or syslog messages, DEBUG level.
#define JEVOIS_TIMED_LOCK(mtx)
Helper macro to create a timed_lock_guard object.
void logSetEngine(Engine *e)
Set an Engine so that all log messages will be forwarded to its serial ports.
std::string getSysInfoCPU()
Get CPU info: frequency, thermal, load.
std::string warnAndIgnoreException(std::string const &prefix="")
Convenience function to catch an exception, issue some LERROR (depending on type),...
#define JEVOIS_TRACE(level)
Trace object.
std::string getSysInfoMem()
Get memory info.
std::string getSysInfoVersion()
Get O.S. version info.
#define LERROR(msg)
Convenience macro for users to print out console or syslog messages, ERROR level.
#define LINFO(msg)
Convenience macro for users to print out console or syslog messages, INFO level.
void setEngine(jevois::Engine *e)
Initialize Python, numpy, and allow python modules to send serial outputs through the JeVois Engine.
std::string strip(std::string const &str)
Strip white space (including CR, LF, tabs, etc) from the end of a string.
std::string getFileString(char const *fname, int skip=0)
Read one line from a file and return it as a string.
std::string system(std::string const &cmd, bool errtoo=true)
Execute a command and grab stdout output to a string.
bool stringStartsWith(std::string const &str, std::string const &prefix)
Return true if str starts with prefix (including if both strings are equal)
std::string fccstr(unsigned int fcc)
Convert a V4L2 four-cc code (V4L2_PIX_FMT_...) to a 4-char string.
std::vector< std::string > split(std::string const &input, std::string const ®ex="\\s+")
Split string into vector of tokens using a regex to specify what to split on; default regex splits by...
std::string to_string(T const &val)
Convert from type to string.
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async_little(Function &&f, Args &&... args)
Async execution using a thread pool.
Main namespace for all JeVois classes and functions.
void drawErrorImage(std::string const &errmsg, RawImage &videoerrimg)
Display an error message into a RawImage.
Simple struct to hold video mapping definitions for the processing Engine.
std::string modulename
Name of the Module that will process this mapping.
std::string ostr() const
Convenience function to print out FCC WxH @ fps, for the output (UVC) format.
std::string str() const
Convenience function to print out the whole mapping in a human-friendly way.
std::string cstrall() const
Convenience function to print out FCC WxH @ fps plus possibly second stream, for the input (camera) f...
bool ispython
True if the module is written in Python; affects behavior of sopath() only.
float ofps
output frame rate in frames/sec
bool isSameAs(VideoMapping const &other) const
Equality operator for specs and also vendor or module name.
unsigned int uvcformat
USB-UVC format number (1-based)
static float uvcToFps(unsigned int interval)
Convert from USB/UVC interval to fps.
unsigned int uvcframe
USB UVC frame number (1-based)
std::string sopath(bool delete_old_versions=false) const
Return the full absolute path and file name of the module's .so or .py file.
bool match(unsigned int oformat, unsigned int owidth, unsigned int oheight, float oframespersec) const
Return true if this VideoMapping's output format is a match to the given output parameters.