The protoComponentGUI Example

From David Vernon's Wiki
Jump to: navigation, search

protoComponentGUI.h

/** @file protoComponentGUI.h  Interface file for the example DREAM component
 *
 * Version 1.0
 * 
 * 30/10/2014
 *
 *
 * \defgroup DREAM_protoComponentGUI protoComponentGUI
 * 
 * protoComponentGUI is a simple example to illustrate how to use the FLTK library 
 * to create a graphic user interface component that can send and receive information  
 * to and fromother components using variety of YARP ports. 
 * 
 * protoComponentGUI complements the functionality of the protoComponent component:
 * 
 * - reading the binary image output from protoComponent and displaying it in a graphic display, 
 * - reading the statistics text from protoComponent and displaying it in an output box,
 * - using an FLTK GUI widget slider to set the binary threshold and send it to protoComponent,
 * - and reading & displaying the original colour image in a separate display. 
 *
 * It makes use of a library \c guiUtilities developed by David Vernon.  This library implements
 * several classes to manipulate and display images.  It also contains example callback functions
 * for standard FLTK evaluators such as sliders and radio buttons as well as writing messages to 
 * a display box. guiUtilities is included in the DREAM software project so that it can be extended
 * as required.
 *
 * It also illustrates how to use the YARP resourceFinder class to locate files, 
 * in this case the DREAM logo image file, in the standard DREAM directories searched by YARP.
 *
 * A complete tutorial on this example is available on the DREAM wiki.
 *
 * 
 * \section lib_sec Libraries
 *
 * YARP
 * FLTK: fltk.lib, fltkgl.lib, fltkimages.lib, fltkpng.lib, fltkzlib.lib
 * guiUtilities.lib
 *
 * \section parameters_sec Parameters
 * 
 * Command-line Parameters  
 * 
 * The following key-value pairs can be specified as command-line parameters 
 * by prefixing \c -- to the key e.g. \c --from file.ini. 
 * The value part can be changed to suit your needs; the default values are 
 * shown below. 
 *
 * - \c from \c protoComponentGUI.ini \n 
 *   specifies the configuration file
 *
 * - \c context \c protoComponentGUI/configuration \n
 *   specifies the sub-path from \c $DREAM_ROOT/protoComponentGUI/configuration 
 *   to the configuration file
 *
 * - \c name \c protoComponentGUI \n   
 *   specifies the name of the module (used to form the stem of module port names)  
 *
 *
 * Configuration File Parameters 
 *
 * The following key-value pairs can be specified as parameters in the configuration file 
 * (they can also be specified as command-line parameters if you so wish). 
 * The value part can be changed to suit your needs; the default values are shown below. 
 *   
 * - \c colourImageInputPort \c /colourimage:i \n    
 *   specifies the image input port name for the colour image 
 *   
 * - \c binaryImageInputPort \c /binaryimage:i \n  
 *   specifies the image input port name for the binary image 
 * 
 * - \c statisticsInputPort \c /statistics:i \n  
 *    specifies the statistics input port name 
 * 
 * - \c thresholdOutputPort \c /threshold:o \n    
 *   specifies the threshold output port name 
 * 
 *   Note: all these filename strings will be prefixed by \c /protoComponentGUI
 *  (or whatever else is specifed by the \c name parameter)
 *
 * - \c threshold \c 7 \n           
 *   specifies the threshold value
 *
 * 
 * \section portsa_sec Ports Accessed
 * 
 * - None
 *                      
 * \section portsc_sec Ports Created
 *
 *  Input ports
 *
 *  - \c /protoComponentGUI \n
 *    This port is used to change the parameters of the module at run time or stop the module. \n
 *    The following commands are available
 * 
 *    \c help \n
 *    \c quit \n
 *    \c set \c thr \c <n>   ... set the threshold for binary segmentation of the input RGB image 
 *    (where \c <n> is an integer number)
 *
 *    Note that the name of this port mirrors whatever is provided by the \c --name parameter value
 *    The port is attached to the terminal so that you can type in commands and receive replies.
 *    The port can be used by other modules but also interactively by a user through the yarp rpc directive, viz.: \c yarp \c rpc \c /protoComponentGUI
 *    This opens a connection from a terminal to the port and allows the user to then type in commands and receive replies.
 *       
 *  - \c /protoComponentGUI/colourImage:i \n
 *  - \c /protoComponentGUI/binaryImage:i \n    
 *  - \c /protoComponentGUI/statistics:i  \n
 *
 * Output ports
 *
 *  - \c /protoComponentGUI/threshold:o \n *
 *  - \c /protoComponentGUI \n
 *    see above
 *
 * Port types 
 *
 * The functional specification above only names the ports to be used to communicate with the module 
 * but doesn't say anything about the data transmitted on the ports. This is defined by the following code. 
 *
 * \c BufferedPort<ImageOf<PixelRgb> >   \c colourImageIn; \n 
 * \c BufferedPort<ImageOf<PixelRgb> >   \c binaryImageIn; \n  
 * \c BufferedPort                       \c statisticsIn; \n      
 * \c BufferedPort<VectorOf<int> >       \c thresholdOut; //int threshold  \n  
 *
 * Thus, there are three types of port in use here, all buffered: 
 * 
 * - image, 
 * - vector of int (there will be just one element in the vector in this case), and 
 * - a bottle comprising various alphanumeric messages.
 *
 *
 * \section in_files_sec Input Data Files
 *
 * \c DREAM_223x59.png 
 *
 * This the DREAM logo. It is located in C:/DREAM/release/components/protoComponentGUI/config 
 * but the resourceFinder identifies this path automatically.
 *
 * \section out_data_sec Output Data Files
 *
 * None
 *
 * \section conf_file_sec Configuration Files
 *
 * \c protoComponentGUI.ini   
 *
 * \section example_sec Example Instantiation of the Module
 * 
 * protoComponentGUI --name protoComponentGUI --context components/protoComponentGUI/config --from protoComponentGUI.ini 
 *
 * \author 
 * 
 * David Vernon, University of Skövde
 * 
 * Copyright (C) 2014 DREAM Consortium
 * 
 */

