UtilityH.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /// \file UtilityH.cpp
  2. /// \brief General Math and Control utility functions
  3. /// \author Hatem Darweesh
  4. /// \date May 14, 2016
  5. #include "op_utility/UtilityH.h"
  6. #include <iostream>
  7. #include <sstream>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <sys/types.h>
  11. #include <pwd.h>
  12. using namespace std;
  13. namespace UtilityHNS
  14. {
  15. UtilityH::UtilityH()
  16. {
  17. }
  18. UtilityH::~UtilityH()
  19. {
  20. }
  21. std::string UtilityH::GetHomeDirectory()
  22. {
  23. struct passwd *pw = getpwuid(getuid());
  24. const char *homedir = pw->pw_dir;
  25. return string(homedir);
  26. }
  27. double UtilityH::GetMomentumScaleFactor(const double& v)
  28. {
  29. if(v < 0.3)
  30. return 0.6;
  31. else if(v <6.4)
  32. return 0.3;
  33. else if(v < 20)
  34. {
  35. double m = 0.7/3.6;
  36. return m*(v - 6.4) + 0.3;
  37. }
  38. else
  39. return 0.9;
  40. }
  41. int UtilityH::GetSign(double x)
  42. {
  43. if(x < 0 )
  44. return -1;
  45. else
  46. return 1;
  47. }
  48. double UtilityH::FixNegativeAngle(const double& a)
  49. {
  50. double angle = 0;
  51. if (a < -2.0 * M_PI || a >= 2.0 * M_PI) {
  52. angle = fmod(a, 2.0 * M_PI);
  53. } else {
  54. angle = a;
  55. }
  56. if(angle < 0) {
  57. angle = 2.0 * M_PI + angle;
  58. }
  59. return angle;
  60. }
  61. double UtilityH::SplitPositiveAngle(const double& a)
  62. {
  63. double angle = a;
  64. if (a < -2.0 * M_PI || a >= 2.0 * M_PI) {
  65. angle = fmod(a, 2.0 * M_PI);
  66. }
  67. if (angle >= M_PI) {
  68. angle -= 2.0 * M_PI;
  69. } else if (angle < -M_PI) {
  70. angle += 2.0 * M_PI;
  71. }
  72. return angle;
  73. }
  74. double UtilityH::InverseAngle(const double& a)
  75. {
  76. double angle = 0;
  77. if(a < M_PI) {
  78. angle = a + M_PI;
  79. } else {
  80. angle = a - M_PI;
  81. }
  82. return angle;
  83. }
  84. double UtilityH::AngleBetweenTwoAnglesPositive(const double& a1, const double& a2)
  85. {
  86. double diff = a1 - a2;
  87. if(diff < 0)
  88. diff = a2 - a1;
  89. if(diff > M_PI)
  90. diff = 2.0*M_PI - diff;
  91. return diff;
  92. }
  93. double UtilityH::GetCircularAngle(const double& prevContAngle, const double& prevAngle, const double& currAngle)
  94. {
  95. double diff = currAngle - prevAngle;
  96. if(diff > M_PI)
  97. diff = diff - 2.0*M_PI;
  98. if(diff < -M_PI)
  99. diff = diff + 2.0*M_PI;
  100. double c_ang = 0;
  101. if(prevContAngle == 0 || fabs(diff) < M_PI_2)
  102. c_ang = prevContAngle + diff;
  103. else
  104. c_ang = prevContAngle;
  105. return c_ang;
  106. }
  107. void UtilityH::GetTickCount(struct timespec& t)
  108. {
  109. while(clock_gettime(0, & t) == -1);
  110. }
  111. double UtilityH::GetTimeDiff(const struct timespec& old_t,const struct timespec& curr_t)
  112. {
  113. return (curr_t.tv_sec - old_t.tv_sec) + ((double)(curr_t.tv_nsec - old_t.tv_nsec)/ 1000000000.0);
  114. }
  115. double UtilityH::GetTimeDiffNow(const struct timespec& old_t)
  116. {
  117. struct timespec curr_t;
  118. GetTickCount(curr_t);
  119. return (curr_t.tv_sec - old_t.tv_sec) + ((double)(curr_t.tv_nsec - old_t.tv_nsec)/ 1000000000.0);
  120. }
  121. string UtilityH::GetFilePrefixHourMinuteSeconds()
  122. {
  123. struct timespec now_time;
  124. UtilityH::GetTickCount(now_time);
  125. tm *gmtm = localtime(&now_time.tv_sec);
  126. ostringstream str;
  127. str << "Y" << gmtm->tm_year;
  128. str << "-";
  129. str << "M" << gmtm->tm_mon;
  130. str << "-";
  131. str << "D" << gmtm->tm_mday;
  132. str << "-";
  133. str << "H" << gmtm->tm_hour;
  134. str << "-";
  135. str << "M" << gmtm->tm_min;
  136. str << "-";
  137. str << "S" << gmtm->tm_sec;
  138. return str.str();
  139. }
  140. string UtilityH::GetDateTimeStr()
  141. {
  142. time_t now = time(0);
  143. char* dateStr = ctime(&now);
  144. string str(dateStr, strlen(dateStr)-1);
  145. int index = str.find(" ");
  146. while(index > 0)
  147. {
  148. str.replace(index,1, "_");
  149. index = str.find(" ");
  150. }
  151. index = str.find(":");
  152. while(index > 0)
  153. {
  154. str.replace(index,1, "-");
  155. index = str.find(":");
  156. }
  157. return str;
  158. }
  159. int UtilityH::tsCompare (struct timespec time1, struct timespec time2, int micro_tolerance)
  160. {
  161. long nanoDiff =
  162. (time1.tv_sec * 1000000000 + time1.tv_nsec) -
  163. (time2.tv_sec * 1000000000 + time2.tv_nsec);
  164. if (nanoDiff < -micro_tolerance) {
  165. return -1; // time1 is less than time2
  166. } else if (nanoDiff > micro_tolerance) {
  167. return 1; // time1 is greater than time2
  168. } else {
  169. return 0; // time1 is equal to time2
  170. }
  171. }
  172. timespec UtilityH::GetTimeSpec(const time_t& srcT)
  173. {
  174. timespec dstT;
  175. dstT.tv_sec = srcT/1000000000;
  176. dstT.tv_nsec = srcT - (dstT.tv_sec*1000000000);
  177. return dstT;
  178. }
  179. time_t UtilityH::GetLongTime(const struct timespec& srcT)
  180. {
  181. time_t dstT;
  182. dstT = srcT.tv_sec * 1000000000 + srcT.tv_nsec;
  183. return dstT;
  184. }
  185. PIDController::PIDController()
  186. {
  187. kp = kp_v = 0;
  188. ki = ki_v = 0;
  189. kd = kd_v = 0;
  190. pid_lim = pid_v = 0;
  191. upper_limit = lower_limit = 0;
  192. bEnableLimit= false;
  193. accumErr = 0;
  194. prevErr = 0;
  195. bResetD = false;
  196. bResetI = false;
  197. }
  198. PIDController::PIDController(const double& kp, const double& ki, const double& kd)
  199. {
  200. Init(kp, ki, kd);
  201. upper_limit = lower_limit = 0;
  202. bEnableLimit= false;
  203. accumErr = 0;
  204. prevErr = 0;
  205. bResetD = false;
  206. bResetI = false;
  207. }
  208. void PIDController::Setlimit(const double& upper,const double& lower)
  209. {
  210. upper_limit = upper;
  211. lower_limit = lower;
  212. bEnableLimit = true;
  213. }
  214. double PIDController::getPID(const double& currValue, const double& targetValue)
  215. {
  216. double e = targetValue - currValue;
  217. return getPID(e);
  218. }
  219. double PIDController::getPID(const double& e)
  220. {
  221. //TODO Remember to add sampling time and multiply the time elapsed by the error
  222. //complex PID error calculation
  223. //TODO //De = ( e(i) + 3*e(i-1) - 3*e(i-2) - e(i-3) ) / 6
  224. if(bResetI)
  225. {
  226. bResetI = false;
  227. accumErr = 0;
  228. }
  229. if(bResetD)
  230. {
  231. bResetD = false;
  232. prevErr = e;
  233. }
  234. if(pid_v < upper_limit && pid_v > lower_limit)
  235. accumErr += e;
  236. double edot= e - prevErr;
  237. kp_v = kp * e;
  238. ki_v = ki * accumErr;
  239. kd_v = kd * edot;
  240. pid_v = kp_v + ki_v + kd_v;
  241. pid_lim = pid_v;
  242. if(bEnableLimit)
  243. {
  244. if(pid_v > upper_limit)
  245. {
  246. pid_lim = upper_limit;
  247. }
  248. else if ( pid_v < lower_limit)
  249. {
  250. pid_lim = lower_limit;
  251. }
  252. }
  253. prevErr = e;
  254. return pid_lim;
  255. }
  256. std::string PIDController::ToStringHeader()
  257. {
  258. std::ostringstream str_out;
  259. str_out << "Time" << "," <<"KP" << "," << "KI" << "," << "KD" << "," << "KP_v" << "," << "KI_v" << "," << "KD_v"
  260. << "," << "pid_v" << "," << "," << "pid_lim" << "," << "," << "prevErr" << "," << "accumErr" << "," ;
  261. return str_out.str();
  262. }
  263. std::string PIDController::ToString()
  264. {
  265. std::ostringstream str_out;
  266. timespec t_stamp;
  267. UtilityH::GetTickCount(t_stamp);
  268. str_out << UtilityH::GetLongTime(t_stamp) << "," <<kp << "," << ki << "," << kd << "," << kp_v << "," << ki_v << "," << kd_v
  269. << "," << pid_v << "," << "," << pid_lim << "," << "," << prevErr << "," << accumErr << "," ;
  270. return str_out.str();
  271. }
  272. void PIDController::ResetD()
  273. {
  274. bResetD = true;
  275. }
  276. void PIDController::ResetI()
  277. {
  278. bResetI = true;
  279. }
  280. void PIDController::Init(const double& kp, const double& ki, const double& kd)
  281. {
  282. this->kp = kp;
  283. this->ki = ki;
  284. this->kd = kd;
  285. }
  286. LowpassFilter::LowpassFilter()
  287. {
  288. A = 0;
  289. d1 = 0;
  290. d2 = 0;
  291. w0 = 0;
  292. w1 = 0;
  293. w2 = 0;
  294. m = 0;
  295. sampleF = 0;
  296. cutOffF = 0;
  297. }
  298. LowpassFilter::~LowpassFilter()
  299. {
  300. // if(A)
  301. // delete A;
  302. // if(d1)
  303. // delete d1;
  304. // if(d2)
  305. // delete d2;
  306. // if(w0)
  307. // delete w0;
  308. // if(w1)
  309. // delete w1;
  310. // if(w2)
  311. // delete w2;
  312. }
  313. LowpassFilter::LowpassFilter(const int& filterOrder, const double& sampleFreq, const double& cutOffFreq)
  314. {
  315. Init(filterOrder, sampleFreq, cutOffFreq);
  316. }
  317. void LowpassFilter::Init(const int& n, const double& sampleFreq, const double& cutOffFreq)
  318. {
  319. if(!(n == 2 || n == 4 || n == 6 || n == 8))
  320. {
  321. cout << "Undefined LowpassFilter order ! " << endl;
  322. A = 0;
  323. d1 = 0;
  324. d2 = 0;
  325. w0 = 0;
  326. w1 = 0;
  327. w2 = 0;
  328. m = 0;
  329. sampleF = 0;
  330. cutOffF = 0;
  331. }
  332. else
  333. {
  334. m = n/2;
  335. sampleF = sampleFreq;
  336. cutOffF = cutOffFreq;
  337. double ep = 1;
  338. double s = sampleFreq;
  339. double f = cutOffFreq;
  340. double a = tan(M_PI*f/s);
  341. double a2 = a*a;
  342. double u = log((1.0+sqrt(1.0+ep*ep))/ep);
  343. double su = sinh(u/(double)n);
  344. double cu = cosh(u/(double)n);
  345. double b, c;
  346. // A = new double[m];
  347. // d1 = new double[m];
  348. // d2 = new double[m];
  349. // w0 = new double[m];
  350. // w1 = new double[m];
  351. // w2 = new double[m];
  352. //
  353. // for(int i=0; i < m ; i++)
  354. // {
  355. // A[i] = 0;
  356. // d1[i] = 0;
  357. // d2[i] = 0;
  358. // w0[i] = 0;
  359. // w1[i] = 0;
  360. // w2[i] = 0;
  361. // }
  362. for(int i=0; i< m; ++i)
  363. {
  364. b = sin(M_PI*(2.0*i+1.0)/(2.0*n))*su;
  365. c = cos(M_PI*(2.0*i+1.0)/(2.0*n))*cu;
  366. c = b*b + c*c;
  367. s = a2*c + 2.0*a*b + 1.0;
  368. A = a2/(4.0*s); // 4.0
  369. d1 = 2.0*(1-a2*c)/s;
  370. d2 = -(a2*c - 2.0*a*b + 1.0)/s;
  371. }
  372. }
  373. }
  374. double LowpassFilter::getFilter(const double& value)
  375. {
  376. double ep = 2.3/1.0; // used to normalize
  377. double x = value;
  378. for(int i=0; i<m; ++i)
  379. {
  380. w0 = d1*w1 + d2*w2 + x;
  381. x = A*(w0 + 2.0*w1 + w2);
  382. w2 = w1;
  383. w1 = w0;
  384. }
  385. return ep*x;
  386. }
  387. }