JeVois  1.20
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Engine.H
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4 // California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5 //
6 // This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7 // redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8 // Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10 // License for more details. You should have received a copy of the GNU General Public License along with this program;
11 // if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 //
13 // Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14 // Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 /*! \file */
17 
18 #pragma once
19 
22 #include <jevois/Types/Enum.H>
23 #include <jevois/Image/RawImage.H>
25 #include <jevois/Debug/Watchdog.H>
26 
27 #include <memory>
28 #include <mutex>
29 #include <vector>
30 #include <list>
31 #include <atomic>
32 
33 // #################### Platform mode config:
34 #ifdef JEVOIS_PLATFORM
35 
36 #if defined(JEVOIS_A33)
37 // ########## JeVois-A33 platform:
38 
39 // On the JeVois-A33 platform, we use a gadget driver by default to send output frames over USB, one hardware serial
40 // driver, and one serial-over-USB driver:
41 
42 //! On platform hardware, device for the camera sensor
43 #define JEVOIS_CAMERA_DEFAULT "/dev/video0"
44 
45 //! On platform hardware, device for the USB gadget driver (which sends video frames over USB to a host computer)
46 #define JEVOIS_GADGET_DEFAULT "/dev/video1"
47 
48 //! On platform hardware, device for the 4-pin hardware serial port
49 #define JEVOIS_SERIAL_DEFAULT "/dev/ttyS0"
50 
51 //! On platform hardware, device for serial-over-USB port
52 #define JEVOIS_USBSERIAL_DEFAULT "/dev/ttyGS0"
53 
54 //! Default camera sensor
55 #define JEVOIS_CAMERASENS_DEFAULT CameraSensor::ov9650
56 
57 //! Default IMU spi device
58 #define JEVOIS_IMUSPI_DEFAULT ""
59 
60 #elif defined(JEVOIS_PRO)
61 // ########## JeVois-Pro platform:
62 
63 // On the JeVois-Pro platform, we have no gadget for now (which will trigger displaying output frames to a window), one
64 // hardware serial driver, and not yet one serial-over-USB driver:
65 
66 //! On platform hardware, device for the camera sensor
67 #define JEVOIS_CAMERA_DEFAULT "/dev/video0"
68 
69 //! On platform hardware, device for the USB gadget driver (which sends video frames over USB to a host computer)
70 #define JEVOIS_GADGET_DEFAULT ""
71 
72 //! On platform hardware, device for the 4-pin hardware serial port
73 #define JEVOIS_SERIAL_DEFAULT "/dev/ttyS4"
74 
75 //! On platform hardware, device for serial-over-USB port
76 #define JEVOIS_USBSERIAL_DEFAULT ""
77 //#define JEVOIS_USBSERIAL_DEFAULT "/dev/ttyGS0"
78 
79 //! Default camera sensor
80 #define JEVOIS_CAMERASENS_DEFAULT CameraSensor::any
81 
82 //! Default IMU spi device
83 #define JEVOIS_IMUSPI_DEFAULT "/dev/spidev32766.0"
84 
85 #else
86 #error "Neither JEVOIS_A33 nor JEVOIS_PRO defined -- ABORT"
87 #endif
88 
89 #else // JEVOIS_PLATFORM
90 // #################### Host mode config:
91 
92 // On the host, we have no gadget (which will trigger displaying output frames to a window) and we use the terminal in
93 // which jevois-daemon was started for serial commands:
94 
95 //! On generic computer hardware, device for the camera sensor
96 #define JEVOIS_CAMERA_DEFAULT "/dev/video0"
97 
98 //! On generic computer hardware, device for the USB gadget driver should always be empty
99 #define JEVOIS_GADGET_DEFAULT ""
100 
101 //! On generic computer hardware, device for serial port should always be stdio to use an StdioInterface
102 #define JEVOIS_SERIAL_DEFAULT "stdio"
103 
104 //! On generic computer hardware, device for the serial-over-USB port should always be empty
105 #define JEVOIS_USBSERIAL_DEFAULT ""
106 
107 //! Default IMU spi device
108 #define JEVOIS_IMUSPI_DEFAULT ""
109 
110 #ifdef JEVOIS_PRO
111 //! Default camera sensor
112 #define JEVOIS_CAMERASENS_DEFAULT CameraSensor::imx290
113 #else
114 //! Default camera sensor
115 #define JEVOIS_CAMERASENS_DEFAULT CameraSensor::ov9650
116 #endif
117 
118 #endif // JEVOIS_PLATFORM
119 
120 namespace jevois
121 {
122  class VideoInput;
123  class VideoOutput;
124  class Module;
125  class DynamicLoader;
126  class UserInterface;
127  class GUIhelper;
128  class GUIconsole;
129  class Camera;
130  class IMU;
131 
132  namespace engine
133  {
134  static ParameterCategory const ParamCateg("Engine Options");
135 
136  //! Parameter \relates jevois::Engine
137  JEVOIS_DECLARE_PARAMETER(cameradev, std::string, "Camera device name (if starting with /dev/v...), or movie "
138  "file name (e.g., movie.mpg) or image sequence (e.g., im%02d.jpg, to read frames "
139  "im00.jpg, im01.jpg, etc).",
140  JEVOIS_CAMERA_DEFAULT, ParamCateg);
141 
142  //! Parameter \relates jevois::Engine
143  JEVOIS_DECLARE_PARAMETER(camerasens, CameraSensor, "Camera sensor. Users would usually not set this parameter "
144  "manually, it is set through boot-time configuration.",
145  JEVOIS_CAMERASENS_DEFAULT, CameraSensor_Values, ParamCateg);
146 
147  JEVOIS_DECLARE_PARAMETER(imudev, std::string, "IMU SPI device name, typically starting with /dev/spidev..., "
148  "or empty if device does not have an IMU with SPI interface.",
149  JEVOIS_IMUSPI_DEFAULT, ParamCateg);
150 
151  //! Parameter \relates jevois::Engine
152  JEVOIS_DECLARE_PARAMETER(cameranbuf, unsigned int, "Number of video input (camera) buffers, or 0 for automatic.",
153  0, ParamCateg);
154 
155  //! Parameter \relates jevois::Engine
156  JEVOIS_DECLARE_PARAMETER(gadgetdev, std::string, "Gadget device name. This is used on platform hardware only. "
157  "On host hardware, a display window will be used unless gadgetdev is None (useful "
158  "for benchmarking) or is a file stem for a movie file that does not start with /dev/ "
159  "(and which should contain a printf-style directive for a single int argument, "
160  "the movie number).",
161  JEVOIS_GADGET_DEFAULT, ParamCateg);
162 
163  //! Parameter \relates jevois::Engine
164  JEVOIS_DECLARE_PARAMETER(gadgetnbuf, unsigned int, "Number of video output (USB video) buffers, or 0 for auto",
165  0, ParamCateg);
166 
167  //! Parameter \relates jevois::Engine
168  JEVOIS_DECLARE_PARAMETER(videomapping, int, "Index of Video Mapping to use, or -1 to use the default mapping. "
169  "Note that this parameter is only available when parsing command-line arguments. "
170  "At runtime, the setmapping command should be used instead.",
171  -1, ParamCateg);
172 
173  //! Parameter \relates jevois::Engine
174  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(serialdev, std::string, "Hardware (4-pin connector) serial device name, "
175  "or 'stdio' to use the console, or empty for no hardware serial port",
176  JEVOIS_SERIAL_DEFAULT, ParamCateg);
177 
178  //! Parameter \relates jevois::Engine
179  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(usbserialdev, std::string, "Over-the-USB serial device name, or empty",
180  JEVOIS_USBSERIAL_DEFAULT, ParamCateg);
181 
182  //! Parameter \relates jevois::Engine
183  JEVOIS_DECLARE_PARAMETER(camreg, bool, "Enable raw access to camera registers through setcamreg and getcamreg",
184  false, ParamCateg);
185 
186  //! Parameter \relates jevois::Engine
187  JEVOIS_DECLARE_PARAMETER(imureg, bool, "Enable raw access to IMU registers through setimureg and getimureg",
188  false, ParamCateg);
189 
190  //! Parameter \relates jevois::Engine
191  JEVOIS_DECLARE_PARAMETER(camturbo, bool, "Enable camera turbo mode by relaxing the need for DMA-coherent video "
192  "buffer memory. This can accelerate severalfolds access to the captured image data, but "
193  "it may also yield stripe artifacts with some modules, such as PassThrough. The stripes "
194  "are pieces of incorrect data in the cache. You should experiment with each particular "
195  "module. Turbo mode is not recommended for any production-grade application.",
196  false, ParamCateg);
197 
198  //! Enum for Parameter \relates jevois::Engine
199  JEVOIS_DEFINE_ENUM_CLASS(SerPort, (None) (All) (Hard) (USB) );
200 
201  //! Parameter \relates jevois::Engine
202  JEVOIS_DECLARE_PARAMETER(serlog, SerPort, "Show log and debug messages on selected serial port(s)",
203  SerPort::None, SerPort_Values, ParamCateg);
204 
205  //! Parameter \relates jevois::Engine
206  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(videoerrors, bool, "Show any machine vision module errors (exceptions) "
207  "in the video stream. Only takes effect if streaming video to USB.",
208  true, ParamCateg);
209 
210  //! Parameter \relates jevois::Engine
211  JEVOIS_DECLARE_PARAMETER(serout, SerPort, "Send module serial messages to selected serial port(s)",
212  SerPort::None, SerPort_Values, ParamCateg);
213 
214  //! Enum for Parameter \relates jevois::Engine
215  JEVOIS_DEFINE_ENUM_CLASS(CPUmode, (PowerSave) (Conservative) (OnDemand) (Interactive) (Performance) );
216 
217  //! Parameter \relates jevois::Engine
218  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(cpumode, CPUmode, "CPU frequency modulation mode"
219 #ifdef JEVOIS_PRO
220  " for A73 big cores"
221 #endif
222  , CPUmode::Performance, CPUmode_Values, ParamCateg);
223 
224 #ifdef JEVOIS_PRO
225  //! Parameter \relates jevois::Engine
226  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(cpumodel, CPUmode, "CPU frequency modulation mode for A53 little cores",
227  CPUmode::Performance, CPUmode_Values, ParamCateg);
228 #endif
229 
230  //! Parameter \relates jevois::Engine
231  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(cpumax, unsigned int, "CPU maximum frequency in MHz"
232 #ifdef JEVOIS_PRO
233  ". To enable overclock frequencies above 2208 MHz, you need to first edit "
234  "/boot/env.txt and change max_freq_a73, then reboot. Use with caution!"
235 #endif
236 #ifdef JEVOIS_A33
237  // keep this in sync with sunxi-cpufreq.c
238  , 1344, { 120, 240, 312, 408, 480, 504, 600, 648, 720, 816, 912, 1008,
239  1044, 1056, 1080, 1104, 1116, 1152, 1200, 1224, 1248, 1296, 1344 },
240 #else
241  // keep this in sync with device tree
242  // A73 cores
243  , 2208, { 500, 667, 1000, 1200, 1398, 1512, 1608, 1704, 1800, 1908, 2016,
244  2100, 2208, 2304, 2400 },
245  // A53 cores
246  //1800, { 500, 667, 1000, 1200, 1398, 1512, 1608, 1704, 1800, 1908, 2016,
247  // 2100, 2208 },
248 #endif
249  ParamCateg);
250 #ifdef JEVOIS_PRO
251  //! Parameter \relates jevois::Engine
252  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(cpumaxl, unsigned int, "CPU maximum frequency in MHz, for A53 little cores. "
253  "To enable overclock frequencies above 1800 MHz, you need to first edit "
254  "/boot/env.txt and change max_freq_a53, then reboot. Use with caution!",
255  // keep this in sync with device tree
256  1800, { 500, 667, 1000, 1200, 1398, 1512, 1608, 1704, 1800, 1908, 2016,
257  2100, 2208 },
258  ParamCateg);
259 #endif
260 
261  //! Parameter \relates jevois::Engine
262  JEVOIS_DECLARE_PARAMETER(multicam, bool, "Allow up to 3 JeVois cameras on one USB bus. Enabling this "
263  "reduces the amount of USB bandwidth used by each JeVois camera, from 3kb "
264  "per USB isochronous microframe to 1kb. All 3 JeVois cameras must have this "
265  "option enabled, and the JeVois linux kernel module should also have "
266  "been loaded with multicam on.",
267  false, ParamCateg);
268 
269  //! Parameter \relates jevois::Engine
270  JEVOIS_DECLARE_PARAMETER(quietcmd, bool, "When true, do not issue a message 'OK' after every correct command "
271  "received at the command-line interface. Recommended for advanced users only.",
272  false, ParamCateg);
273 
274  //! Parameter \relates jevois::Engine
275  JEVOIS_DECLARE_PARAMETER(python, bool, "When true, enable support for modules written in Python. Otherwise, "
276  "attempting to load a python module will throw an exception. Disabling python saves "
277  "a lot of memory and may be useful when using C++ modules that run large deep neural "
278  "networks.",
279  true, ParamCateg);
280 
281  //! Parameter \relates jevois::Engine
282  JEVOIS_DECLARE_PARAMETER(serlimit, size_t, "Maximum number of serial messages that can be sent by a module "
283  "using sendSerial(), for each video frame, or 0 for no limit. Any message sent by "
284  "the module beyond the first serlimit ones will be dropped. This is useful to avoid "
285  "overloading the serial link, for example in case one is running a ArUco detector and "
286  "a large number of ArUco tags are present in the field of view of JeVois.",
287  0, ParamCateg);
288 
289 #ifdef JEVOIS_PRO
290  //! Parameter \relates jevois::Engine
291  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(gui, bool, "Use a graphical user interface instead of plain display "
292  "when true",
293  true, ParamCateg);
294  //! Parameter \relates jevois::Engine
295  JEVOIS_DECLARE_PARAMETER(conslock, bool, "Lock the console and capture the keyboard and mouse to avoid "
296  "interference, only effective on JeVois-Pro Platform, otherwise ignored. Set conslock "
297  "to false if you are experiencing hard crashes and want to run jevoispro-daemon in gdb.",
298  true, ParamCateg);
299 
300  //! Parameter \relates jevois::Engine
301  JEVOIS_DECLARE_PARAMETER(watchdog, double, "Timeout in seconds after which we kill this process if the main loop "
302  "is stuck somehow, or 0.0 for no watchdog",
303  10.0, ParamCateg);
304 
305  //! Parameter \relates jevois::Engine
306  JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(demomode, float, "Show a demonstration of some available JeVois-Pro "
307  "machine vision modules, cycling to the next modules after a number "
308  "of seconds specified by this parameter (or 0.0 for no demo mode).",
309  0.0F, ParamCateg);
310 #endif
311  }
312 
313  //! JeVois processing engine - gets images from camera sensor, processes them, and sends results over USB
314  /*! The Engine is orchestrating the execution of vision processing software. It is a Manager, i.e., it is the root of
315  a hierarchy of Component objects and it handles access to their Parameter settings and their construction, init(),
316  unInit(), and destruction. The component hierarchy consists of Engine at the root, then one Module which is
317  selected by the user at runtime, e.g., by selecting a given video format on video camera software running on a
318  host computer connected to the JeVois hardware. The Module may then contain an arbitrarily complex hierarchy of
319  Component objects with Parameter settings in them. Module derives from Component and thus may also have its own
320  Parameter settings.
321 
322  Engine contains the following basic elements:
323 
324  - A VideoInput, instantiated as either a Camera for live video streaming or a MovieInput for processing of
325  pre-recorded video files or sequences of images (useful during algorithm development, to test and optimize on
326  reproducible inputs);
327 
328  - A VideoOutput, instantiated either as a USB Gadget driver when running on the JeVois hardware platform, or as a
329  VideoDisplay when running on a computer that has a graphics display, or as a MovieOutput to save output video
330  frames to disk, or as a VideoOutputNone if desired for benchmarking of vision algorithms while discounting any
331  work related to transmitting output frames.
332 
333  - A DynamicLoader which handles loading the chosen vision processing Module at runtime depending on user
334  selections;
335 
336  - Any number of UserInterface objects, instantiated as either a hardware Serial port (for the 4-pin JST 1.0mm
337  connector on the platform hardware), a serial-over-USB Serial port (visible on the host computer to which the
338  JeVois hardware is connected by USB), or an StdioInterface (used to accept commands and print results directly
339  in the terminal where the JeVois Engine was started, particularly useful when running on a generic computer as
340  opposed to the platform hardware). When running on platform hardware, usually two UserInterface objects are
341  created (one hardware Serial, one serial-over-USB Serial), while, when running on a generic computer, usually
342  only one UserInterface is created (of type StdioInterface to accept commands directly in the terminal in which
343  the jevois-daemon was started);
344 
345  - The list of VideoMapping definitions imported from your videomappings.cfg file. These definitions specify which
346  video output modes are available over USB and their corresponding Camera settings and which Module to use, as
347  well as which modes are available that do not have any sreaming video output over USB (e.g., when connecting the
348  hardware platform to an Arduino only).
349 
350  The main loop of Engine runs until the user decides to quit, and basically goes through the following steps:
351 
352  - Create an InputFrame object which is an exception-safe wrapper around the next available Camera frame. The frame
353  may not have been captured yet. The InputFrame can be understood as a mechanism to gain access to that frame in
354  the future, when it has become available (i.e., has been captured by the camera). This is very similar to the
355  std::future framework of C++11.
356 
357  - When the current VideoMapping specifies that we will be streaming video frames out over USB, also create an
358  OutputFrame object which is an exception-safe wrapper around the next available Gadget frame. This is also just
359  a mechanism for gaining access to the next blank video buffer that is available from the USB driver and that we
360  should fill with interesting pixel data before sending it over USB to a host computer.
361 
362  - Call the currently-loaded Module's process() function, either as process(InputFrame, OutputFrame) when the
363  current VideoMapping specifies that some video output is to be sent over USB, or as process(InputFrame) when the
364  current VideoMapping specifies no video output. Any exception thrown by the Module's process() function will be
365  caught, reported, and ignored. The process() function would typically request the next available camera image
366  through the InputFrame wrapper (this request may block until the frame has been captured by the camera sensor
367  hardware), process that image, request the next available output image through the OutputFrame wrapper (when
368  VideoMapping specifies that there is USB video output), and paint some results into that output image, which
369  will then be sent to the host coputer over USB, for display by some webcam program or for further processing by
370  some custom vision software running on that computer. In addition, the currently loaded Module may issue
371  messages over the UserInterface ports (e.g., indicating the location at which an object was found, to let an
372  Arduino know about it).
373 
374  - Read any new commands issued by users over the UserInterface ports and execute the appropriate commands.
375 
376  - Handle user requests to change VideoMapping, when they select a different video mode in their webcam software
377  running on the host computer connected to the JeVois hardware. Such requests may trigger unloading of the
378  current Module and loading a new one, and changing camera pixel format, image size, etc. These changes are
379  guaranteed to occur when the Module's process() function is not running, i.e., Module programmers do not have to
380  worry about possible changes in image dimensions or pixel formats during execution of their process() function.
381 
382  - Pass any user requests received over USB or UserInterface to adjust camera parameters to the actual Camera
383  hardware driver (e.g., when users change contrast in their webcam program, that request is sent to the Engine
384  over USB, and the Engine then forwards it to the Camera hardware driver).
385 
386  \ingroup core */
387  class Engine : public Manager,
388  public Parameter<engine::cameradev, engine::camerasens, engine::cameranbuf, engine::gadgetdev,
389  engine::gadgetnbuf, engine::imudev, engine::videomapping, engine::serialdev,
390  engine::usbserialdev, engine::camreg, engine::imureg, engine::camturbo,
391  engine::serlog, engine::videoerrors, engine::serout, engine::cpumode, engine::cpumax,
392  engine::multicam, engine::quietcmd, engine::python, engine::serlimit
393 #ifdef JEVOIS_PRO
394  , engine::gui, engine::conslock, engine::cpumaxl, engine::cpumodel, engine::watchdog,
395  engine::demomode
396 #endif
397  >
398  {
399  public:
400  //! Constructor
401  Engine(std::string const & instance);
402 
403  //! Constructor with command-line parsing
404  Engine(int argc, char const* argv[], std::string const & instance);
405 
406  //! Destructor
407  ~Engine();
408 
409  //! Re-load video mappings from videomappings.cfg
410  /*! Mappings are automatically loaded on startup so this should only be used if the file has been modified and the
411  mappings need to be refreshed. Note that this will not refresh the available resolutions for USB output, which
412  requires a full reboot to re-initialize the kernel Gadget module. Also beware of possible state inconsistency
413  (e.g., if external code is holding a reference previously returned by findVideoMapping(). So, use with
414  caution. Basically, only GUIhelper should use this. */
415  void reloadVideoMappings();
416 
417  //! Find the VideoMapping that has the given output specs, or throw if not found
418  VideoMapping const & findVideoMapping(unsigned int oformat, unsigned int owidth, unsigned int oheight,
419  float oframespersec) const;
420 
421  //! Get the current video mapping
422  /*! Note that the current mapping may not have an entry in our list of mappings obtained from videomappings.cfg,
423  if the current one was set on the fly by the setmapping2 CLI command. */
424  VideoMapping const & getCurrentVideoMapping() const;
425 
426  //! Return the number of video mappings
427  size_t numVideoMappings() const;
428 
429  //! Allow access to our video mappings which are parsed from file at construction
430  VideoMapping const & getVideoMapping(size_t idx) const;
431 
432  //! Get the video mapping index for a given UVC iformat, iframe and interval
433  size_t getVideoMappingIdx(unsigned int iformat, unsigned int iframe, unsigned int interval) const;
434 
435  //! Allow access to the default video mapping
436  VideoMapping const & getDefaultVideoMapping() const;
437 
438  //! Allow access to the default video mapping index
439  size_t getDefaultVideoMappingIdx() const;
440 
441  //! Run a function on every video mapping
442  /*! The first mapping your function will be called on is for mapping with index 0, and so on until index
443  numVideoMappings()-1. If your function throws, we report the exception and then ignore it, then we move on to
444  the next mapping. */
445  void foreachVideoMapping(std::function<void(VideoMapping const & m)> && func);
446 
447  //! Use this to request a format change from within process()
448  /*! This should only be used on JeVois-Pro in GUI mode. The engine is locked up hence and setFormat() cannot be
449  called from within a Module's process function, to avoid possible disasters of changing format while we
450  process. Modules or the GUI can use requestSetFormat() to request a format change in between two calls to
451  process(). Note special values: -1 to just reload the current format (e.g., after editing code), -2 does
452  nothing. */
453  void requestSetFormat(int idx);
454 
455  //! Terminate the program
456  void quit();
457 
458  //! Request a reboot
459  /*! On JeVois-A33 Platform, trigger a hard reset. On JeVois-Pro Platform or JeVois-Host, just terminate the
460  program. */
461  void reboot();
462 
463  //! Callback for when the user selects a new output video format
464  /*! Here, we stop streaming, nuke any current processing module, set the camera format, set the gadget output
465  format, load the new processing module, and start streaming again. The given VideoMapping will typically be
466  obtained using findVideoMapping() from output specs received over the USB link. */
467  void setFormat(size_t idx);
468 
469  //! Start streaming on video from camera, processing, and USB
470  void streamOn();
471 
472  //! Stop streaming on video from camera, processing, and USB
473  void streamOff();
474 
475  //! Main loop: grab, process, send over USB. Should be called by main application thread
476  int mainLoop();
477 
478  //! Send a string to all serial ports
479  /*! \note When islog is true, this is assumes to be a log message, and it will be sent to the port(s) specified by
480  parameter serlog. Otherwise, the message will be sent to the ports specified by parameter serout. Note how the
481  number of messages that can be sent for each video frame may be limited by parameter \p serlimit; only up to
482  \p serlimit messages will be sent for a given video frame. This is useful to avoid overloading the serial
483  link, for example in cases one is running a ArUco detector and a large number of ArUco tags are present in the
484  field of view of JeVois. */
485  void sendSerial(std::string const & str, bool islog = false);
486 
487  //! Get a pointer to our current module (may be null)
488  std::shared_ptr<Module> module() const;
489 
490  //! Get a pointer to our IMU (may be null)
491  std::shared_ptr<IMU> imu() const;
492 
493  //! Get a pointer to our Camera (may be null, especially if not using a camera but, eg, movie input)
494  std::shared_ptr<Camera> camera() const;
495 
496 #ifdef JEVOIS_PRO
497  //! Draw all camera controls into our GUI
498  void drawCameraGUI();
499 #endif
500 
501  //! Register a component as linked to some python code, used by dynamic params created in python
502  /*! Use with extreme caution to guarantee thread safety and object lifetime since we just use raw pointers here */
503  void registerPythonComponent(Component * comp, void * pyinst);
504 
505  //! Unregister a component as linked to some python code, used by dynamic params created in python
506  /*! Use with extreme caution to guarantee thread safety and object lifetime since we just use raw pointers here */
508 
509  //! Get the component registered with a given python instance
510  /*! Use with extreme caution to guarantee thread safety and object lifetime since we just use raw pointers here */
511  Component * getPythonComponent(void * pyinst) const;
512 
513  // Report an error to console and JeVois-Pro GUI
514  /*! Try to minimize the use of this function, and normally use LERROR() or LFATAL() instead. Currently the only
515  use is in jevois::dnn::Pipeline, to report parameters set in the zoo file but not used by the pipeline, as
516  issuing an LFATAL() for that may be too strict, but issuing an LERROR() may go un-noticed since the pipeline
517  is still running just fine. */
518  void reportError(std::string const & err);
519 
520  //! Clear all errors currently displayed in the JeVois-Pro GUI
521  /*! In the JevoisPro GUI, errors reported via reportError() remain displayed for a few seconds, but sometimes we
522  want to clear them right away, e.g., after DNN pipeline threw, if the user selects another one, we want the
523  previous error to disappear immediately since it is not applicable anymore. When the JeVois-Pro GUI is not
524  used, this has no effect. */
525  void clearErrors();
526 
527 #ifdef JEVOIS_PRO
528  //! When in demo mode, switch to next demo
529  void nextDemo();
530 
531  //! When in demo mode, abort demo mode
532  void abortDemo();
533 #endif
534 
535  protected:
536  //! Run a script from file
537  /*! The filename should be absolute. The file should have any of the commands supported by Engine, one per
538  line. Filename should be relative to the current module's path. */
539  void runScriptFromFile(std::string const & filename, std::shared_ptr<UserInterface> ser,
540  bool throw_no_file);
541 
542  //! Parameter callback
543  void onParamChange(engine::serialdev const & param, std::string const & newval) override;
544 
545  //! Parameter callback
546  void onParamChange(engine::usbserialdev const & param, std::string const & newval) override;
547 
548  //! Parameter callback
549  void onParamChange(engine::cpumode const & param, engine::CPUmode const & newval) override;
550 
551  //! Parameter callback
552  void onParamChange(engine::cpumax const & param, unsigned int const & newval) override;
553 
554  //! Parameter callback
555  void onParamChange(engine::videoerrors const & param, bool const & newval) override;
556 
557 #ifdef JEVOIS_PRO
558  //! Parameter callback
559  void onParamChange(engine::gui const & param, bool const & newval) override;
560 
561  //! Parameter callback
562  void onParamChange(engine::cpumaxl const & param, unsigned int const & newval) override;
563 
564  //! Parameter callback
565  void onParamChange(engine::cpumodel const & param, engine::CPUmode const & newval) override;
566 
567  //! Parameter callback
568  void onParamChange(engine::demomode const & param, float const & newval) override;
569 #endif
570 
571  size_t itsDefaultMappingIdx; //!< Index of default mapping
572  std::vector<VideoMapping> itsMappings; //!< All our mappings from videomappings.cfg
573  VideoMapping itsCurrentMapping { }; //!< Current mapping, may not match any in itsMappings if setmapping2 used
574 
575  std::shared_ptr<VideoInput> itsCamera; //!< Our camera
576  std::shared_ptr<IMU> itsIMU; //! Our IMU
577  std::shared_ptr<VideoOutput> itsGadget; //!< Our gadget
578 
579  std::unique_ptr<DynamicLoader> itsLoader; //!< Our module loader
580  std::shared_ptr<Module> itsModule; //!< Our current module
581 
582  std::atomic<bool> itsRunning; //!< True when we are running
583  std::atomic<bool> itsStreaming; //!< True when we are streaming video
584  std::atomic<bool> itsStopMainLoop; //!< Flag used to stop the main loop
585 
586  mutable std::timed_mutex itsMtx; //!< Mutex to protect our internals
587 
588  void preInit() override; //!< Override of Manager::preInit()
589  void postInit() override; //!< Override of Manager::postInit()
590 
591  //! Parse a user command received over serial port
592  /*! Throw upon receiving an incorrect command (eg, bad parameter value), return true if success, return false if
593  command was not recognized and should be tried by Module. pfx is an optional prefix which will be added to all
594  produced messages or errors. */
595  bool parseCommand(std::string const & str, std::shared_ptr<UserInterface> s, std::string const & pfx = "");
596 
597  private:
598  std::list<std::shared_ptr<UserInterface> > itsSerials;
599 
600  void setFormatInternal(size_t idx); // itsMtx should be locked by caller
601  void setFormatInternal(jevois::VideoMapping const & m, bool reload = false); // itsMtx should be locked by caller
602 
603  // Loop over all available camera controls and run a function on each:
604  void foreachCamCtrl(std::function<void(struct v4l2_queryctrl & qc, std::set<int> & doneids)> && func);
605 
606  // Return help string for a camera control or throw
607  std::string camCtrlHelp(struct v4l2_queryctrl & qc, std::set<int> & doneids);
608 
609  // Return machine-oriented string for a camera control or throw
610  std::string camCtrlInfo(struct v4l2_queryctrl & qc, std::set<int> & doneids);
611 
612  // Send info about built-in engine commands
613  void cmdInfo(std::shared_ptr<UserInterface> s, bool showAll, std::string const & pfx = "");
614 
615  // Send info about module commands
616  void modCmdInfo(std::shared_ptr<UserInterface> s, std::string const & pfx = "");
617 
618  // Get short name from V4L2 ID, long name is a backup in case we don't find the control in our list
619  std::string camctrlname(unsigned int id, char const * longname) const;
620 
621  // Get V4L2 ID from short name
622  unsigned int camctrlid(std::string const & shortname);
623 
624  // Report an error to console, video frame, or GUI
625  /*! Call this from within catch. Note, in GUI mode, this calls endFrame() so it should not be used except for
626  exceptions that will not be ignored. */
627  void reportErrorInternal(std::string const & err = "");
628 
629  bool itsShellMode; // When true, pass any CLI command to the Linux shell
630  bool itsTurbo;
631  bool itsManualStreamon; // allow manual streamon when outputing video to None or file
632  std::atomic<bool> itsVideoErrors; // fast cached value for engine::videoerrors
633  jevois::RawImage itsVideoErrorImage;
634  std::string itsModuleConstructionError; // Non-empty error message if module constructor threw
635 
636 #ifdef JEVOIS_PLATFORM_A33
637  // Things related to mass storage gadget to export our /jevois partition as a virtual USB flash drive:
638  void checkMassStorage(); // thread to check mass storage gadget status
639  std::future<void> itsCheckMassStorageFut;
640  std::atomic<bool> itsCheckingMassStorage;
641  std::atomic<bool> itsMassStorageMode;
642  void startMassStorageMode();
643  void stopMassStorageMode();
644 #endif
645 
646  std::atomic<size_t> itsNumSerialSent; // Number of serial messages sent this frame; see serlimit
647  std::atomic<int> itsRequestedFormat; // Set by requestSetFormat(), could be -1 to reload, otherwise -2
648 
649 #ifdef JEVOIS_PRO
650  std::shared_ptr<GUIhelper> itsGUIhelper;
651 
652  // Draw ImGui widgets for all camera controls
653  void camCtrlGUI(struct v4l2_queryctrl & qc, std::set<int> & doneids);
654 
655  std::shared_ptr<jevois::Watchdog> itsWatchdog;
656 
657  bool itsDemoReset = true; // Restart the demo
658  void runDemoStep(); // run one step of the demo mode
659  struct DemoData
660  {
661  int mapping_idx;
662  std::string title;
663  std::string msg;
664  std::vector<std::pair<std::string /* param name */, std::string /* param val */>> params;
665  };
666  std::vector<DemoData> itsDemoData;
667  bool itsNextDemoRequested = false;
668 #endif
669 
670  // Python code registry, used to assign dynamic parameters created in python code to the correct owning component.
671  // This looks thread-unsafe but should be ok as long as objects inherit first from Component and then from
672  // PythonWrapper.
673  std::map<void *, Component *> itsPythonRegistry;
674  mutable std::mutex itsPyRegMtx;
675  };
676 } // namespace jevois
677 
jevois::Engine::getDefaultVideoMappingIdx
size_t getDefaultVideoMappingIdx() const
Allow access to the default video mapping index.
Definition: Engine.C:1498
JEVOIS_USBSERIAL_DEFAULT
#define JEVOIS_USBSERIAL_DEFAULT
On platform hardware, device for serial-over-USB port.
Definition: Engine.H:76
jevois::Engine::foreachVideoMapping
void foreachVideoMapping(std::function< void(VideoMapping const &m)> &&func)
Run a function on every video mapping.
Definition: Engine.C:1502
jevois::Engine::quit
void quit()
Terminate the program.
Definition: Engine.C:1793
jevois::Manager
Manager of a hierarchy of Component objects.
Definition: Manager.H:73
JEVOIS_CAMERA_DEFAULT
#define JEVOIS_CAMERA_DEFAULT
On platform hardware, device for the camera sensor.
Definition: Engine.H:67
Watchdog.H
jevois::Engine::itsModule
std::shared_ptr< Module > itsModule
Our current module.
Definition: Engine.H:580
Manager.H
RawImage.H
jevois::Component
A component of a model hierarchy.
Definition: Component.H:181
JEVOIS_GADGET_DEFAULT
#define JEVOIS_GADGET_DEFAULT
On platform hardware, device for the USB gadget driver (which sends video frames over USB to a host c...
Definition: Engine.H:70
jevois::Engine::itsRunning
std::atomic< bool > itsRunning
True when we are running.
Definition: Engine.H:582
jevois::Engine::camera
std::shared_ptr< Camera > camera() const
Get a pointer to our Camera (may be null, especially if not using a camera but, eg,...
Definition: Engine.C:1442
jevois::RawImage
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
jevois::Engine::numVideoMappings
size_t numVideoMappings() const
Return the number of video mappings.
Definition: Engine.C:1450
jevois::Engine::unRegisterPythonComponent
void unRegisterPythonComponent(Component *comp)
Unregister a component as linked to some python code, used by dynamic params created in python.
Definition: Engine.C:2930
jevois::ParameterCategory
A category to which multiple ParameterDef definitions can belong.
Definition: ParameterDef.H:33
jevois::Engine::setFormat
void setFormat(size_t idx)
Callback for when the user selects a new output video format.
Definition: Engine.C:923
jevois::Engine::reboot
void reboot()
Request a reboot.
Definition: Engine.C:1772
jevois::Engine::itsCamera
std::shared_ptr< VideoInput > itsCamera
Our camera.
Definition: Engine.H:575
jevois::Engine::getDefaultVideoMapping
const VideoMapping & getDefaultVideoMapping() const
Allow access to the default video mapping.
Definition: Engine.C:1494
jevois::Engine::itsLoader
std::unique_ptr< DynamicLoader > itsLoader
Our module loader.
Definition: Engine.H:579
jevois
Definition: Concepts.dox:1
F
float F
Definition: GUIhelper.C:2373
jevois::Engine::streamOn
void streamOn()
Start streaming on video from camera, processing, and USB.
Definition: Engine.C:884
JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK
JEVOIS_DECLARE_PARAMETER_WITH_CALLBACK(l2grad, bool, "Use more accurate L2 gradient norm if true, L1 if false", false, ParamCateg)
jevois::Engine::clearErrors
void clearErrors()
Clear all errors currently displayed in the JeVois-Pro GUI.
Definition: Engine.C:1376
jevois::Engine::findVideoMapping
const VideoMapping & 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.
Definition: Engine.C:1510
jevois::Engine::itsMtx
std::timed_mutex itsMtx
Mutex to protect our internals.
Definition: Engine.H:586
jevois::Component::Engine
friend class Engine
Definition: Component.H:518
jevois::engine::JEVOIS_DECLARE_PARAMETER
JEVOIS_DECLARE_PARAMETER(imudev, std::string, "IMU SPI device name, typically starting with /dev/spidev..., " "or empty if device does not have an IMU with SPI interface.", JEVOIS_IMUSPI_DEFAULT, ParamCateg)
jevois::Engine::streamOff
void streamOff()
Stop streaming on video from camera, processing, and USB.
Definition: Engine.C:895
jevois::Engine::nextDemo
void nextDemo()
When in demo mode, switch to next demo.
Definition: Engine.C:587
jevois::Engine::requestSetFormat
void requestSetFormat(int idx)
Use this to request a format change from within process()
Definition: Engine.C:916
jevois::Engine
JeVois processing engine - gets images from camera sensor, processes them, and sends results over USB...
Definition: Engine.H:387
jevois::Engine::getVideoMapping
const VideoMapping & getVideoMapping(size_t idx) const
Allow access to our video mappings which are parsed from file at construction.
Definition: Engine.C:1454
jevois::Engine::runScriptFromFile
void runScriptFromFile(std::string const &filename, std::shared_ptr< UserInterface > ser, bool throw_no_file)
Run a script from file.
Definition: Engine.C:2705
jevois::Engine::reportError
void reportError(std::string const &err)
Definition: Engine.C:1367
VideoMapping.H
jevois::Engine::mainLoop
int mainLoop()
Main loop: grab, process, send over USB. Should be called by main application thread.
Definition: Engine.C:1079
jevois::Engine::onParamChange
void onParamChange(engine::serialdev const &param, std::string const &newval) override
Parameter callback.
jevois::Engine::imu
std::shared_ptr< IMU > imu() const
Get a pointer to our IMU (may be null)
Definition: Engine.C:1438
jevois::Engine::itsIMU
std::shared_ptr< IMU > itsIMU
Definition: Engine.H:576
CameraSensor.H
jevois::Engine::itsMappings
std::vector< VideoMapping > itsMappings
All our mappings from videomappings.cfg.
Definition: Engine.H:572
jevois::Engine::getVideoMappingIdx
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.
Definition: Engine.C:1463
jevois::Engine::itsDefaultMappingIdx
size_t itsDefaultMappingIdx
Index of default mapping.
Definition: Engine.H:571
jevois::Engine::preInit
void preInit() override
Override of Manager::preInit()
Definition: Engine.C:604
JEVOIS_CAMERASENS_DEFAULT
#define JEVOIS_CAMERASENS_DEFAULT
Default camera sensor.
Definition: Engine.H:80
jevois::Engine::itsStreaming
std::atomic< bool > itsStreaming
True when we are streaming video.
Definition: Engine.H:583
jevois::Engine::registerPythonComponent
void registerPythonComponent(Component *comp, void *pyinst)
Register a component as linked to some python code, used by dynamic params created in python.
Definition: Engine.C:2920
jevois::Engine::getPythonComponent
Component * getPythonComponent(void *pyinst) const
Get the component registered with a given python instance.
Definition: Engine.C:2939
jevois::Engine::postInit
void postInit() override
Override of Manager::postInit()
Definition: Engine.C:628
jevois::Engine::itsCurrentMapping
VideoMapping itsCurrentMapping
Current mapping, may not match any in itsMappings if setmapping2 used.
Definition: Engine.H:573
jevois::Engine::parseCommand
bool parseCommand(std::string const &str, std::shared_ptr< UserInterface > s, std::string const &pfx="")
Parse a user command received over serial port.
Definition: Engine.C:1895
jevois::Engine::abortDemo
void abortDemo()
When in demo mode, abort demo mode.
Definition: Engine.C:591
jevois::Engine::~Engine
~Engine()
Destructor.
Definition: Engine.C:814
jevois::Engine::sendSerial
void sendSerial(std::string const &str, bool islog=false)
Send a string to all serial ports.
Definition: Engine.C:1322
jevois::JEVOIS_DEFINE_ENUM_CLASS
JEVOIS_DEFINE_ENUM_CLASS(CameraSensor,(any)(imx290)(os08a10)(ar0234))
Enum for different sensor models.
jevois::Engine::module
std::shared_ptr< Module > module() const
Get a pointer to our current module (may be null)
Definition: Engine.C:1434
JEVOIS_IMUSPI_DEFAULT
#define JEVOIS_IMUSPI_DEFAULT
Default IMU spi device.
Definition: Engine.H:83
jevois::Engine::reloadVideoMappings
void reloadVideoMappings()
Re-load video mappings from videomappings.cfg.
Definition: Engine.C:615
jevois::Engine::getCurrentVideoMapping
const VideoMapping & getCurrentVideoMapping() const
Get the current video mapping.
Definition: Engine.C:1446
jevois::Engine::itsStopMainLoop
std::atomic< bool > itsStopMainLoop
Flag used to stop the main loop.
Definition: Engine.H:584
jevois::Engine::drawCameraGUI
void drawCameraGUI()
Draw all camera controls into our GUI.
Definition: Engine.C:2783
JEVOIS_SERIAL_DEFAULT
#define JEVOIS_SERIAL_DEFAULT
On platform hardware, device for the 4-pin hardware serial port.
Definition: Engine.H:73
jevois::Engine::itsGadget
std::shared_ptr< VideoOutput > itsGadget
Our IMU.
Definition: Engine.H:577
Enum.H