/* 
 * Copyright (C) 2014 DREAM Consortium
 * FP7 Project 611391 co-funded by the European Commission
 *
 * Author:  David Vernon, University of Skövde 
 * Email:   david.vernon@his.se 
 * Website: www.dream20202.eu 
 *
 * This program comes with ABSOLUTELY NO WARRANTY 
 */
  
  
/*
 * Audit Trail
 * -----------
 * 30/10/14  First version validated (David Vernon)
 *
 */ 
 
#include <iostream>
#include <string>

#include <yarp/sig/all.h>
#include <yarp/os/all.h>
#include <yarp/os/RFModule.h>
#include <yarp/os/Network.h>
#include <yarp/os/Thread.h>
 
#include "guiUtilities.h"

using namespace std;
using namespace yarp::os; 
using namespace yarp::sig;
  
#define STRINGLENGTH 132 // used to define a string when post-processing the bottle messages

class ProtoComponentGUIThread : public Thread {

private:

   /* class variables */

   bool              debug;
   int               x, y;
   PixelRgb          rgbPixel;
   int               *thresholdValue;   
   int               numberOfForegroundPixels;
   int               rgb_width;
   int               rgb_height;
   int               rgb_depth;
   int               binary_width;
   int               binary_height;
   int               binary_depth;
   unsigned char     pixel_value;
   float             float_pixel_value;
   double            thresholdValueDouble;
   string            logoFilenameValue;
   int               temp;
 
   ImageOf<PixelRgb> *rgbYARPImage;
   ImageOf<PixelRgb> *binaryYARPImage;
   DVimage           *rgbDVImage;
   DVimage           *binaryDVImage;
   Bottle            *statisticsMessage; 

   /* thread parameters: they are pointers so that they refer to the original variables in protoComponentGUI */

