1/* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.h" 12 13#include <math.h> 14#include <stdio.h> 15 16#include <algorithm> 17#include <sstream> 18 19#ifdef MATLAB 20#include "engine.h" 21#endif 22 23#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 24#include "webrtc/system_wrappers/interface/event_wrapper.h" 25#include "webrtc/system_wrappers/interface/thread_wrapper.h" 26#include "webrtc/system_wrappers/interface/tick_util.h" 27 28using namespace webrtc; 29 30#ifdef MATLAB 31MatlabEngine eng; 32 33MatlabLine::MatlabLine(int maxLen /*= -1*/, const char *plotAttrib /*= NULL*/, const char *name /*= NULL*/) 34: 35_xArray(NULL), 36_yArray(NULL), 37_maxLen(maxLen), 38_plotAttribute(), 39_name() 40{ 41 if (_maxLen > 0) 42 { 43 _xArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); 44 _yArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); 45 } 46 47 if (plotAttrib) 48 { 49 _plotAttribute = plotAttrib; 50 } 51 52 if (name) 53 { 54 _name = name; 55 } 56} 57 58MatlabLine::~MatlabLine() 59{ 60 if (_xArray != NULL) 61 { 62 mxDestroyArray(_xArray); 63 } 64 if (_yArray != NULL) 65 { 66 mxDestroyArray(_yArray); 67 } 68} 69 70void MatlabLine::Append(double x, double y) 71{ 72 if (_maxLen > 0 && _xData.size() > static_cast<uint32_t>(_maxLen)) 73 { 74 _xData.resize(_maxLen); 75 _yData.resize(_maxLen); 76 } 77 78 _xData.push_front(x); 79 _yData.push_front(y); 80} 81 82 83// append y-data with running integer index as x-data 84void MatlabLine::Append(double y) 85{ 86 if (_xData.empty()) 87 { 88 // first element is index 0 89 Append(0, y); 90 } 91 else 92 { 93 // take last x-value and increment 94 double temp = _xData.back(); // last x-value 95 Append(temp + 1, y); 96 } 97} 98 99 100void MatlabLine::SetMaxLen(int maxLen) 101{ 102 if (maxLen <= 0) 103 { 104 // means no maxLen 105 _maxLen = -1; 106 } 107 else 108 { 109 _maxLen = maxLen; 110 111 if (_xArray != NULL) 112 { 113 mxDestroyArray(_xArray); 114 mxDestroyArray(_yArray); 115 } 116 _xArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); 117 _yArray = mxCreateDoubleMatrix(1, _maxLen, mxREAL); 118 119 maxLen = ((unsigned int)maxLen <= _xData.size()) ? maxLen : (int)_xData.size(); 120 _xData.resize(maxLen); 121 _yData.resize(maxLen); 122 123 //// reserve the right amount of memory 124 //_xData.reserve(_maxLen); 125 //_yData.reserve(_maxLen); 126 } 127} 128 129void MatlabLine::SetAttribute(char *plotAttrib) 130{ 131 _plotAttribute = plotAttrib; 132} 133 134void MatlabLine::SetName(char *name) 135{ 136 _name = name; 137} 138 139void MatlabLine::GetPlotData(mxArray** xData, mxArray** yData) 140{ 141 // Make sure we have enough Matlab allocated memory. 142 // Assuming both arrays (x and y) are of the same size. 143 if (_xData.empty()) 144 { 145 return; // No data 146 } 147 unsigned int size = 0; 148 if (_xArray != NULL) 149 { 150 size = (unsigned int)mxGetNumberOfElements(_xArray); 151 } 152 if (size < _xData.size()) 153 { 154 if (_xArray != NULL) 155 { 156 mxDestroyArray(_xArray); 157 mxDestroyArray(_yArray); 158 } 159 _xArray = mxCreateDoubleMatrix(1, _xData.size(), mxREAL); 160 _yArray = mxCreateDoubleMatrix(1, _yData.size(), mxREAL); 161 } 162 163 if (!_xData.empty()) 164 { 165 double* x = mxGetPr(_xArray); 166 167 std::list<double>::iterator it = _xData.begin(); 168 169 for (int i = 0; it != _xData.end(); it++, i++) 170 { 171 x[i] = *it; 172 } 173 } 174 175 if (!_yData.empty()) 176 { 177 double* y = mxGetPr(_yArray); 178 179 std::list<double>::iterator it = _yData.begin(); 180 181 for (int i = 0; it != _yData.end(); it++, i++) 182 { 183 y[i] = *it; 184 } 185 } 186 *xData = _xArray; 187 *yData = _yArray; 188} 189 190std::string MatlabLine::GetXName() 191{ 192 std::ostringstream xString; 193 xString << "x_" << _name; 194 return xString.str(); 195} 196 197std::string MatlabLine::GetYName() 198{ 199 std::ostringstream yString; 200 yString << "y_" << _name; 201 return yString.str(); 202} 203 204std::string MatlabLine::GetPlotString() 205{ 206 207 std::ostringstream s; 208 209 if (_xData.size() == 0) 210 { 211 s << "[0 1], [0 1]"; // To get an empty plot 212 } 213 else 214 { 215 s << GetXName() << "(1:" << _xData.size() << "),"; 216 s << GetYName() << "(1:" << _yData.size() << ")"; 217 } 218 219 s << ", '"; 220 s << _plotAttribute; 221 s << "'"; 222 223 return s.str(); 224} 225 226std::string MatlabLine::GetRefreshString() 227{ 228 std::ostringstream s; 229 230 if (_xData.size() > 0) 231 { 232 s << "set(h,'xdata',"<< GetXName() <<"(1:" << _xData.size() << "),'ydata',"<< GetYName() << "(1:" << _yData.size() << "));"; 233 } 234 else 235 { 236 s << "set(h,'xdata',[NaN],'ydata',[NaN]);"; 237 } 238 return s.str(); 239} 240 241std::string MatlabLine::GetLegendString() 242{ 243 return ("'" + _name + "'"); 244} 245 246bool MatlabLine::hasLegend() 247{ 248 return (!_name.empty()); 249} 250 251 252// remove data points, but keep attributes 253void MatlabLine::Reset() 254{ 255 _xData.clear(); 256 _yData.clear(); 257} 258 259 260void MatlabLine::UpdateTrendLine(MatlabLine * sourceData, double slope, double offset) 261{ 262 Reset(); // reset data, not attributes and name 263 264 double thexMin = sourceData->xMin(); 265 double thexMax = sourceData->xMax(); 266 Append(thexMin, thexMin * slope + offset); 267 Append(thexMax, thexMax * slope + offset); 268} 269 270double MatlabLine::xMin() 271{ 272 if (!_xData.empty()) 273 { 274 std::list<double>::iterator theStart = _xData.begin(); 275 std::list<double>::iterator theEnd = _xData.end(); 276 return(*min_element(theStart, theEnd)); 277 } 278 return (0.0); 279} 280 281double MatlabLine::xMax() 282{ 283 if (!_xData.empty()) 284 { 285 std::list<double>::iterator theStart = _xData.begin(); 286 std::list<double>::iterator theEnd = _xData.end(); 287 return(*max_element(theStart, theEnd)); 288 } 289 return (0.0); 290} 291 292double MatlabLine::yMin() 293{ 294 if (!_yData.empty()) 295 { 296 std::list<double>::iterator theStart = _yData.begin(); 297 std::list<double>::iterator theEnd = _yData.end(); 298 return(*min_element(theStart, theEnd)); 299 } 300 return (0.0); 301} 302 303double MatlabLine::yMax() 304{ 305 if (!_yData.empty()) 306 { 307 std::list<double>::iterator theStart = _yData.begin(); 308 std::list<double>::iterator theEnd = _yData.end(); 309 return(*max_element(theStart, theEnd)); 310 } 311 return (0.0); 312} 313 314 315 316MatlabTimeLine::MatlabTimeLine(int horizonSeconds /*= -1*/, const char *plotAttrib /*= NULL*/, 317 const char *name /*= NULL*/, 318 int64_t refTimeMs /* = -1*/) 319 : 320_timeHorizon(horizonSeconds), 321MatlabLine(-1, plotAttrib, name) // infinite number of elements 322{ 323 if (refTimeMs < 0) 324 _refTimeMs = TickTime::MillisecondTimestamp(); 325 else 326 _refTimeMs = refTimeMs; 327} 328 329void MatlabTimeLine::Append(double y) 330{ 331 MatlabLine::Append(static_cast<double>(TickTime::MillisecondTimestamp() - _refTimeMs) / 1000.0, y); 332 333 PurgeOldData(); 334} 335 336 337void MatlabTimeLine::PurgeOldData() 338{ 339 if (_timeHorizon > 0) 340 { 341 // remove old data 342 double historyLimit = static_cast<double>(TickTime::MillisecondTimestamp() - _refTimeMs) / 1000.0 343 - _timeHorizon; // remove data points older than this 344 345 std::list<double>::reverse_iterator ritx = _xData.rbegin(); 346 uint32_t removeCount = 0; 347 while (ritx != _xData.rend()) 348 { 349 if (*ritx >= historyLimit) 350 { 351 break; 352 } 353 ritx++; 354 removeCount++; 355 } 356 if (removeCount == 0) 357 { 358 return; 359 } 360 361 // remove the range [begin, it). 362 //if (removeCount > 10) 363 //{ 364 // printf("Removing %lu elements\n", removeCount); 365 //} 366 _xData.resize(_xData.size() - removeCount); 367 _yData.resize(_yData.size() - removeCount); 368 } 369} 370 371 372int64_t MatlabTimeLine::GetRefTime() 373{ 374 return(_refTimeMs); 375} 376 377 378 379 380MatlabPlot::MatlabPlot() 381: 382_figHandle(-1), 383_smartAxis(false), 384_critSect(CriticalSectionWrapper::CreateCriticalSection()), 385_timeToPlot(false), 386_plotting(false), 387_enabled(true), 388_firstPlot(true), 389_legendEnabled(true), 390_donePlottingEvent(EventWrapper::Create()) 391{ 392 CriticalSectionScoped cs(_critSect); 393 394 _xlim[0] = 0; 395 _xlim[1] = 0; 396 _ylim[0] = 0; 397 _ylim[1] = 0; 398 399#ifdef PLOT_TESTING 400 _plotStartTime = -1; 401 _plotDelay = 0; 402#endif 403 404} 405 406 407MatlabPlot::~MatlabPlot() 408{ 409 _critSect->Enter(); 410 411 // delete all line objects 412 while (!_line.empty()) 413 { 414 delete *(_line.end() - 1); 415 _line.pop_back(); 416 } 417 418 delete _critSect; 419 delete _donePlottingEvent; 420} 421 422 423int MatlabPlot::AddLine(int maxLen /*= -1*/, const char *plotAttrib /*= NULL*/, const char *name /*= NULL*/) 424{ 425 CriticalSectionScoped cs(_critSect); 426 if (!_enabled) 427 { 428 return -1; 429 } 430 431 MatlabLine *newLine = new MatlabLine(maxLen, plotAttrib, name); 432 _line.push_back(newLine); 433 434 return (static_cast<int>(_line.size() - 1)); // index of newly inserted line 435} 436 437 438int MatlabPlot::AddTimeLine(int maxLen /*= -1*/, const char *plotAttrib /*= NULL*/, const char *name /*= NULL*/, 439 int64_t refTimeMs /*= -1*/) 440{ 441 CriticalSectionScoped cs(_critSect); 442 443 if (!_enabled) 444 { 445 return -1; 446 } 447 448 MatlabTimeLine *newLine = new MatlabTimeLine(maxLen, plotAttrib, name, refTimeMs); 449 _line.push_back(newLine); 450 451 return (static_cast<int>(_line.size() - 1)); // index of newly inserted line 452} 453 454 455int MatlabPlot::GetLineIx(const char *name) 456{ 457 CriticalSectionScoped cs(_critSect); 458 459 if (!_enabled) 460 { 461 return -1; 462 } 463 464 // search the list for a matching line name 465 std::vector<MatlabLine*>::iterator it = _line.begin(); 466 bool matchFound = false; 467 int lineIx = 0; 468 469 for (; it != _line.end(); it++, lineIx++) 470 { 471 if ((*it)->_name == name) 472 { 473 matchFound = true; 474 break; 475 } 476 } 477 478 if (matchFound) 479 { 480 return (lineIx); 481 } 482 else 483 { 484 return (-1); 485 } 486} 487 488 489void MatlabPlot::Append(int lineIndex, double x, double y) 490{ 491 CriticalSectionScoped cs(_critSect); 492 493 if (!_enabled) 494 { 495 return; 496 } 497 498 // sanity for index 499 if (lineIndex < 0 || lineIndex >= static_cast<int>(_line.size())) 500 { 501 throw "Line index out of range"; 502 exit(1); 503 } 504 505 return (_line[lineIndex]->Append(x, y)); 506} 507 508 509void MatlabPlot::Append(int lineIndex, double y) 510{ 511 CriticalSectionScoped cs(_critSect); 512 513 if (!_enabled) 514 { 515 return; 516 } 517 518 // sanity for index 519 if (lineIndex < 0 || lineIndex >= static_cast<int>(_line.size())) 520 { 521 throw "Line index out of range"; 522 exit(1); 523 } 524 525 return (_line[lineIndex]->Append(y)); 526} 527 528 529int MatlabPlot::Append(const char *name, double x, double y) 530{ 531 CriticalSectionScoped cs(_critSect); 532 533 if (!_enabled) 534 { 535 return -1; 536 } 537 538 // search the list for a matching line name 539 int lineIx = GetLineIx(name); 540 541 if (lineIx < 0) //(!matchFound) 542 { 543 // no match; append new line 544 lineIx = AddLine(-1, NULL, name); 545 } 546 547 // append data to line 548 Append(lineIx, x, y); 549 return (lineIx); 550} 551 552int MatlabPlot::Append(const char *name, double y) 553{ 554 CriticalSectionScoped cs(_critSect); 555 556 if (!_enabled) 557 { 558 return -1; 559 } 560 561 // search the list for a matching line name 562 int lineIx = GetLineIx(name); 563 564 if (lineIx < 0) //(!matchFound) 565 { 566 // no match; append new line 567 lineIx = AddLine(-1, NULL, name); 568 } 569 570 // append data to line 571 Append(lineIx, y); 572 return (lineIx); 573} 574 575int MatlabPlot::Length(char *name) 576{ 577 CriticalSectionScoped cs(_critSect); 578 579 if (!_enabled) 580 { 581 return -1; 582 } 583 584 int ix = GetLineIx(name); 585 if (ix >= 0) 586 { 587 return (static_cast<int>(_line[ix]->_xData.size())); 588 } 589 else 590 { 591 return (-1); 592 } 593} 594 595 596void MatlabPlot::SetPlotAttribute(char *name, char *plotAttrib) 597{ 598 CriticalSectionScoped cs(_critSect); 599 600 if (!_enabled) 601 { 602 return; 603 } 604 605 int lineIx = GetLineIx(name); 606 607 if (lineIx >= 0) 608 { 609 _line[lineIx]->SetAttribute(plotAttrib); 610 } 611} 612 613// Must be called under critical section _critSect 614void MatlabPlot::UpdateData(Engine* ep) 615{ 616 if (!_enabled) 617 { 618 return; 619 } 620 621 for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) 622 { 623 mxArray* xData = NULL; 624 mxArray* yData = NULL; 625 (*it)->GetPlotData(&xData, &yData); 626 if (xData != NULL) 627 { 628 std::string xName = (*it)->GetXName(); 629 std::string yName = (*it)->GetYName(); 630 _critSect->Leave(); 631#ifdef MATLAB6 632 mxSetName(xData, xName.c_str()); 633 mxSetName(yData, yName.c_str()); 634 engPutArray(ep, xData); 635 engPutArray(ep, yData); 636#else 637 int ret = engPutVariable(ep, xName.c_str(), xData); 638 assert(ret == 0); 639 ret = engPutVariable(ep, yName.c_str(), yData); 640 assert(ret == 0); 641#endif 642 _critSect->Enter(); 643 } 644 } 645} 646 647bool MatlabPlot::GetPlotCmd(std::ostringstream & cmd, Engine* ep) 648{ 649 _critSect->Enter(); 650 651 if (!DataAvailable()) 652 { 653 return false; 654 } 655 656 if (_firstPlot) 657 { 658 GetPlotCmd(cmd); 659 _firstPlot = false; 660 } 661 else 662 { 663 GetRefreshCmd(cmd); 664 } 665 666 UpdateData(ep); 667 668 _critSect->Leave(); 669 670 return true; 671} 672 673// Call inside critsect 674void MatlabPlot::GetPlotCmd(std::ostringstream & cmd) 675{ 676 // we have something to plot 677 // empty the stream 678 cmd.str(""); // (this seems to be the only way) 679 680 cmd << "figure; h" << _figHandle << "= plot("; 681 682 // first line 683 std::vector<MatlabLine*>::iterator it = _line.begin(); 684 cmd << (*it)->GetPlotString(); 685 686 it++; 687 688 // remaining lines 689 for (; it != _line.end(); it++) 690 { 691 cmd << ", "; 692 cmd << (*it)->GetPlotString(); 693 } 694 695 cmd << "); "; 696 697 if (_legendEnabled) 698 { 699 GetLegendCmd(cmd); 700 } 701 702 if (_smartAxis) 703 { 704 double xMin = _xlim[0]; 705 double xMax = _xlim[1]; 706 double yMax = _ylim[1]; 707 for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) 708 { 709 xMax = std::max(xMax, (*it)->xMax()); 710 xMin = std::min(xMin, (*it)->xMin()); 711 712 yMax = std::max(yMax, (*it)->yMax()); 713 yMax = std::max(yMax, fabs((*it)->yMin())); 714 } 715 _xlim[0] = xMin; 716 _xlim[1] = xMax; 717 _ylim[0] = -yMax; 718 _ylim[1] = yMax; 719 720 cmd << "axis([" << _xlim[0] << ", " << _xlim[1] << ", " << _ylim[0] << ", " << _ylim[1] << "]);"; 721 } 722 723 int i=1; 724 for (it = _line.begin(); it != _line.end(); i++, it++) 725 { 726 cmd << "set(h" << _figHandle << "(" << i << "), 'Tag', " << (*it)->GetLegendString() << ");"; 727 } 728} 729 730// Call inside critsect 731void MatlabPlot::GetRefreshCmd(std::ostringstream & cmd) 732{ 733 cmd.str(""); // (this seems to be the only way) 734 std::vector<MatlabLine*>::iterator it = _line.begin(); 735 for (it = _line.begin(); it != _line.end(); it++) 736 { 737 cmd << "h = findobj(0, 'Tag', " << (*it)->GetLegendString() << ");"; 738 cmd << (*it)->GetRefreshString(); 739 } 740 //if (_legendEnabled) 741 //{ 742 // GetLegendCmd(cmd); 743 //} 744} 745 746void MatlabPlot::GetLegendCmd(std::ostringstream & cmd) 747{ 748 std::vector<MatlabLine*>::iterator it = _line.begin(); 749 bool anyLegend = false; 750 for (; it != _line.end(); it++) 751 { 752 anyLegend = anyLegend || (*it)->hasLegend(); 753 } 754 if (anyLegend) 755 { 756 // create the legend 757 758 cmd << "legend(h" << _figHandle << ",{"; 759 760 761 // iterate lines 762 int i = 0; 763 for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) 764 { 765 if (i > 0) 766 { 767 cmd << ", "; 768 } 769 cmd << (*it)->GetLegendString(); 770 i++; 771 } 772 773 cmd << "}, 2); "; // place legend in upper-left corner 774 } 775} 776 777// Call inside critsect 778bool MatlabPlot::DataAvailable() 779{ 780 if (!_enabled) 781 { 782 return false; 783 } 784 785 for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) 786 { 787 (*it)->PurgeOldData(); 788 } 789 790 return true; 791} 792 793void MatlabPlot::Plot() 794{ 795 CriticalSectionScoped cs(_critSect); 796 797 _timeToPlot = true; 798 799#ifdef PLOT_TESTING 800 _plotStartTime = TickTime::MillisecondTimestamp(); 801#endif 802} 803 804 805void MatlabPlot::Reset() 806{ 807 CriticalSectionScoped cs(_critSect); 808 809 _enabled = true; 810 811 for (std::vector<MatlabLine*>::iterator it = _line.begin(); it != _line.end(); it++) 812 { 813 (*it)->Reset(); 814 } 815 816} 817 818void MatlabPlot::SetFigHandle(int handle) 819{ 820 CriticalSectionScoped cs(_critSect); 821 822 if (handle > 0) 823 _figHandle = handle; 824} 825 826bool 827MatlabPlot::TimeToPlot() 828{ 829 CriticalSectionScoped cs(_critSect); 830 return _enabled && _timeToPlot; 831} 832 833void 834MatlabPlot::Plotting() 835{ 836 CriticalSectionScoped cs(_critSect); 837 _plotting = true; 838} 839 840void 841MatlabPlot::DonePlotting() 842{ 843 CriticalSectionScoped cs(_critSect); 844 _timeToPlot = false; 845 _plotting = false; 846 _donePlottingEvent->Set(); 847} 848 849void 850MatlabPlot::DisablePlot() 851{ 852 _critSect->Enter(); 853 while (_plotting) 854 { 855 _critSect->Leave(); 856 _donePlottingEvent->Wait(WEBRTC_EVENT_INFINITE); 857 _critSect->Enter(); 858 } 859 _enabled = false; 860} 861 862int MatlabPlot::MakeTrend(const char *sourceName, const char *trendName, double slope, double offset, const char *plotAttrib) 863{ 864 CriticalSectionScoped cs(_critSect); 865 866 int sourceIx; 867 int trendIx; 868 869 sourceIx = GetLineIx(sourceName); 870 if (sourceIx < 0) 871 { 872 // could not find source 873 return (-1); 874 } 875 876 trendIx = GetLineIx(trendName); 877 if (trendIx < 0) 878 { 879 // no trend found; add new line 880 trendIx = AddLine(2 /*maxLen*/, plotAttrib, trendName); 881 } 882 883 _line[trendIx]->UpdateTrendLine(_line[sourceIx], slope, offset); 884 885 return (trendIx); 886 887} 888 889 890MatlabEngine::MatlabEngine() 891: 892_critSect(CriticalSectionWrapper::CreateCriticalSection()), 893_eventPtr(NULL), 894_plotThread(NULL), 895_running(false), 896_numPlots(0) 897{ 898 _eventPtr = EventWrapper::Create(); 899 900 _plotThread = ThreadWrapper::CreateThread(MatlabEngine::PlotThread, this, kLowPriority, "MatlabPlot"); 901 902 if (_plotThread == NULL) 903 { 904 throw "Unable to start MatlabEngine thread"; 905 exit(1); 906 } 907 908 _running = true; 909 910 unsigned int tid; 911 _plotThread->Start(tid); 912 913} 914 915MatlabEngine::~MatlabEngine() 916{ 917 _critSect->Enter(); 918 919 if (_plotThread) 920 { 921 _plotThread->SetNotAlive(); 922 _running = false; 923 _eventPtr->Set(); 924 925 while (!_plotThread->Stop()) 926 { 927 ; 928 } 929 930 delete _plotThread; 931 } 932 933 _plots.clear(); 934 935 _plotThread = NULL; 936 937 delete _eventPtr; 938 _eventPtr = NULL; 939 940 _critSect->Leave(); 941 delete _critSect; 942 943} 944 945MatlabPlot * MatlabEngine::NewPlot(MatlabPlot *newPlot) 946{ 947 CriticalSectionScoped cs(_critSect); 948 949 //MatlabPlot *newPlot = new MatlabPlot(); 950 951 if (newPlot) 952 { 953 newPlot->SetFigHandle(++_numPlots); // first plot is number 1 954 _plots.push_back(newPlot); 955 } 956 957 return (newPlot); 958 959} 960 961 962void MatlabEngine::DeletePlot(MatlabPlot *plot) 963{ 964 CriticalSectionScoped cs(_critSect); 965 966 if (plot == NULL) 967 { 968 return; 969 } 970 971 std::vector<MatlabPlot *>::iterator it; 972 for (it = _plots.begin(); it < _plots.end(); it++) 973 { 974 if (plot == *it) 975 { 976 break; 977 } 978 } 979 980 assert (plot == *it); 981 982 (*it)->DisablePlot(); 983 984 _plots.erase(it); 985 --_numPlots; 986 987 delete plot; 988} 989 990 991bool MatlabEngine::PlotThread(void *obj) 992{ 993 if (!obj) 994 { 995 return (false); 996 } 997 998 MatlabEngine *eng = (MatlabEngine *) obj; 999 1000 Engine *ep = engOpen(NULL); 1001 if (!ep) 1002 { 1003 throw "Cannot open Matlab engine"; 1004 return (false); 1005 } 1006 1007 engSetVisible(ep, true); 1008 engEvalString(ep, "close all;"); 1009 1010 while (eng->_running) 1011 { 1012 eng->_critSect->Enter(); 1013 1014 // iterate through all plots 1015 for (unsigned int ix = 0; ix < eng->_plots.size(); ix++) 1016 { 1017 MatlabPlot *plot = eng->_plots[ix]; 1018 if (plot->TimeToPlot()) 1019 { 1020 plot->Plotting(); 1021 eng->_critSect->Leave(); 1022 std::ostringstream cmd; 1023 1024 if (engEvalString(ep, cmd.str().c_str())) 1025 { 1026 // engine dead 1027 return (false); 1028 } 1029 1030 // empty the stream 1031 cmd.str(""); // (this seems to be the only way) 1032 if (plot->GetPlotCmd(cmd, ep)) 1033 { 1034 // things to plot, we have already accessed what we need in the plot 1035 plot->DonePlotting(); 1036 1037 int64_t start = TickTime::MillisecondTimestamp(); 1038 // plot it 1039 int ret = engEvalString(ep, cmd.str().c_str()); 1040 printf("time=%I64i\n", TickTime::MillisecondTimestamp() - start); 1041 if (ret) 1042 { 1043 // engine dead 1044 return (false); 1045 } 1046 1047#ifdef PLOT_TESTING 1048 if(plot->_plotStartTime >= 0) 1049 { 1050 plot->_plotDelay = TickTime::MillisecondTimestamp() - plot->_plotStartTime; 1051 plot->_plotStartTime = -1; 1052 } 1053#endif 1054 } 1055 eng->_critSect->Enter(); 1056 } 1057 } 1058 1059 eng->_critSect->Leave(); 1060 // wait a while 1061 eng->_eventPtr->Wait(66); // 33 ms 1062 } 1063 1064 if (ep) 1065 { 1066 engClose(ep); 1067 ep = NULL; 1068 } 1069 1070 return (true); 1071 1072} 1073 1074#endif // MATLAB 1075