PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/webrtc/modules/rtp_rtcp/test/BWEStandAlone/MatlabPlot.cc

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