   BufferedPort<ImageOf<PixelRgb> > *colourImagePortIn;
   BufferedPort<ImageOf<PixelRgb> > *binaryImagePortIn;
   BufferedPort<Bottle>             *statisticsPortIn; 
   BufferedPort<VectorOf<int> >     *thresholdPortOut; 

public:

   /* class methods */

   ProtoComponentGUIThread(BufferedPort<ImageOf<PixelRgb> > *colourImageIn, 
                           BufferedPort<ImageOf<PixelRgb> > *binaryImageIn,
                           BufferedPort<Bottle>             *statisticsIn, 
                           BufferedPort<VectorOf<int> >     *thresholdOut, 
                           int *threshold, 
                           string logoFilename);
   bool threadInit();     
   void threadRelease();
   void run(); 
};


class ProtoComponentGUI:public RFModule {

   /* module parameters */

   string moduleName;
   string colourImageInputPortName;
   string thresholdOutputPortName;
   string binaryImageInputPortName;
   string statisticsInputPortName;  
   string handlerPortName;
   string logoFilename;
   int    thresholdValue;

   /* class variables */

   BufferedPort<ImageOf<PixelRgb> > colourImageIn;  // example image input port
   BufferedPort<ImageOf<PixelRgb> > binaryImageIn;  // example image input port
   BufferedPort<Bottle>             statisticsIn;   // example bottle input port
   BufferedPort<VectorOf<int> >     thresholdOut;   // example vector output port
   Port handlerPort;                                // a port to handle interactive messages (also uses bottles)

   /* pointer to a new thread to be created and started in configure() and stopped in close() */

   ProtoComponentGUIThread *protoComponentGUIThread; 

public:
   
   bool configure(yarp::os::ResourceFinder &rf); // configure all the module parameters and return true if successful
   bool interruptModule();                       // interrupt, e.g., the ports 
   bool close();                                 // close and shut down the module
   bool respond(const Bottle& command, Bottle& reply);
   double getPeriod(); 
   bool updateModule();
};

Back to Software Development Guide

protoComponentGUIConfiguration.cpp

/* 
 * Copyright (C) 2014 DREAM Consortium
 * FP7 Project 611391 co-funded by the European Commission
 *
 * Author:  David Vernon, University of Skövde 
 * Email:   david.vernon@his.se 
 * Website: www.dream20202.eu 
 *
 * This program comes with ABSOLUTELY NO WARRANTY 
 */
  
 
/*
 * Audit Trail
 * -----------
 * 30/10/14  First version validated (David Vernon))
 *
 */ 

#include "protoComponentGUI.h"


/* 
 * Configure method ... use it to do component coordination, 
 * i.e. to configure your component at runtime
 */

