loc_misc_utils.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. /* Copyright (c) 2014, 2020-2021 The Linux Foundation. All rights reserved.
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are
  5. * met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above
  9. * copyright notice, this list of conditions and the following
  10. * disclaimer in the documentation and/or other materials provided
  11. * with the distribution.
  12. * * Neither the name of The Linux Foundation, nor the names of its
  13. * contributors may be used to endorse or promote products derived
  14. * from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  20. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  23. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  24. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  25. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  26. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. */
  29. #define LOG_NDEBUG 0
  30. #define LOG_TAG "LocSvc_misc_utils"
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <inttypes.h>
  34. #include <dlfcn.h>
  35. #include <math.h>
  36. #include <log_util.h>
  37. #include <loc_misc_utils.h>
  38. #include <ctype.h>
  39. #include <fcntl.h>
  40. #include <inttypes.h>
  41. #include <sys/stat.h>
  42. #ifndef MSEC_IN_ONE_SEC
  43. #define MSEC_IN_ONE_SEC 1000ULL
  44. #endif
  45. #define GET_MSEC_FROM_TS(ts) ((ts.tv_sec * MSEC_IN_ONE_SEC) + (ts.tv_nsec + 500000)/1000000)
  46. int loc_util_split_string(char *raw_string, char **split_strings_ptr,
  47. int max_num_substrings, char delimiter)
  48. {
  49. int raw_string_index=0;
  50. int num_split_strings=0;
  51. unsigned char end_string=0;
  52. int raw_string_length=0;
  53. if(!raw_string || !split_strings_ptr) {
  54. LOC_LOGE("%s:%d]: NULL parameters", __func__, __LINE__);
  55. num_split_strings = -1;
  56. goto err;
  57. }
  58. LOC_LOGD("%s:%d]: raw string: %s\n", __func__, __LINE__, raw_string);
  59. raw_string_length = strlen(raw_string) + 1;
  60. split_strings_ptr[num_split_strings] = &raw_string[raw_string_index];
  61. for(raw_string_index=0; raw_string_index < raw_string_length; raw_string_index++) {
  62. if(raw_string[raw_string_index] == '\0')
  63. end_string=1;
  64. if((raw_string[raw_string_index] == delimiter) || end_string) {
  65. raw_string[raw_string_index] = '\0';
  66. if (num_split_strings < max_num_substrings) {
  67. LOC_LOGD("%s:%d]: split string: %s\n",
  68. __func__, __LINE__, split_strings_ptr[num_split_strings]);
  69. }
  70. num_split_strings++;
  71. if(((raw_string_index + 1) < raw_string_length) &&
  72. (num_split_strings < max_num_substrings)) {
  73. split_strings_ptr[num_split_strings] = &raw_string[raw_string_index+1];
  74. }
  75. else {
  76. break;
  77. }
  78. }
  79. if(end_string)
  80. break;
  81. }
  82. err:
  83. LOC_LOGD("%s:%d]: num_split_strings: %d\n", __func__, __LINE__, num_split_strings);
  84. return num_split_strings;
  85. }
  86. void loc_util_trim_space(char *org_string)
  87. {
  88. char *scan_ptr, *write_ptr;
  89. char *first_nonspace = NULL, *last_nonspace = NULL;
  90. if(org_string == NULL) {
  91. LOC_LOGE("%s:%d]: NULL parameter", __func__, __LINE__);
  92. goto err;
  93. }
  94. scan_ptr = write_ptr = org_string;
  95. while (*scan_ptr) {
  96. //Find the first non-space character
  97. if ( !isspace(*scan_ptr) && first_nonspace == NULL) {
  98. first_nonspace = scan_ptr;
  99. }
  100. //Once the first non-space character is found in the
  101. //above check, keep shifting the characters to the left
  102. //to replace the spaces
  103. if (first_nonspace != NULL) {
  104. *(write_ptr++) = *scan_ptr;
  105. //Keep track of which was the last non-space character
  106. //encountered
  107. //last_nonspace will not be updated in the case where
  108. //the string ends with spaces
  109. if ( !isspace(*scan_ptr)) {
  110. last_nonspace = write_ptr;
  111. }
  112. }
  113. scan_ptr++;
  114. }
  115. //Add NULL terminator after the last non-space character
  116. if (last_nonspace) { *last_nonspace = '\0'; }
  117. err:
  118. return;
  119. }
  120. inline void logDlError(const char* failedCall) {
  121. const char * err = dlerror();
  122. LOC_LOGw("%s error: %s", failedCall, (nullptr == err) ? "unknown" : err);
  123. }
  124. void* dlGetSymFromLib(void*& libHandle, const char* libName, const char* symName)
  125. {
  126. void* sym = nullptr;
  127. if ((nullptr != libHandle || nullptr != libName) && nullptr != symName) {
  128. if (nullptr == libHandle) {
  129. libHandle = dlopen(libName, RTLD_NOW);
  130. if (nullptr == libHandle) {
  131. logDlError("dlopen");
  132. }
  133. }
  134. // NOT else, as libHandle gets assigned 5 line above
  135. if (nullptr != libHandle) {
  136. sym = dlsym(libHandle, symName);
  137. if (nullptr == sym) {
  138. logDlError("dlsym");
  139. }
  140. }
  141. } else {
  142. LOC_LOGe("Either libHandle (%p) or libName (%p) must not be null; "
  143. "symName (%p) can not be null.", libHandle, libName, symName);
  144. }
  145. return sym;
  146. }
  147. uint64_t getQTimerTickCount()
  148. {
  149. uint64_t qTimerCount = 0;
  150. #if __aarch64__
  151. asm volatile("mrs %0, cntvct_el0" : "=r" (qTimerCount));
  152. #elif defined (__i386__) || defined (__x86_64__)
  153. /* Qtimer not supported in x86 architecture */
  154. qTimerCount = 0;
  155. #else
  156. asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (qTimerCount));
  157. #endif
  158. return qTimerCount;
  159. }
  160. uint64_t getQTimerDeltaNanos()
  161. {
  162. char qtimer_val_string[100];
  163. char *temp;
  164. uint64_t local_qtimer = 0, remote_qtimer = 0;
  165. int mdm_fd = -1, ret = 0;
  166. uint64_t delta = 0;
  167. memset(qtimer_val_string, '\0', sizeof(qtimer_val_string));
  168. char devNode[] = "/sys/bus/mhi/devices/0306_00.01.00/time_us";
  169. for (; devNode[27] < 3 && mdm_fd < 0; devNode[27]++) {
  170. mdm_fd = ::open(devNode, O_RDONLY);
  171. if (mdm_fd < 0) {
  172. LOC_LOGe("MDM open file: %s error: %s", devNode, strerror(errno));
  173. }
  174. }
  175. if (mdm_fd > 0) {
  176. ret = read(mdm_fd, qtimer_val_string, sizeof(qtimer_val_string)-1);
  177. ::close(mdm_fd);
  178. if (ret < 0) {
  179. LOC_LOGe("MDM read time_us file error: %s", strerror(errno));
  180. } else {
  181. temp = qtimer_val_string;
  182. temp = strchr(temp, ':');
  183. temp = temp + 2;
  184. local_qtimer = atoll(temp);
  185. temp = strchr(temp, ':');
  186. temp = temp + 2;
  187. remote_qtimer = atoll(temp);
  188. if (local_qtimer >= remote_qtimer) {
  189. delta = (local_qtimer - remote_qtimer) * 1000;
  190. }
  191. LOC_LOGv("qtimer values in microseconds: local:%" PRIi64 " remote:%" PRIi64 ""
  192. " delta in nanoseconds:%" PRIi64 "",
  193. local_qtimer, remote_qtimer, delta);
  194. }
  195. }
  196. return delta;
  197. }
  198. uint64_t getQTimerFreq()
  199. {
  200. #if __aarch64__
  201. uint64_t val = 0;
  202. asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
  203. #elif defined (__i386__) || defined (__x86_64__)
  204. /* Qtimer not supported in x86 architecture */
  205. uint64_t val = 0;
  206. #else
  207. uint32_t val = 0;
  208. asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (val));
  209. #endif
  210. return val;
  211. }
  212. uint64_t getBootTimeMilliSec()
  213. {
  214. struct timespec curTs = {};
  215. clock_gettime(CLOCK_BOOTTIME, &curTs);
  216. return (uint64_t)GET_MSEC_FROM_TS(curTs);
  217. }
  218. // Used for convert position/velocity from GSNS antenna based to VRP based
  219. void Matrix_MxV(float a[3][3], float b[3], float c[3]) {
  220. int i, j;
  221. for (i=0; i<3; i++) {
  222. c[i] = 0.0f;
  223. for (j=0; j<3; j++)
  224. c[i] += a[i][j] * b[j];
  225. }
  226. }
  227. // Used for convert position/velocity from GNSS antenna based to VRP based
  228. void Matrix_Skew(float a[3], float c[3][3]) {
  229. c[0][0] = 0.0f;
  230. c[0][1] = -a[2];
  231. c[0][2] = a[1];
  232. c[1][0] = a[2];
  233. c[1][1] = 0.0f;
  234. c[1][2] = -a[0];
  235. c[2][0] = -a[1];
  236. c[2][1] = a[0];
  237. c[2][2] = 0.0f;
  238. }
  239. // Used for convert position/velocity from GNSS antenna based to VRP based
  240. void Euler2Dcm(float euler[3], float dcm[3][3]) {
  241. float cr = 0.0, sr = 0.0, cp = 0.0, sp = 0.0, ch = 0.0, sh = 0.0;
  242. cr = cosf(euler[0]);
  243. sr = sinf(euler[0]);
  244. cp = cosf(euler[1]);
  245. sp = sinf(euler[1]);
  246. ch = cosf(euler[2]);
  247. sh = sinf(euler[2]);
  248. dcm[0][0] = cp * ch;
  249. dcm[0][1] = (sp*sr*ch) - (cr*sh);
  250. dcm[0][2] = (cr*sp*ch) + (sh*sr);
  251. dcm[1][0] = cp * sh;
  252. dcm[1][1] = (sr*sp*sh) + (cr*ch);
  253. dcm[1][2] = (cr*sp*sh) - (sr*ch);
  254. dcm[2][0] = -sp;
  255. dcm[2][1] = sr * cp;
  256. dcm[2][2] = cr * cp;
  257. }
  258. // Used for convert position from GSNS based to VRP based
  259. // The converted position will be stored in the llaInfo parameter.
  260. #define A6DOF_WGS_A (6378137.0f)
  261. #define A6DOF_WGS_B (6335439.0f)
  262. #define A6DOF_WGS_E2 (0.00669437999014f)
  263. void loc_convert_lla_gnss_to_vrp(double lla[3], float rollPitchYaw[3],
  264. float leverArm[3]) {
  265. LOC_LOGv("lla: %f, %f, %f, lever arm: %f %f %f, "
  266. "rollpitchyaw: %f %f %f",
  267. lla[0], lla[1], lla[2],
  268. leverArm[0], leverArm[1], leverArm[2],
  269. rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2]);
  270. float cnb[3][3];
  271. memset(cnb, 0, sizeof(cnb));
  272. Euler2Dcm(rollPitchYaw, cnb);
  273. float sl = sin(lla[0]);
  274. float cl = cos(lla[0]);
  275. float sf = 1.0f / (1.0f - A6DOF_WGS_E2 * sl* sl);
  276. float sfr = sqrtf(sf);
  277. float rn = A6DOF_WGS_B * sf * sfr + lla[2];
  278. float re = A6DOF_WGS_A * sfr + lla[2];
  279. float deltaNEU[3];
  280. // gps_pos_lla = imu_pos_lla + Cbn*la_b .* [1/geo.Rn; 1/(geo.Re*geo.cL); -1];
  281. Matrix_MxV(cnb, leverArm, deltaNEU);
  282. // NED to lla conversion
  283. lla[0] = lla[0] + deltaNEU[0] / rn;
  284. lla[1] = lla[1] + deltaNEU[1] / (re * cl);
  285. lla[2] = lla[2] + deltaNEU[2];
  286. }
  287. // Used for convert velocity from GSNS based to VRP based
  288. // The converted velocity will be stored in the enuVelocity parameter.
  289. void loc_convert_velocity_gnss_to_vrp(float enuVelocity[3], float rollPitchYaw[3],
  290. float rollPitchYawRate[3], float leverArm[3]) {
  291. LOC_LOGv("enu velocity: %f, %f, %f, lever arm: %f %f %f, roll pitch yaw: %f %f %f,"
  292. "rollpitchyawRate: %f %f %f",
  293. enuVelocity[0], enuVelocity[1], enuVelocity[2],
  294. leverArm[0], leverArm[1], leverArm[2],
  295. rollPitchYaw[0], rollPitchYaw[1], rollPitchYaw[2],
  296. rollPitchYawRate[0], rollPitchYawRate[1], rollPitchYawRate[2]);
  297. float cnb[3][3];
  298. memset(cnb, 0, sizeof(cnb));
  299. Euler2Dcm(rollPitchYaw, cnb);
  300. float skewLA[3][3];
  301. memset(skewLA, 0, sizeof(skewLA));
  302. Matrix_Skew(leverArm, skewLA);
  303. float tmp[3];
  304. float deltaEnuVelocity[3];
  305. memset(tmp, 0, sizeof(tmp));
  306. memset(deltaEnuVelocity, 0, sizeof(deltaEnuVelocity));
  307. Matrix_MxV(skewLA, rollPitchYawRate, tmp);
  308. Matrix_MxV(cnb, tmp, deltaEnuVelocity);
  309. enuVelocity[0] = enuVelocity[0] - deltaEnuVelocity[0];
  310. enuVelocity[1] = enuVelocity[1] - deltaEnuVelocity[1];
  311. enuVelocity[2] = enuVelocity[2] - deltaEnuVelocity[2];
  312. }
  313. // Wait for the system script(rootdir/etc/init.qcom.rc) to create the folder
  314. void locUtilWaitForDir(const char* dirName) {
  315. struct stat buf_stat;
  316. while (1) {
  317. LOC_LOGv("waiting for %s...", dirName);
  318. int rc = stat(dirName, &buf_stat);
  319. if (!rc) {
  320. break;
  321. }
  322. //check every 100ms
  323. usleep(100000);
  324. }
  325. LOC_LOGv("done");
  326. }