DishVisualizer.cpp
Go to the documentation of this file.
00001 /*
00002  * DishVisualizer.cpp
00003  * Copyright 2013 University of Massachusetts Lowell
00004  * Authors: Abraham Shultz, Jonathan Hasenzahl
00005  */
00006 
00007 #include "dish_viz/DishVisualizer.h"
00008 
00009 #define RADIUS 20
00010 #define P_WIDTH ((7 * RADIUS) + (8 * (2 * RADIUS)) + (2 * RADIUS))
00011 #define P_HEIGHT P_WIDTH
00012 #define X_STEP (3*RADIUS)
00013 #define Y_STEP X_STEP
00014 #define START_X (2*RADIUS)
00015 #define START_Y START_X
00016 #define ROWS 8
00017 #define COLS ROWS
00018 
00019 DishVisualizer::DishVisualizer() {
00020         isInit = FALSE;
00021         plot_ca = false;
00022         data.assign(60, 0);
00023         for (int i = 0; i < 60; i++)
00024         {
00025             baselines[i] = 0.0;
00026             thresholds[i] = 0.0;
00027             min_volts[i] = 0.0;
00028             max_volts[i] = 0.0;
00029         }
00030 }
00031 
00032 DishVisualizer::~DishVisualizer() {
00033         isInit = FALSE;
00034 }
00035 
00041 int DishVisualizer::init(int mode) {
00042         isInit = FALSE;
00043 
00044         // Set color mode
00045     if (mode >= 0 && mode <= 3)
00046     {
00047         color_mode = mode;
00048         ROS_INFO("Visualizer color mode set to %d", color_mode);
00049     }
00050     else
00051     {
00052         color_mode = RED_BLUE_SEPARATED;
00053         ROS_WARN("Color mode (%d) is out of range [0...3]", mode);
00054     }
00055 
00056         /* set Plotter parameters */
00057         PlotterParams plotter_params;
00058         //convert width and height to config string
00059         ostringstream oss;
00060         oss << P_WIDTH << "x" << P_HEIGHT;
00061         plotter_params.setplparam("BITMAPSIZE", (void*) oss.str().c_str());
00062         //plotter_params.setplparam("VANISH_ON_DELETE", (char *)"yes");
00063         plotter_params.setplparam("USE_DOUBLE_BUFFERING", (char *) "yes");
00064 
00065         /* create an X Plotter with the specified parameters */
00066         plotter = new XPlotter(stdin, stdout, stderr, plotter_params);
00067 
00068         if (plotter->openpl() < 0) /* open Plotter */
00069         {
00070                 ROS_FATAL("Couldn't open Plotter");
00071                 return 1;
00072         }
00073 
00074         plotter->space(0, 0, P_WIDTH, P_HEIGHT); //coordinates in pixels, not (0,0)-(1,1)
00075         plotter->flinewidth(0.01); //line thickness
00076         plotter->filltype(1); //Fill objects
00077         plotter->bgcolor(0, 0, 0); //Black, colors are RGB, 16 bits/channel
00078         plotter->erase();
00079 
00080         for (int row = ROWS - 1; row >= 0; row--) {
00081                 for (int col = 0; col < COLS; col++) {
00082                         //Calculate the locations of the circles
00083                         if (!((row == 0 && col == 0) || (row == ROWS - 1 && col == COLS - 1)
00084                                         || (row == 0 && col == COLS - 1)
00085                                         || (row == ROWS - 1 && col == 0))) {
00086 
00087                                 //int index = (COLS * row) + col;
00088                                 int xPos = START_X + (col * X_STEP);
00089                                 int yPos = START_Y + (row * Y_STEP);
00090                                 //ROS_INFO("%d, %d, %d", index, xPos, yPos);
00091                                 //Stash them in the array
00092                                 vector<int> tmp;
00093                                 tmp.push_back(xPos);
00094                                 tmp.push_back(yPos);
00095                                 centers.push_back(tmp);
00096                                 plotter->color(65535, 0, 0); //Set pen and fill color
00097                                 plotter->circle(xPos, yPos, RADIUS); //Draw a circle at the location
00098                         }
00099                 }
00100         }
00101 
00102     // Draw lines to separate grid into quadrants
00103     plotter->pencolorname("white");
00104     plotter->line(P_WIDTH / 2, 0, P_WIDTH / 2, P_HEIGHT);
00105     plotter->line(0, P_HEIGHT / 2, P_WIDTH, P_HEIGHT / 2);
00106     plotter->endpath();
00107 
00108         plotter->erase();
00109 
00110         //Start up updating thread
00111         boost::thread visualUpdate(&DishVisualizer::redraw, this);
00112 
00113         isInit = TRUE;
00114         return 0;
00115 
00116 }
00117 
00127 int DishVisualizer::intMap(double input, double min_in, double max_in,
00128                 int min_out, int max_out) {
00129         int retVal = 0;
00130         //constrain to the range
00131         if (input > max_in) {
00132                 input = max_in;
00133         } else if (input < min_in) {
00134                 input = min_in;
00135         }
00136 
00137         //map the constrained value into the range
00138         retVal = (int) ((input - (float) min_in) * (max_out - min_out)
00139                         / ((float) max_in - (float) min_in) + min_out);
00140         return retVal;
00141 }
00142 
00146 void DishVisualizer::redraw() {
00147         while (isInit) {
00148         for (uint showChan = 0; showChan < data.size(); showChan++) {
00149             uint16_t red = 0;
00150             uint16_t green = 0;
00151             uint16_t blue = 0;
00152 
00153             switch (color_mode)
00154             {
00155                 // Red/blue separated:
00156                 //     Channels at/under threshold are a red gradient
00157                 //     Channels above threshold are solid blue
00158                 case RED_BLUE_SEPARATED:
00159                     if (data[showChan] <= thresholds[showChan])
00160                         red = intMap(data[showChan], min_volts[showChan],
00161                                      thresholds[showChan], MAX_COLOR / 2, 0);
00162                     else
00163                         blue = MAX_COLOR;
00164                     break;
00165 
00166                 // Red/blue mix:
00167                 //     Channels have a mix of red and blue. Mostly red
00168                 //     indicates a low value and mostly blue indicates a
00169                 //     high value.
00170                 case RED_BLUE_MIX:
00171                     red = intMap(data[showChan], min_volts[showChan],
00172                                  max_volts[showChan], MAX_COLOR, 0);
00173                     blue = intMap(data[showChan], min_volts[showChan],
00174                                  max_volts[showChan], 0, MAX_COLOR);
00175                     break;
00176 
00177                 // Red/green/blue:
00178                 //     Channels at/under baseline are a red gradient
00179                 //     Channels above baseline and at/under threshold are
00180                 //       a green gradient
00181                 //     Channels above threshold are solid blue
00182                 case RED_GREEN_BLUE:
00183                     if (data[showChan] <= baselines[showChan])
00184                         red = intMap(data[showChan], min_volts[showChan],
00185                                      thresholds[showChan], MAX_COLOR, 0);
00186                     else if (data[showChan] <= thresholds[showChan])
00187                         green = intMap(data[showChan], min_volts[showChan],
00188                                        thresholds[showChan], MAX_COLOR, 0);
00189                     else
00190                         blue = MAX_COLOR;
00191                     break;
00192 
00193                 // Blue only:
00194                 //     Channels at/under threshold are black
00195                 //     Channels above threshold are solid blue
00196                 case BLUE_ONLY:
00197                     if (data[showChan] > thresholds[showChan])
00198                         blue = MAX_COLOR;
00199                     break;
00200 
00201                 default:
00202                     ROS_ERROR("Color mode (%d) is out of range [0...3]",
00203                               color_mode);
00204                     color_mode = RED_BLUE_SEPARATED;
00205                     break;
00206             }
00207 
00208             plotter->color(red, green, blue);
00209 
00210             //Get the center coordinates and draw the circle
00211             int xPos = centers[showChan][0];
00212             int yPos = centers[showChan][1];
00213 
00214             //ROS_INFO("%d = %f: %d, %d, %d at (%d, %d)", showChan, data[showChan], red, green, blue, xPos, yPos);
00215             plotter->circle(xPos, yPos, RADIUS);
00216                 }
00217 
00218         // Plot CA if it has been updated
00219         if (plot_ca)
00220         {
00221             int x_coord = static_cast<int>((ca.x - 4.5) * X_STEP) + P_WIDTH / 2;
00222             int y_coord = P_HEIGHT / 2 - static_cast<int>((ca.y - 4.5) * Y_STEP);
00223 
00224             plotter->colorname("orange");
00225             plotter->circle(x_coord, y_coord, RADIUS);
00226 
00227             plot_ca = false;
00228         }
00229 
00230         // Draw lines to separate grid into quadrants
00231         plotter->pencolorname("white");
00232         plotter->line(P_WIDTH / 2, 0, P_WIDTH / 2, P_HEIGHT);
00233         plotter->line(0, P_HEIGHT / 2, P_WIDTH, P_HEIGHT / 2);
00234         plotter->endpath();
00235 
00236                 plotter->erase();
00237                 //sleep for a 60th of a second
00238                 boost::this_thread::sleep(boost::posix_time::millisec(16));
00239         }
00240 }
00241 
00247 void DishVisualizer::update(int channel, double newValue) {
00248         if (isInit) {
00249                 boost::mutex::scoped_lock lock(dataUpdate);
00250                 data[channel]= newValue;
00251                 //ROS_INFO("Channel %d (of %d) = %f", channel, data.size(), newValue);
00252         } else {
00253             ROS_ERROR("Visualizer attempted to be updated while not initialized");
00254         }
00255 }
00256 
00261 void DishVisualizer::updateCa(const burst_calc::ca& c)
00262 {
00263     if (isInit)
00264     {
00265         boost::mutex::scoped_lock lock(dataUpdate);
00266         ca = c;
00267         plot_ca = true;
00268     }
00269     else
00270         ROS_ERROR("Visualizer attempted to be updated while not initialized");
00271 }
00272 
00280 void DishVisualizer::setVoltRanges(const boost::array<double, 60>& b,
00281                                    const boost::array<double, 60>& t,
00282                                    const boost::array<double, 60>& min,
00283                                    const boost::array<double, 60>& max)
00284 {
00285     for (int i = 0; i < 60; i++)
00286     {
00287         baselines[i] = b[i];
00288         thresholds[i] = t[i];
00289         min_volts[i] = min[i];
00290         max_volts[i] = max[i];
00291     }
00292 }


dish_viz
Author(s): Abraham Shultz
autogenerated on Sun Jan 5 2014 11:12:31