bool ProtoComponentGUI::configure(yarp::os::ResourceFinder &rf)
{     
   /* Process all parameters from both command-line and .ini file */

   /* get the module name which will form the stem of all module port names */

   moduleName            = rf.check("name", 
                           Value("protoComponentGUI"), 
                           "module name (string)").asString();
 
   /*
    * before continuing, set the module name before getting any other parameters, 
    * specifically the port names which are dependent on the module name
    */
   
   setName(moduleName.c_str());

   /* now, get the rest of the parameters */

   /* get the name of the input and output ports, automatically prefixing the module name by using getName() */

   colourImageInputPortName    =      "/";
   colourImageInputPortName   +=      getName(
                                      rf.check("colourImageInputPort", 
                                      Value("/colourimage:i"),
                                      "Colour input image port (string)").asString()
                                      );

   binaryImageInputPortName   =      "/";
   binaryImageInputPortName  +=      getName(
                                      rf.check("binaryImageInputPort", 
                                      Value("/binaryimage:i"),
                                      "Binary input image port (string)").asString()
                                      );

   statisticsInputPortName   =       "/";
   statisticsInputPortName  +=       getName(
                                      rf.check("statisticsInputPort", 
                                      Value("/statistics:i"),
                                      "Statistics output port (string)").asString()
                                      );
   
   thresholdOutputPortName =          "/";
   thresholdOutputPortName +=         getName(
                                      rf.check("thresholdInputPort", 
                                      Value("/threshold:o"),
                                      "Threshold output port (string)").asString()
                                       );


   /* get the threshold value */

   thresholdValue             =       rf.check("threshold",
                                      Value(8),
                                      "Key value (int)").asInt();

  
   /* get the DREAM logo file  */

   logoFilename  = rf.check("dreamLogo", 
                            Value("DREAM_223x59.png"), 
                            "DREAM logo filename (string)").asString();

   logoFilename = (rf.findFile(logoFilename.c_str())).c_str();
 

   /* do all initialization here */
     
   /* open ports  */ 
       
   if (!colourImageIn.open(colourImageInputPortName.c_str())) {
      cout << getName() << ": unable to open port " << colourImageInputPortName << endl;
      return false;  // unable to open; let RFModule know so that it won't run
   }

   if (!binaryImageIn.open(binaryImageInputPortName.c_str())) {
      cout << getName() << ": unable to open port " << binaryImageInputPortName << endl;
      return false;  // unable to open; let RFModule know so that it won't run
   } 

   if (!statisticsIn.open(statisticsInputPortName.c_str())) {
      cout << getName() << ": unable to open port " << statisticsInputPortName << endl;
      return false;  // unable to open; let RFModule know so that it won't run
   }
   
   if (!thresholdOut.open(thresholdOutputPortName.c_str())) {
      cout << getName() << ": unable to open port " << thresholdOutputPortName << endl;
      return false;  // unable to open; let RFModule know so that it won't run
   }
   


   /*
    * attach a port of the same name as the module (prefixed with a /) to the module
    * so that messages received from the port are redirected to the respond method
    */

   handlerPortName =  "/";
   handlerPortName += getName();         // use getName() rather than a literal 
 
   if (!handlerPort.open(handlerPortName.c_str())) {           
      cout << getName() << ": Unable to open port " << handlerPortName << endl;  
      return false;
   }

   attach(handlerPort);                  // attach to port
 
   /* create the thread and pass pointers to the module parameters */

   protoComponentGUIThread = new ProtoComponentGUIThread(&colourImageIn, &binaryImageIn, &statisticsIn, &thresholdOut, &thresholdValue, logoFilename);

   /* now start the thread to do the work */

   protoComponentGUIThread->start(); // this calls threadInit() and it if returns true, it then calls run()



   return true ;      // let the RFModule know everything went well
                      // so that it will then run the module
}
 

bool ProtoComponentGUI::interruptModule()
{
   /* NB you must stop the thread before interrupting the ports and then closing them
      If you don't then gyarpmanger will not be able to stop the module and you will have
      to resort to killing it                                                              */

   protoComponentGUIThread->stop();  
  
   colourImageIn.interrupt();
   binaryImageIn.interrupt();
   statisticsIn.interrupt();
   thresholdOut.interrupt(); 
   handlerPort.interrupt();

   return true;
} 


bool ProtoComponentGUI::close()
{
   colourImageIn.close();
   binaryImageIn.close();
   statisticsIn.close();
   thresholdOut.close(); 
   handlerPort.close();

   return true;
}

 
bool ProtoComponentGUI::respond(const Bottle& command, Bottle& reply) 
{
  string helpMessage =  string(getName().c_str()) + 
                        " commands are: \n" +  
                        "help \n" + 
                        "quit \n" + 
                        "set thr <n> ... set the threshold \n" + 
                        "(where <n> is an integer number) \n";

   reply.clear(); 

   if (command.get(0).asString()=="quit") {
       reply.addString("quitting");
       return false;     
   }
   else if (command.get(0).asString()=="help") {
      cout << helpMessage;
	  reply.addString("command is: set thr <n>");
   }
   else if (command.get(0).asString()=="set") {
      if (command.get(1).asString()=="thr") {
         thresholdValue = command.get(2).asInt(); // set parameter value
         reply.addString("ok");
      }
   }
   return true;
} 


/* Called periodically every getPeriod() seconds */

bool ProtoComponentGUI::updateModule()
{
   return true;
}


