时间同步功能,已实现PPS功能,DjiTimeSync_TransferToAircraftTime能同步到飞机的时...

Comments

27 comments

  • DJI Developer Support
    时间同步的是GPS时间,需要断开模拟器,在GPS信号良好的环境中进行时间获取或转换。本地时间需要UTC时间加时区。 ![](https://djisdksupport.zendesk.com/attachments/token/dj8FZ9KO9hpGlF1f5XqY3Fa3L/?name=image.png)
    0
    Comment actions Permalink
  • towel

      我在户外信号良好的情况下得到的时间日期是16号,跟实际差的比较多,时区差应该最多也不超过一天吧

    0
    Comment actions Permalink
  • DJI Developer Support
     我在户外信号良好的情况下得到的时间日期是16号,跟实际差的比较多,时区差应该最多也不超过一天吧
    0
    Comment actions Permalink
  • DJI Developer Support
    通过TOPIC:DJI_FC_SUBSCRIPTION_TOPIC_GPS_DATE,DJI_FC_SUBSCRIPTION_TOPIC_GPS_TIME拿到的时间是多少呢?
    0
    Comment actions Permalink
  • DJI Developer Support
     20151018 5538
    0
    Comment actions Permalink
  • DJI Developer Support
    这个时间看起来不是实际环境中的时间,断开模拟器,重启一下飞机并连接遥控器查看确认GPS信号状态。如果还是不对,麻烦导出飞机log提交到dev@dji.com邮箱,我们查看log记录时间(备注一下测试时的北京时间)。
    0
    Comment actions Permalink
  • DJI Developer Support
      osalHandler->GetTimeMs(&currentTimeMs); 是32位的,得出来的时间存在着溢出,这个会影响DjiTimeSync_TransferToAircraftTime 这个函数的使用吗
    0
    Comment actions Permalink
  • DJI Developer Support
    Linux平台这个回调要修改一下,不修改会出现溢出导致本地时间无效报错。可以改成从0按ms计数,也可以启动时获取一下本地时间,然后获取时间先减去启动的时间再通过这个回调赋值传给PSDK lib。 5.16 时间同步(time_sync) https://sdk-forum.dji.net/hc/zh-cn/articles/7025264281241 ![](https://djisdksupport.zendesk.com/attachments/token/r4qb5uKWvKy47zSiqXzhhnlef/?name=image.png)
    0
    Comment actions Permalink
  • DJI Developer Support
      改为从零开始计时后反而一起报错 [time_sync]-[Error]-[DjiTimeSync_ReceiveAircraftTimestampHandle:470) aircraft timestamp package is invalid, local: 1203829135000, trigger: 1659061204947000.
    0
    Comment actions Permalink
  • 0
    Comment actions Permalink
  • towel

       你好, local的时间是哪里的时间,我把时间都同步为64位后,

    DjiTest_TimeSyncTask的while循环没有进入,trigger的时间是我本地的时间

    0
    Comment actions Permalink
  • towel

    关于osalHandler->GetTimeMs 这个函数, psdk改不了吧,被封装了,

    0
    Comment actions Permalink
  • DJI Developer Support
    osalHandler->GetTimeMs这个是外部注册的回调,外部根据使用平台实现,PSDK内部也会调用这个回调。函数实现代码文件:osal.c
    0
    Comment actions Permalink
  • towel

      GPS信号正常,同步飞机调用也正常后,得到的飞机时间还是有问题

    0
    Comment actions Permalink
  • DJI Developer Support
    飞机固件版本和PSDK版本分别是多少?我这边用最新的版本测试时间是正常的(北京时间+8)。 ![](https://djisdksupport.zendesk.com/attachments/token/s57h0rs02M20pzTrUmYHZfhuL/?name=image.png)
    0
    Comment actions Permalink
  • DJI Developer Support
    飞机是这周刚更新最新的固件,PSDK是3.1的
    0
    Comment actions Permalink
  • DJI Developer Support
    PSDK用最新的master分支试试,我这边用的是最新的master版本(1509)。TOPIC获取飞机时间是对的,飞机端的时间应该没有问题,如果PSDK版本也没有问题,可能就要查代码了。将转换的时间和PPS脉冲的时间打印出来比对一下。 ![](https://djisdksupport.zendesk.com/attachments/token/RHC413YG42MBcihg3mn4xTLNI/?name=image.png)
    0
    Comment actions Permalink
  • towel
    /**

     ********************************************************************

     * @file    test_time_sync.c

     * @brief

     *

     * @copyright (c) 2021 DJI. All rights reserved.

     *

     * All information contained herein is, and remains, the property of DJI.

     * The intellectual and technical concepts contained herein are proprietary

     * to DJI and may be covered by U.S. and foreign patents, patents in process,

     * and protected by trade secret or copyright law.  Dissemination of this

     * information, including but not limited to data and other proprietary

     * material(s) incorporated within the information, in any form, is strictly

     * prohibited without the express written consent of DJI.

     *

     * If you receive this source code without DJI’s authorization, you may not

     * further disseminate the information, and you must immediately remove the

     * source code and notify DJI of its removal. DJI reserves the right to pursue

     * legal actions against you for any loss(es) or damage(s) caused by your

     * failure to do so.

     *

     *********************************************************************

     */

    /* Includes ------------------------------------------------------------------*/

    #include <fc_subscription/test_fc_subscription.h>

    #include "test_time_sync.h"

    #include "dji_time_sync.h"

    #include "dji_logger.h"

    #include "utils/util_misc.h"

    #include "dji_platform.h"

    #include <unistd.h>

    #include <sys/types.h>

    #include <sys/time.h>

    #include <sys/stat.h>

    #include <fcntl.h>

    #include "czi_time_format.h"

    /* Private constants ---------------------------------------------------------*/

    #define DJI_TEST_TIME_SYNC_TASK_FREQ            (1)

    #define DJI_TEST_TIME_SYNC_TASK_STACK_SIZE      (2048)

    /* Private types -------------------------------------------------------------*/

    /* Private functions declaration ---------------------------------------------*/

    static void *DjiTest_TimeSyncTask(void *arg);

    static void *DjiTest_PpsTask(void *arg);

    static T_DjiReturnCode czi_TimeSyncInit();

    static T_DjiReturnCode czi_PpsSignalResponseInit(void);

    static T_DjiReturnCode czi_GetNewestPpsTriggerLocalTimeUs(uint64_t *localTimeUs);

    static uint64_t czi_GetTimeMs();

    /* Private variables ---------------------------------------------------------*/

    static T_DjiTestTimeSyncHandler s_timeSyncHandler;

    static T_DjiTaskHandle s_timeSyncThread;

    static T_DjiTaskHandle s_ppsIrqThread;

    static uint64_t s_ppsNewestTriggerLocalTimeMs = 0;

    static T_DjiMutexHandle s_ppsMutex = {0};

    static T_DjiTimeSyncAircraftTime m_aircraftTime = {0};

    static T_DjiMutexHandle s_aircraftTimeMutex = {0};

    static bool s_tiemSyncInitStatus = false;

    static uint32_t startTimeMs = 0;

    /* Exported functions definition ---------------------------------------------*/

    /**

     * @brief Register handler function for initialising PPS pin configure and reporting the latest local time when PPS is

     * triggered. This function have to be called before calling DjiTest_TimeSyncInit().

     * @param timeSyncHandler: pointer to handler function for time synchronization.

     * @return Execution result.

     */

    T_DjiReturnCode DjiTest_TimeSyncRegHandler(T_DjiTestTimeSyncHandler *timeSyncHandler)

    {

        if (timeSyncHandler->PpsSignalResponseInit == NULL) {

            USER_LOG_ERROR("reg time sync handler PpsSignalResponseInit error");

            return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;

        }

        if (timeSyncHandler->GetNewestPpsTriggerLocalTimeUs == NULL) {

            USER_LOG_ERROR("reg time sync handler GetNewestPpsTriggerLocalTimeUs error");

            return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;

        }

        memcpy(&s_timeSyncHandler, timeSyncHandler, sizeof(T_DjiTestTimeSyncHandler));

        return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;

    }

    T_DjiReturnCode DjiTest_TimeSyncStartService(void)

    {

        T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();

        if (osalHandler->TaskCreate("user_time_sync_task", DjiTest_TimeSyncTask,

                                    DJI_TEST_TIME_SYNC_TASK_STACK_SIZE, NULL, &s_timeSyncThread) !=

            DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("user time sync task create error.");

            return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;

        }

        return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;

    }

    T_DjiReturnCode DjiTest_TimeSyncGetNewestPpsTriggerLocalTimeUs(uint64_t *localTimeUs)

    {

        if (s_timeSyncHandler.GetNewestPpsTriggerLocalTimeUs == NULL) {

            USER_LOG_ERROR("GetNewestPpsTriggerLocalTimeUs null error.");

            return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;

        }

        return s_timeSyncHandler.GetNewestPpsTriggerLocalTimeUs(localTimeUs);

    }

    T_DjiReturnCode Czi_GetAircraftTime(T_DjiTimeSyncAircraftTime *aircraftTime)

    {    

        if(s_tiemSyncInitStatus == false)

            return -1;

        T_DjiReturnCode returnCode;

        T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();

        returnCode = osalHandler->MutexLock(s_aircraftTimeMutex);

        if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("unlock mutex error: 0x%08llX.", stat);

            return returnCode;

        }

        *aircraftTime = m_aircraftTime;

        returnCode = osalHandler->MutexUnlock(s_aircraftTimeMutex);

        if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);

            return returnCode;

        }

    }

    /* Private functions definition-----------------------------------------------*/

    #ifndef __CC_ARM

    #pragma GCC diagnostic push

    #pragma GCC diagnostic ignored "-Wmissing-noreturn"

    #pragma GCC diagnostic ignored "-Wreturn-type"

    #endif

    static void *DjiTest_TimeSyncTask(void *arg)

    {

        T_DjiReturnCode djiStat;

        uint64_t currentTimeMs = 0;

       

        T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();

       

        uint8_t totalSatelliteNumber = 0;

        USER_UTIL_UNUSED(arg);

        czi_TimeSyncInit();

        s_tiemSyncInitStatus = true;

        osalHandler->GetTimeMs(&startTimeMs);

        if (osalHandler->TaskCreate("user_pps_task", DjiTest_PpsTask,

                                    DJI_TEST_TIME_SYNC_TASK_STACK_SIZE, NULL, &s_ppsIrqThread) !=

            DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("user pps task create error.");

            return arg;

        }

        while (1) {

            osalHandler->TaskSleepMs(1000 / DJI_TEST_TIME_SYNC_TASK_FREQ);

            djiStat = DjiTest_FcSubscriptionGetTotalSatelliteNumber(&totalSatelliteNumber);

            if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

                USER_LOG_ERROR("get total satellite number error: 0x%08llX.", djiStat);

                continue;

            }

            // djiStat = osalHandler->GetTimeMs(&currentTimeMs);

            // if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            //     USER_LOG_ERROR("get current time error: 0x%08llX.", djiStat);

            //     continue;

            // }

            // currentTimeMs = czi_GetTimeMs() - 1000*60*60*24;

            // USER_LOG_INFO("currentTimeMs:%d ms", currentTimeMs);

            djiStat = osalHandler->MutexLock(s_aircraftTimeMutex);

            if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

                USER_LOG_ERROR("unlock mutex error: 0x%08llX.", stat);

                continue;

            }

            osalHandler->GetTimeMs((uint32_t *)(&currentTimeMs));

            djiStat = DjiTimeSync_TransferToAircraftTime(currentTimeMs * 1000, &m_aircraftTime);

            if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

                USER_LOG_ERROR("transfer to aircraft time error: 0x%08llX.", djiStat);

                continue;

            }

            USER_LOG_INFO("GetTimeMs current aircraft time is %04d.%02d.%02d %02d:%02d %02d.", m_aircraftTime.year, m_aircraftTime.month,

                    m_aircraftTime.day, m_aircraftTime.hour, m_aircraftTime.minute, m_aircraftTime.second);

           

            djiStat = osalHandler->MutexUnlock(s_aircraftTimeMutex);

            if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

                USER_LOG_ERROR("unlock mutex error: 0x%08llX.", stat);

                continue;

            }

        }

    }

    static void *DjiTest_PpsTask(void *arg)

    {

        T_DjiReturnCode stat;

        T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();

        int fd_pps = open("/sys/class/pps/pps0/assert", O_RDONLY);

        if(fd_pps < 0)

        {

            USER_LOG_ERROR("fd_pps open error");

            return arg;

        }

        char buf[32];

        int nums;

        int ret;

        int nums_old;

        uint32_t timeMs;

        USER_UTIL_UNUSED(arg);

        while (1) {

            osalHandler->TaskSleepMs(1);

            memset(buf, 0, 32);

            lseek(fd_pps, 0, SEEK_SET);

            ret = read(fd_pps, buf, 32);

            if(ret)

            {

                USER_LOG_INFO("pps time : %s", buf);

                if(sscanf(buf, "%*[^#]#%d", &nums) == 1)

                {

                    if(nums != nums_old)

                    {

                        nums_old = nums;

                        stat = osalHandler->GetTimeMs(&timeMs);

                        if(stat == DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS)

                        {

                            stat = osalHandler->MutexLock(s_ppsMutex);

                            if (stat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

                                USER_LOG_ERROR("lock mutex error: 0x%08llX.", stat);

                                continue;

                            }

                            s_ppsNewestTriggerLocalTimeMs = timeMs;

                            stat = osalHandler->MutexUnlock(s_ppsMutex);

                            if (stat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

                                USER_LOG_ERROR("unlock mutex error: 0x%08llX.", stat);

                                continue;

                            }  

                        }

                    }

                }

            }

        }

    }

    static T_DjiReturnCode czi_TimeSyncInit()

    {

        T_DjiReturnCode djiStat;

        T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();

        T_DjiDataTimestamp timestamp = {0};

        T_DjiFcSubscriptionGpsDate gpsDate = 0;

        T_DjiFcSubscriptionGpsTime gpsTime = 0;

        char DateTimeStr[32];

        osalHandler->TaskSleepMs(5000);

        djiStat = DjiFcSubscription_GetLatestValueOfTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_DATE,

                                                        (uint8_t *) &gpsDate,

                                                        sizeof(T_DjiFcSubscriptionGpsDate),

                                                        &timestamp);

        if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("get value of topic GPS_DATE error.");

        }

        djiStat = DjiFcSubscription_GetLatestValueOfTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_TIME,

                                                        (uint8_t *) &gpsTime,

                                                        sizeof(T_DjiFcSubscriptionGpsTime),

                                                        &timestamp);

        if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("get value of topic GPS_TIME error.");

        }

        czi_gpstime_UtcToBeijing(&gpsDate, &gpsTime);

        snprintf(DateTimeStr, 64, "sudo date -s '%04d%02d%02d %02d:%02d:%02d'", gpsDate/10000, gpsDate/100%100, gpsDate%100,

            gpsTime/10000, gpsTime/100%100, gpsTime%100);

            USER_LOG_INFO("%s", DateTimeStr);

        system(DateTimeStr);

        djiStat = DjiTimeSync_Init();

        if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("time synchronization module init error.");

            return djiStat;

        }

        s_timeSyncHandler.PpsSignalResponseInit = czi_PpsSignalResponseInit;

        s_timeSyncHandler.GetNewestPpsTriggerLocalTimeUs = czi_GetNewestPpsTriggerLocalTimeUs;

        if (s_timeSyncHandler.PpsSignalResponseInit == NULL) {

            USER_LOG_ERROR("time sync handler PpsSignalResponseInit interface is NULL error");

            return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;

        }

        if (s_timeSyncHandler.GetNewestPpsTriggerLocalTimeUs == NULL) {

            USER_LOG_ERROR("time sync handler GetNewestPpsTriggerLocalTimeUs interface is NULL error");

            return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;

        }

        djiStat = osalHandler->MutexCreate(&s_ppsMutex);

        if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("create mutex used to lock pps arguments error: 0x%08llX", djiStat);

            return djiStat;

        }

        djiStat = osalHandler->MutexCreate(&s_aircraftTimeMutex);

        if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("create mutex used to lock aircraftTimeMutex arguments error: 0x%08llX", djiStat);

            return djiStat;

        }

        // users must register getNewestPpsTriggerTime callback function

        djiStat = DjiTimeSync_RegGetNewestPpsTriggerTimeCallback(s_timeSyncHandler.GetNewestPpsTriggerLocalTimeUs);

        if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("register GetNewestPpsTriggerLocalTimeUsCallback error.");

            return djiStat;

        }

        djiStat = s_timeSyncHandler.PpsSignalResponseInit();

        if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("pps signal response init error");

            return djiStat;

        }

    }

    static T_DjiReturnCode czi_PpsSignalResponseInit(void)

    {

        return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;

    }

    static T_DjiReturnCode czi_GetNewestPpsTriggerLocalTimeUs(uint64_t *localTimeUs)

    {

        T_DjiReturnCode returnCode;

        T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();

       

        if (localTimeUs == NULL) {

            USER_LOG_ERROR("input pointer is null.");

            return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;

        }

       

        returnCode = osalHandler->MutexLock(s_ppsMutex);

        if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);

            return returnCode;

        }

        if (s_ppsNewestTriggerLocalTimeMs == 0) {

            USER_LOG_WARN("pps have not been triggered.");

            return DJI_ERROR_SYSTEM_MODULE_CODE_BUSY;

        }

        *localTimeUs = (uint64_t) (s_ppsNewestTriggerLocalTimeMs * 1000);

        returnCode = osalHandler->MutexUnlock(s_ppsMutex);

        if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {

            USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);

            return returnCode;

        }

        return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;

    }

    static uint64_t czi_GetTimeMs()

    {

        struct timeval tv;

        long long t = 0;

        gettimeofday(&tv, NULL);

        t = (tv.tv_sec*1000 + tv.tv_usec/1000);

        return t;

    }

    #ifndef __CC_ARM

    #pragma GCC diagnostic pop

    #endif

    /****************** (C) COPYRIGHT DJI Innovations *****END OF FILE****/
    0
    Comment actions Permalink
  • towel

     试了下最新的psdk还是一样的效果,附上相关代码和日志。

    0
    Comment actions Permalink
  • DJI Developer Support
    可以在下面两个地方加一下debug log,确认一下PPS时间以及转换飞机时间的currenttime ![](https://djisdksupport.zendesk.com/attachments/token/k8M8MJ3DQ3z6MYlKSPauLHsrp/?name=image.png) 和 ![](https://djisdksupport.zendesk.com/attachments/token/42UJfIOtKS4oHMxYS7DRhtaHC/?name=image.png)
    0
    Comment actions Permalink
  • towel

      看时间是符合时间同步的500ms内的,

    0
    Comment actions Permalink
  • DJI Developer Support
    是否有连接RTK,若有连接先断开RTK试试?若未连接RTK,麻烦提供一下PSDK运行的平台是哪一个?或者使用PSDK lib的文件夹是哪一个(交叉编译链名)。
    0
    Comment actions Permalink
  • DJI Developer Support
    没有连接RTK, 使用的是jetson, aarch64
    0
    Comment actions Permalink
  • DJI Developer Support
    我这边编个aarc64的测试程序您运行一下获取飞机的时间试试。可能要提供一下您的APPINFO,麻烦您通过个人邮箱发个邮件到dev@dji.com,。
    0
    Comment actions Permalink
  • towel

    已通過郵箱發送

    0
    Comment actions Permalink
  • towel
    cz@ubuntu:~$ sudo ./dji_sdk_demo_linux
    [0.001][core]-[Info]-[DjiCore_Init:92) Payload SDK Version : V3.1.0-beta.0-build.999
    [0.284][adapter]-[Info]-[DjiAccessAdapter_Init:154) Identify aircraft series is Matrice 300 Series
    [0.284][adapter]-[Info]-[DjiAccessAdapter_Init:171) Identify mount position type is Payload Port Type
    [0.298][adapter]-[Info]-[DjiPayloadNegotiate_Start:199) Waiting payload negotiate finished.
    l4tbr0: ERROR while getting interface flags: No such device
    [1.316][user]-[Error]-[HalNetWork_Init:59) Can't open the network.Probably the program not execute with root permission.Please use the root permission to execute the program.
    [1.316][adapter]-[Error]-[DjiPayloadNegotiate_Start:238) Payload negetiate network config error:0x000000EC
    [1.316][adapter]-[Error]-[DjiAccessAdapter_Init:273) Payload negotiate error, returnCode = 236
    [1.316][adapter]-[Error]-[DjiAccessAdapter_Init:279) Payload negotiate error, returnCode = 236
    [1.316][core]-[Error]-[DjiCore_Init:103) Access adapter init error, stat:236
    [1.316][user]-[Error]-[main:201) Core init error
    0
    Comment actions Permalink
  • towel

    你的網絡設備是eth0嗎

    0
    Comment actions Permalink

Please sign in to leave a comment.