double ProtoComponentGUI::getPeriod()
{
   /* module periodicity (seconds), called implicitly by protoComponentGUI */
    
   return 0.1;
}

Back to Software Development Guide

protoComponentGUIComputation.cpp

/* 
 * Copyright (C) 2014 DREAM Consortium
 * FP7 Project 611391 co-funded by the European Commission
 *
 * Author:  David Vernon, University of Skövde 
 * Email:   david.vernon@his.se 
 * Website: www.dream20202.eu 
 *
 * This program comes with ABSOLUTELY NO WARRANTY 
*/


/*
 * Audit Trail
 * -----------
 * 30/10/14  First version validated (David Vernon)
 *
 */ 
 
#include "protoComponentGUI.h"

ProtoComponentGUIThread::ProtoComponentGUIThread(BufferedPort<ImageOf<PixelRgb> > *colourImageIn, 
                                                 BufferedPort<ImageOf<PixelRgb> > *binaryImageIn,
                                                 BufferedPort<Bottle>             *statisticsIn, 
                                                 BufferedPort<VectorOf<int> >     *thresholdOut,
                                                 int *threshold,
                                                 string logoFilename)
{
   colourImagePortIn    = colourImageIn;
   binaryImagePortIn    = binaryImageIn;    
   statisticsPortIn     = statisticsIn;
   thresholdPortOut     = thresholdOut;
   thresholdValue       = threshold;
   thresholdValueDouble = (double)*thresholdValue;
   logoFilenameValue    = logoFilename;
}

bool ProtoComponentGUIThread::threadInit() 
{
   /* initialize variables and create data-structures if needed */

   debug = false;
   rgbDVImage = NULL;
   binaryDVImage = NULL;
   rgbYARPImage = NULL;
   binaryYARPImage = NULL;

   return true;
}

void ProtoComponentGUIThread::run(){

  /* 
    * Here we set up the GUI for the component
    * The particular GUI complements the functionality of the protoComponent component:
    * taking its image output and displaying it, 
    * taking its statistics text and writing it in an output box,
    * using a GUI widget slider to set the threshold and send it to protoComponent,
    * It also reads & displays the original colour image in a separate display. 
    */ 

   Fl_Group *start_protoComponent_GUI;
   Fl_Box *box1, *box2, *heading;
   Fl_PNG_Image *logo=new Fl_PNG_Image(logoFilenameValue.c_str());
 
   int i, j;
   char modifiedString[STRINGLENGTH]; 

   /* variable that determine the presentation of the GUI */ 

   int control_panel_x, control_panel_y;
   int control_panel_width, control_panel_height;
   int heading_x, heading_y, heading_width, heading_height;
   int display_width, display_height;
   int display_x1, display_x2, display_y;
   int display_spacing;
   int display_offset_x, display_offset_y;
   int control_offset_x, control_offset_y;
   int button_size_x, button_size_y, button_spacing_y;
   int input_size_x, input_size_y;
   int title_height;
   int threshold_x, threshold_y;
   int threshold_size_x, threshold_size_y;
   int section_spacing_y;
   int window_width, window_height, border_width, border_height;
   int text_output_width,text_output_height;
   int text_output_x,   text_output_y;
	
   /* intialize the presentation settings */

   window_width  = GetSystemMetrics(SM_CXFULLSCREEN);      // this is the area available for the window on the screen
   window_height = GetSystemMetrics(SM_CYFULLSCREEN);

   border_width  = GetSystemMetrics(SM_CXSIZEFRAME);  
   border_height = GetSystemMetrics(SM_CYSIZEFRAME);

   display_width  = DISPLAY_WIDTH;   
   display_height = DISPLAY_HEIGHT;
   display_spacing = 25;

   heading_x = (window_width - display_width*2 - display_spacing)/2; 
   heading_y = MENUBAR_HEIGHT;
   heading_width = display_width*2 + display_spacing;       // centre over displays
   heading_height = HEADING_HEIGHT*2;                       // logo and caption

   display_offset_x = heading_x ;
   display_offset_y = heading_y + heading_height;
   display_x1 = display_offset_x;
   display_x2 = display_x1 + display_spacing + display_width  ;
   display_y  = display_offset_y;
  
   title_height = 12;

   button_size_x = 130;
   button_size_y = 20;
   button_spacing_y = 5;

   input_size_x = button_size_x;
   input_size_y = button_size_y;
 
   control_offset_x = 20;
   control_offset_y = 0;

   control_panel_width  = display_width * 1;
   control_panel_height = display_height / 2; // alternative to match the panel height to the number of widgets: 
                                              // control_panel_height = title_height + 1*(5 + button_size_y) + title_height; 
   control_panel_x = display_x2;
   control_panel_y = display_y + display_height + display_spacing;

   section_spacing_y = 8;

   threshold_size_x = control_panel_width - 2 * control_offset_x;
   threshold_size_y = input_size_y;
   threshold_x = control_panel_x + control_offset_x;
   threshold_y = control_panel_y + control_offset_x + 0 * (button_size_y + button_spacing_y); // 0 because threshold is the first widget in the control panel
                                                                                              // increase by 1 for every extra widget added
   text_output_width  = display_width;
   text_output_height = display_height / 2;
   text_output_x = display_offset_x;
   text_output_y = display_offset_y + display_height + display_spacing;
    
   
   /* define a group with all the GUI widgets */

   start_protoComponent_GUI = new Fl_Group(0,MENUBAR_HEIGHT,window_width,window_height-MENUBAR_HEIGHT,"");

   start_protoComponent_GUI->begin();  

      /*  ... note: we don't declare heading because it is declared in the guiUtilities library   */ 

      heading = new Fl_Box(heading_x, heading_y,
                           heading_width,heading_height,"The protoComponentGUI Example" );

      heading->align(FL_ALIGN_INSIDE | FL_ALIGN_CENTER |  FL_ALIGN_IMAGE_OVER_TEXT);
      heading->labelsize(20);
      heading->labelcolor(FL_BLACK);  
      heading->labelfont(FL_HELVETICA_BOLD);
      heading->box(FL_NO_BOX);
      heading->image(logo);
  

      /* boxes to frame images ... note: we don't declare box1 or box2 because they are declared in the guiUtilities library   */ 

      box1 = new Fl_Box(display_x1-BORDER,display_y-BORDER,
                        display_width+2*BORDER,display_height+2*BORDER,"" );
      box1->box(FL_DOWN_BOX);
      box1->align(FL_ALIGN_BOTTOM | FL_ALIGN_CENTER);
      box1->labelsize(12);
 
      box2 = new Fl_Box(display_x2-BORDER,display_y-BORDER,
                        display_width+2*BORDER,display_height+2*BORDER,"" );
      box2->box(FL_DOWN_BOX);
      box2->align(FL_ALIGN_BOTTOM | FL_ALIGN_CENTER);
      box2->labelsize(12);
 

      /* image display ... note: we don't declare display1 or display2 because they declared in the guiUtilities library   */ 
      
      display1 = new DVdisplay(display_x1, display_y, 
	                            display_width,display_height);

      display2 = new DVdisplay(display_x2, display_y, 
   	                         display_width,display_height);

      /* box to frame controls */

      Fl_Box *control_panel;
      control_panel = new Fl_Box(control_panel_x, control_panel_y, control_panel_width, control_panel_height,"" );
      control_panel->align(FL_ALIGN_TOP | FL_ALIGN_CENTER | FL_ALIGN_INSIDE);
      control_panel->labelsize(12);
      control_panel->labelfont(FL_HELVETICA_BOLD);
      control_panel->box(FL_PLASTIC_DOWN_BOX);
 

      /* threshold slider */

      Fl_Value_Slider *threshold;
      threshold = new Fl_Value_Slider(threshold_x, threshold_y, threshold_size_x, threshold_size_y,"Binary Threshold Value");
      threshold->type(FL_HOR_NICE_SLIDER);
      threshold->textsize(11);
      threshold->callback(valuator_cb, &thresholdValueDouble); // NB valuator_cb() is a general-purpose callback defined in guiUtilities.h
      threshold->labelsize(12);                                // other general-purpose callbacks are defined there too, e.g. radio buttons
      threshold->labelfont(FL_HELVETICA_BOLD);                 // some widgets may require you to write your own callback
      threshold->when(FL_WHEN_ENTER_KEY | FL_WHEN_CHANGED | FL_WHEN_RELEASE); 
      threshold->align(FL_ALIGN_TOP);
      threshold->minimum(0);
      threshold->maximum(255);
      threshold->step(1);
      threshold->value((double)*thresholdValue);  // initialize the threshold to the value passed as a parameter
      threshold->box(FL_PLASTIC_DOWN_BOX);
 

      /* Text output ... note: we don't declare text_output because it is declared in the guiUtilities library   */ 
 
      text_output = new Fl_Multiline_Output(text_output_x, text_output_y, text_output_width, text_output_height,"" );
      text_output->align(FL_ALIGN_TOP | FL_ALIGN_CENTER );
      text_output->labelsize(12);
      text_output->textsize(12);
      //text_output->color(FL_GREEN);
      text_output->value("");
      //text_output->box(FL_THIN_DOWN_FRAME);  // matches the image display frames
      text_output->box(FL_PLASTIC_DOWN_BOX);   // rounded edges for something more visually appealing
 
   start_protoComponent_GUI->end();  // end of the group 

   // create main window
  
   DVwindow = new Fl_Double_Window(window_width-border_width,window_height-border_height,"The DREAM Project");
   DVwindow->position(0,0); 
	
   Fl::visual(FL_DOUBLE|FL_INDEX); // enable double buffering of the window 

   DVwindow->end(); 
   DVwindow->show();

   // add the GUI

   DVwindow->add(start_protoComponent_GUI);
   DVwindow->redraw();
   Fl::check();

   /* write some text in the window ...                                                               */
   /* note that funtion message() is defined in guiUtilities as a general-purpose routine to write    */
   /* to the predefined display widget text_output ... notice how we didn't declare text_output above */
   /* we didn't have to because it is declared in guiUtilities                                        */

   message("Waiting to start .... image statistics will be displayed here");


   /*************************************************************************************/
   /*   This is where the definition of the GUI ends and the normal run() loop begins   */
   /*************************************************************************************/

   while (isStopping() != true) { // the thread continues to run until isStopping() returns true
 
      DVwindow->redraw();

      Fl::check();         // refresh the GUI   .... we do it this way rather than calling Fl::run() as we nomally would 
                           // because we do not want to cede control to the event loop 

      if (debug) cout << "protoComponentGUIThread: threshold value is " << *thresholdValue << endl;
      
      /* get the threshold value set by the threshold widget callback                                   */
      /* we have to do this because we passed a temporary variable thresholdValueDouble to the callback */
      /* to ensure the type of the argument agrees with the type of the callback parameter (double)     */

      *thresholdValue = (int) thresholdValueDouble;

      if (debug) cout << "protoComponentGUIThread: threshold value is " << *thresholdValue << endl;

      /*** read colour image ... do not block if image is not received ***/

      rgbYARPImage = colourImagePortIn->read(false);

      if (rgbYARPImage != NULL) {

         rgb_width  = rgbYARPImage->width();  
         rgb_height = rgbYARPImage->height();
         rgb_depth  = 3;
    
         if (debug) printf("protoComponentGUI: rgb width = %d, rgb height = %d, rgb depth = %d\n",rgb_width, rgb_height, rgb_depth);
 
         if (rgbDVImage == NULL) {
             rgbDVImage = new DVimage(rgb_width, rgb_height, rgb_depth);
         }


         /*  now copy the image to local format */
 
         for (x = 0; x < rgb_width; x++) {
            for (y = 0; y < rgb_height; y++) {
               rgbPixel = rgbYARPImage->safePixel(x,y);  
               rgbDVImage->put_pixel(x, y, rgbPixel.r, 0);
               rgbDVImage->put_pixel(x, y, rgbPixel.g, 1);
               rgbDVImage->put_pixel(x, y, rgbPixel.b, 2);
           }
         } 
 
         display1->draw(rgbDVImage); 
      }
      else {
         if (debug) printf("protoComponentGUI: colour image not received\n");
      }


      /*** read binary image ... do not block if image is not received ***/

      binaryYARPImage = binaryImagePortIn->read(false);

      if (binaryYARPImage != NULL) {

         binary_width  = binaryYARPImage->width();  
         binary_height = binaryYARPImage->height();
         binary_depth  = 3;
    
         if (debug) printf("protoComponentGUI: rgb width = %d, rgb height = %d, rgb depth = %d\n",binary_width, binary_height, binary_depth);
 
         if (binaryDVImage == NULL) {
             binaryDVImage = new DVimage(binary_width, binary_height, binary_depth);
         }


         /*  now copy the image to local format */
 
         for (x = 0; x < binary_width; x++) {
            for (y = 0; y < binary_height; y++) {
               rgbPixel = binaryYARPImage->safePixel(x,y);  
               binaryDVImage->put_pixel(x, y, rgbPixel.r, 0);
               binaryDVImage->put_pixel(x, y, rgbPixel.g, 1);
               binaryDVImage->put_pixel(x, y, rgbPixel.b, 2);
           }
         } 
 
         display2->draw(binaryDVImage); 
      }
      else {
         if (debug) printf("protoComponentGUI: binary image not received\n");
      }
      
      /* read the image statistics ... do not block if bottle is not received*/

      statisticsMessage = statisticsPortIn->read(false);
     
      if (statisticsMessage != NULL) {

         /* for some strange reason, YARP puts double quotes around every individual string in a bottle so we strip them here */

         j=0;
         for (i=0; i<min(STRINGLENGTH-1,(int)strlen(statisticsMessage->toString().c_str()));i++) {
            if (statisticsMessage->toString().c_str()[i]!='\"') {
               modifiedString[j] = statisticsMessage->toString().c_str()[i];
               j++; 
            }
         }
         modifiedString[j]='\0';


         /* now copy the message to the display */

         message(modifiedString);
         if (debug) cout << "protoComponentGUIThread: statistics message is " << modifiedString << endl;    
      }
      else {
         if (debug) printf("protoComponentGUI: statistics not received\n");
      }


      /*** write the threshold ***/

      VectorOf<int> &thresholdVector = thresholdPortOut->prepare(); 
      thresholdVector.resize(1);
      thresholdVector(0) = *thresholdValue;
 
      thresholdPortOut->write(); 

      if (debug) cout << "protoComponentGUIThread: threshold value is " << *thresholdValue << endl;
 
   }
}

void ProtoComponentGUIThread::threadRelease() 
{
   /* for example, delete dynamically created data-structures */
}

Back to Software Development Guide

protoComponentGUIMain.cpp

/* 
 * Copyright (C) 2014 DREAM Consortium
 * FP7 Project 611391 co-funded by the European Commission
 *
 * Author:  David Vernon, University of Skövde 
 * Email:   david.vernon@his.se 
 * Website: www.dream20202.eu 
 *
 * This program comes with ABSOLUTELY NO WARRANTY 
 */
  

/*
 * Audit Trail
 * -----------
 * 20/08/14  First version validated (David Vernon)
 */ 

#include "protoComponentGUI.h" 

int main(int argc, char * argv[])
{ 
   /* initialize yarp network */ 
 
   Network yarp;

   /* create your module */

   ProtoComponentGUI protoComponentGUI; 

   /* prepare and configure the resource finder */

   ResourceFinder rf;
   rf.setVerbose(true);
   rf.setDefaultConfigFile("protoComponentGUI.ini");          // can be overridden by --from parameter
   rf.setDefaultContext("protoComponentGUI/configuration");   // can be overridden by --context parameter
   rf.configure("DREAM_ROOT", argc, argv);                    // environment variable with root of configuration path
 
   /* run the module: runModule() calls configure first and, if successful, it then runs */

   protoComponentGUI.runModule(rf);

   return 0;
}

Back to Software Development Guide