如何使用SDK进行UTC时间同步 #123
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
如何utc同步来进行采样保存lvx文件呢?目前参考lidar_utc_sync与lidar_lvx_sample结合,控制逻辑是连接Lidar并配置同步,使用LidarStartSampling来进行采样,但收到的数据包时间戳并不是UTC时间。该如何在采样程序中嵌入同步UTC?能提供一下代码吗?
请问你解决了吗?我也遇到同样问题,打印点云的时间戳与UTC时间戳不一致
兄弟,我看你把这个问题关闭了,你是解决了吗?能分享一下吗?问题一直卡在这里
不知道你用的是那种同步方式,我用的是GPS同步,你的是最新版的Livox-SDK吗?
来自 Outlookhttp://aka.ms/weboutlook
发件人: Gitwlmai @.>
发送时间: 2021年6月10日 10:55
收件人: Livox-SDK/Livox-SDK @.>
抄送: feiwei93 @.>; State change @.>
主题: Re: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
兄弟,我看你把这个问题关闭了,你是解决了吗?能分享一下吗?问题一直卡在这里
―
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHubhttps://github.com/Livox-SDK/Livox-SDK/issues/123#issuecomment-858240176, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ARFAWKUY5AY25REHKZPVK5LTSASQRANCNFSM43LQXVZA.
我用的是GPS+PPS的同步方式,GPS发送UTC到我们的主机然后通过SDK发给雷达,PPS脉冲1HZ接雷达的同步接口,然后时间戳就如下所示
Rmc: $GNRMC,115611.00,A,2309.6336714,N,11322.8560422,E,0.013,319.4,090621,0.0,E,D*2A 第一步接收RMC时间
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356419517
time: 21/6/9 11:3371000000 打印RMC时间21/6/9 11:3371000000
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356419917 点云输出时间 21-6-9 11:3356419917 (两者相差了将近15s)
[2021-06-09 19:56:11.070] [console] [info] Send Command: Set 1 Id 10 Seq 208 [command_channel.cpp] [Send] [247]
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356420316
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356420715
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356421114
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356421515
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356421913
lidar: data_type:6 ts_type:3 timeStamp: 21-6-9 11:3356421623
[2021-06-09 19:56:11.072] [console] [info] Recieve Ack: Set 1 Id 10 Seq 208 [command_handler.cpp] [OnCommand] [118]
OnLidarSetRmcSyncTimeCallback statue 0 handle 0 response 0.
没有同步到点云上,有偏差,我用的是2.3.0的SDK,应该是最新的
我的是先确认收到GPS信号,用GPS信号同步TX2本机时钟localtime,之后再运行lidar_utc_sync与lidar_lvx_sample的整合代码。
来自 Outlookhttp://aka.ms/weboutlook
发件人: Fei Wei @.>
发送时间: 2021年6月11日 9:12
收件人: Livox-SDK/Livox-SDK @.>
主题: 回复: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
不知道你用的是那种同步方式,我用的是GPS同步,你的是最新版的Livox-SDK吗?
来自 Outlookhttp://aka.ms/weboutlook
发件人: Gitwlmai @.>
发送时间: 2021年6月10日 10:55
收件人: Livox-SDK/Livox-SDK @.>
抄送: feiwei93 @.>; State change @.>
主题: Re: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
兄弟,我看你把这个问题关闭了,你是解决了吗?能分享一下吗?问题一直卡在这里
―
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHubhttps://github.com/Livox-SDK/Livox-SDK/issues/123#issuecomment-858240176, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ARFAWKUY5AY25REHKZPVK5LTSASQRANCNFSM43LQXVZA.
不是直接解析GPS端发过来的时间直接通过SDK给到雷达吗?
你打印的rmc时间不是GNRMC的时间。你确定用GNRMC同步主机时间了吗?两者相差的时间可能是你代码运行的时间发自我的iPhone------------------ 原始邮件 ------------------发件人: Gitwlmai @.>发送时间: 2021年6月11日 09:31收件人: Livox-SDK/Livox-SDK @.>抄送: feiwei93 @.>, State change @.>主题: 回复:[Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
我用的是GPS+PPS的同步方式,GPS发送UTC到我们的主机然后通过SDK发给雷达,PPS脉冲1HZ接雷达的同步接口,然后时间戳就如下所示
Rmc: $GNRMC,115611.00,A,2309.6336714,N,11322.8560422,E,0.013,319.4,090621,0.0,E,D*2A 第一步接收RMC时间
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356419517
time: 21/6/9 11:3371000000 打印RMC时间21/6/9 11:3371000000
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356419917 点云输出时间 21-6-9 11:3356419917 (两者相差了将近15s)
[2021-06-09 19:56:11.070] [console] [info] Send Command: Set 1 Id 10 Seq 208 [command_channel.cpp] [Send] [247]
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356420316
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356420715
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356421114
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356421515
lidar: data_type:2 ts_type:3 timeStamp: 21-6-9 11:3356421913
lidar: data_type:6 ts_type:3 timeStamp: 21-6-9 11:3356421623
[2021-06-09 19:56:11.072] [console] [info] Recieve Ack: Set 1 Id 10 Seq 208 [command_handler.cpp] [OnCommand] [118]
OnLidarSetRmcSyncTimeCallback statue 0 handle 0 response 0.
没有同步到点云上,有偏差,我用的是2.3.0的SDK,应该是最新的
—You are receiving this because you modified the open/close state.Reply to this email directly, view it on GitHub, or unsubscribe.
[
{
@.": "http://schema.org",
@.": "EmailMessage",
"potentialAction": {
@.": "ViewAction",
"target": "https://github.com/Livox-SDK/Livox-SDK/issues/123#issuecomment-859195069",
"url": "https://github.com/Livox-SDK/Livox-SDK/issues/123#issuecomment-859195069",
"name": "View Issue"
},
"description": "View this Issue on GitHub",
"publisher": {
@.": "Organization",
"name": "GitHub",
"url": "https://github.com"
}
}
]
不是的,要先同步一下主机时间,你这个点云的时间不是GPS的时间,是主机的localtime,你看一下sample里面的lvx_file代码,确认一下是否用到过这个函数发自我的iPhone------------------ 原始邮件 ------------------发件人: Gitwlmai @.>发送时间: 2021年6月11日 09:44收件人: Livox-SDK/Livox-SDK @.>抄送: feiwei93 @.>, State change @.>主题: 回复:[Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
不是直接解析GPS端发过来的时间直接通过SDK给到雷达吗?
—You are receiving this because you modified the open/close state.Reply to this email directly, view it on GitHub, or unsubscribe.
[
{
@.": "http://schema.org",
@.": "EmailMessage",
"potentialAction": {
@.": "ViewAction",
"target": "https://github.com/Livox-SDK/Livox-SDK/issues/123#issuecomment-859199255",
"url": "https://github.com/Livox-SDK/Livox-SDK/issues/123#issuecomment-859199255",
"name": "View Issue"
},
"description": "View this Issue on GitHub",
"publisher": {
@.": "Organization",
"name": "GitHub",
"url": "https://github.com"
}
}
]
我看了一下那个lidar_utc_sample,它是直接读取/dev/ttyUSB0发过来的GPRMC数据,然后解析出里面的UTC时间,直接通过SDK发给雷达,所以我是参照它这个sample做的,您说同步主机时间,官方提供的demo里面没看到这一步骤呢?
那个lidar_utc_sample代码本身就不是完整的代码。你只运行了lidar_utc_sample这一个代码吗?这样吧,你先把主机的时间随便改成一个错误的时间,然后在运行你之前的代码,打印出来看看。
来自 Outlookhttp://aka.ms/weboutlook
发件人: Gitwlmai @.>
发送时间: 2021年6月11日 9:57
收件人: Livox-SDK/Livox-SDK @.>
抄送: feiwei93 @.>; State change @.>
主题: Re: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
我看了一下那个lidar_utc_sample,它是直接读取/dev/ttyUSB0发过来的GPRMC数据,然后解析出里面的UTC时间,直接通过SDK发给雷达,所以我是参照它这个sample做的,您说同步主机时间,官方提供的demo里面没看到这一步骤呢?
―
You are receiving this because you modified the open/close state.
Reply to this email directly, view it on GitHubhttps://github.com/Livox-SDK/Livox-SDK/issues/123#issuecomment-859204312, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ARFAWKX3OHXXQFTB3EDGMXLTSFUQHANCNFSM43LQXVZA.
我大概理解您的意思,就是点云输出的时间戳应该是主机的localtime,我只需要根据GPS的时间修正主机的localtime就行了。但是我有个疑问,SDK为啥提供发送UTC时间的接口给lidar,然后官网的文档这样描述的:Livox 设备接收到 PPS 信号上升沿,并由 GPRMC 数据解析出正确的时间信息后,会设置点云时间为 GPS 时间,并保持此时间基准持续累加,来实现和 GPS 设备的时间同步 看它的意思是会设置点云时间为GPS时间。
您好,我按照您的方法,将主机的时间修改之后,实际上点云的时间戳还是按照GPS时间进行输出的,只不过这个时间戳没有对齐,相差几秒。不知您那边是这么做的
您好,我最近也碰到了这个问题,我想先通过lidar_utc_sync进行雷达和UTC时间同步,然后使用lidar_lvx_sample保存lvx文件,但我发现两个不能同时运行,端口冲突,请问下您是通过什么方法解决的这个问题,把lidar_utc_sync和lidar_lvx_sample整合成一个代码运行吗? 可以提供下参考吗 感谢!
非常感谢您!我好好学习一下,再次感谢!!
---原始邮件---
发件人: @.>
发送时间: 2021年6月18日(周五) 下午5:17
收件人: @.>;
抄送: @.@.>;
主题: Re: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
我的是先确认收到GPS信号,用GPS信号同步TX2本机时钟localtime,之后再运行lidar_utc_sync与lidar_lvx_sample的整合代码。 来自 Outlookhttp://aka.ms/weboutlook
…
________________________________ 发件人: Fei Wei @.> 发送时间: 2021年6月11日 9:12 收件人: Livox-SDK/Livox-SDK @**.> 主题: 回复: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123) 不知道你用的是那种同步方式,我用的是GPS同步,你的是最新版的Livox-SDK吗? 来自 Outlookhttp://aka.ms/weboutlook
________________________________ 发件人: Gitwlmai @.> 发送时间: 2021年6月10日 10:55 收件人: Livox-SDK/Livox-SDK @._> 抄送: feiwei93 @.>; State change @.**_> 主题: Re: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123) 兄弟,我看你把这个问题关闭了,你是解决了吗?能分享一下吗?问题一直卡在这里 ― You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub<#123 (comment)>, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ARFAWKUY5AY25REHKZPVK5LTSASQRANCNFSM43LQXVZA.
您好,我最近也碰到了这个问题,我想先通过lidar_utc_sync进行雷达和UTC时间同步,然后使用lidar_lvx_sample保存lvx文件,但我发现两个不能同时运行,端口冲突,请问下您是通过什么方法解决的这个问题,把lidar_utc_sync和lidar_lvx_sample整合成一个代码运行吗? 可以提供下参考吗 感谢!
你好,这是我整合后的完整代码,已经测试过可以运行希望对你有所帮助。大家相互学习,欢迎交流!
#include
#include <string.h>
#include "lvx_file.h"
#include "cmdline.h"
#include <stdio.h>
#include <stdlib.h>
#include
#include
#include "lds_lidar.h"
#include "synchro.h"
DeviceItem devices[kMaxLidarCount];
LvxFileHandle lvx_file_handler;
std::list point_packet_list;
std::vectorstd::string broadcast_code_rev;
std::condition_variable lidar_arrive_condition;
std::condition_variable extrinsic_condition;
std::condition_variable point_pack_condition;
std::mutex mtx;
int lvx_file_save_time =10; //设置运行时间(s)
bool is_finish_extrinsic_parameter = false;
bool is_read_extrinsic_from_xml = false;
uint8_t connected_lidar_count = 0;
#define FRAME_RATE 20
using namespace std::chrono;
/** Cmdline input broadcast code */
static std::vectorstd::string cmdline_broadcast_code;
/** Connect all the broadcast device in default and connect specific device when use program options or broadcast_code_list is not empty. */
std::vectorstd::string broadcast_code_list = {
"3GGDJ3300100351"
};
/** Receiving error message from Livox Lidar. */
void OnLidarErrorStatusCallback(livox_status status, uint8_t handle, ErrorMessage *message) {
static uint32_t error_message_count = 0;
if (message != NULL) {
++error_message_count;
if (0 == (error_message_count % 100)) {
printf("handle: %u\n", handle);
printf("temp_status : %u\n", message->lidar_error_code.temp_status);
printf("volt_status : %u\n", message->lidar_error_code.volt_status);
printf("motor_status : %u\n", message->lidar_error_code.motor_status);
printf("dirty_warn : %u\n", message->lidar_error_code.dirty_warn);
printf("firmware_err : %u\n", message->lidar_error_code.firmware_err);
printf("pps_status : %u\n", message->lidar_error_code.device_status);
printf("fan_status : %u\n", message->lidar_error_code.fan_status);
printf("self_heating : %u\n", message->lidar_error_code.self_heating);
printf("ptp_status : %u\n", message->lidar_error_code.ptp_status);
printf("time_sync_status : %u\n", message->lidar_error_code.time_sync_status);
printf("system_status : %u\n", message->lidar_error_code.system_status);
}
}
}
/** Receiving point cloud data from Livox LiDAR. */
void GetLidarData(uint8_t handle, LivoxEthPacket *data, uint32_t data_num, void *client_data) {
if (data) {
if (handle < connected_lidar_count && is_finish_extrinsic_parameter) {
std::unique_lockstd::mutex lock(mtx);
LvxBasePackDetail packet;
packet.device_index = handle;
lvx_file_handler.BasePointsHandle(data, packet);
point_packet_list.push_back(packet);
}
}
}
/** Callback function of starting sampling. */
void OnSampleCallback(livox_status status, uint8_t handle, uint8_t response, void *data) {
printf("OnSampleCallback statues %d handle %d response %d \n", status, handle, response);
if (status == kStatusSuccess) {
if (response != 0) {
devices[handle].device_state = kDeviceStateConnect;
}
} else if (status == kStatusTimeout) {
devices[handle].device_state = kDeviceStateConnect;
}
}
/** Callback function of stopping sampling. */
void OnStopSampleCallback(livox_status status, uint8_t handle, uint8_t response, void *data) {
}
/** Callback function of get LiDARs' extrinsic parameter. */
void OnGetLidarExtrinsicParameter(livox_status status, uint8_t handle, LidarGetExtrinsicParameterResponse *response, void *data) {
if (status == kStatusSuccess) {
if (response != 0) {
printf("OnGetLidarExtrinsicParameter statue %d handle %d response %d \n", status, handle, response->ret_code);
std::unique_lockstd::mutex lock(mtx);
LvxDeviceInfo lidar_info;
strncpy((char *)lidar_info.lidar_broadcast_code, devices[handle].info.broadcast_code, kBroadcastCodeSize);
memset(lidar_info.hub_broadcast_code, 0, kBroadcastCodeSize);
lidar_info.device_index = handle;
lidar_info.device_type = devices[handle].info.type;
lidar_info.extrinsic_enable = true;
lidar_info.pitch = response->pitch;
lidar_info.roll = response->roll;
lidar_info.yaw = response->yaw;
lidar_info.x = static_cast(response->x / 1000.0);
lidar_info.y = static_cast(response->y / 1000.0);
lidar_info.z = static_cast(response->z / 1000.0);
lvx_file_handler.AddDeviceInfo(lidar_info);
if (lvx_file_handler.GetDeviceInfoListSize() == connected_lidar_count) {
is_finish_extrinsic_parameter = true;
extrinsic_condition.notify_one();
}
}
}
else if (status == kStatusTimeout) {
printf("GetLidarExtrinsicParameter timeout! \n");
}
}
/** Get LiDARs' extrinsic parameter from file named "extrinsic.xml". */
void LidarGetExtrinsicFromXml(uint8_t handle) {
LvxDeviceInfo lidar_info;
ParseExtrinsicXml(devices[handle], lidar_info);
lvx_file_handler.AddDeviceInfo(lidar_info);
lidar_info.extrinsic_enable = true;
if (lvx_file_handler.GetDeviceInfoListSize() == broadcast_code_list.size()) {
is_finish_extrinsic_parameter = true;
extrinsic_condition.notify_one();
}
}
/** Query the firmware version of Livox LiDAR. */
void OnDeviceInformation(livox_status status, uint8_t handle, DeviceInformationResponse *ack, void *data) {
if (status != kStatusSuccess) {
printf("Device Query Informations Failed %d\n", status);
}
if (ack) {
printf("firm ver: %d.%d.%d.%d\n",
ack->firmware_version[0],
ack->firmware_version[1],
ack->firmware_version[2],
ack->firmware_version[3]);
}
}
void LidarConnect(const DeviceInfo *info) {
uint8_t handle = info->handle;
QueryDeviceInformation(handle, OnDeviceInformation, NULL);
if (devices[handle].device_state == kDeviceStateDisconnect) {
devices[handle].device_state = kDeviceStateConnect;
devices[handle].info = *info;
}
}
void LidarDisConnect(const DeviceInfo *info) {
uint8_t handle = info->handle;
devices[handle].device_state = kDeviceStateDisconnect;
}
void LidarStateChange(const DeviceInfo *info) {
uint8_t handle = info->handle;
devices[handle].info = *info;
}
/** Callback function of changing of device state. */
void OnDeviceInfoChange(const DeviceInfo *info, DeviceEvent type) {
if (info == nullptr) {
return;
}
printf("OnDeviceChange broadcast code %s update type %d\n", info->broadcast_code, type);
uint8_t handle = info->handle;
if (handle >= kMaxLidarCount) {
return;
}
if (type == kEventConnect) {
LidarConnect(info);
printf("[WARNING] Lidar sn: [%s] Connect!!!\n", info->broadcast_code);
} else if (type == kEventDisconnect) {
LidarDisConnect(info);
printf("[WARNING] Lidar sn: [%s] Disconnect!!!\n", info->broadcast_code);
} else if (type == kEventStateChange) {
LidarStateChange(info);
printf("[WARNING] Lidar sn: [%s] StateChange!!!\n", info->broadcast_code);
}
if (devices[handle].device_state == kDeviceStateConnect) {
printf("Device Working State %d\n", devices[handle].info.state);
if (devices[handle].info.state == kLidarStateInit) {
printf("Device State Change Progress %u\n", devices[handle].info.status.progress);
} else {
printf("Device State Error Code 0X%08x\n", devices[handle].info.status.status_code.error_code);
}
printf("Device feature %d\n", devices[handle].info.feature);
SetErrorMessageCallback(handle, OnLidarErrorStatusCallback);
if (devices[handle].info.state == kLidarStateNormal) {
if (!is_read_extrinsic_from_xml) {
LidarGetExtrinsicParameter(handle, OnGetLidarExtrinsicParameter, nullptr);
} else {
LidarGetExtrinsicFromXml(handle);
}
LidarStartSampling(handle, OnSampleCallback, nullptr);
devices[handle].device_state = kDeviceStateSampling;
}
}
}
/** Callback function when broadcast message received.
You need to add listening device broadcast code and set the point cloud data callback in this function.
*/
void OnDeviceBroadcast(const BroadcastDeviceInfo *info) {
if (info == nullptr || info->dev_type == kDeviceTypeHub) {
return;
}
printf("Receive Broadcast Code %s\n", info->broadcast_code);
if ((broadcast_code_rev.size() == 0) ||
(std::find(broadcast_code_rev.begin(), broadcast_code_rev.end(), info->broadcast_code) == broadcast_code_rev.end())) {
broadcast_code_rev.push_back(info->broadcast_code);
lidar_arrive_condition.notify_one();
}
}
/** Wait until no new device arriving in 2 second. */
void WaitForDevicesReady( ) {
bool device_ready = false;
seconds wait_time = seconds(2);
steady_clock::time_point last_time = steady_clock::now();
while (!device_ready) {
std::unique_lockstd::mutex lock(mtx);
lidar_arrive_condition.wait_for(lock,wait_time);
if ((steady_clock::now() - last_time + milliseconds(50)) >= wait_time) {
device_ready = true;
} else {
last_time = steady_clock::now();
}
}
}
void WaitForExtrinsicParameter() {
std::unique_lockstd::mutex lock(mtx);
extrinsic_condition.wait(lock);
}
void AddDevicesToConnect() {
if (broadcast_code_rev.size() == 0)
return;
for (int i = 0; i < broadcast_code_rev.size(); ++i) {
if ((broadcast_code_list.size() != 0) &&
(std::find(broadcast_code_list.begin(), broadcast_code_list.end(), broadcast_code_rev[i]) == broadcast_code_list.end())) {
continue;
}
uint8_t handle = 0;
livox_status result = AddLidarToConnect(broadcast_code_rev[i].c_str(), &handle);
if (result == kStatusSuccess) {
/** Set the point cloud data for a specific Livox LiDAR. */
SetDataCallback(handle, GetLidarData, nullptr);
devices[handle].handle = handle;
devices[handle].device_state = kDeviceStateDisconnect;
connected_lidar_count++;
}
}
}
/** Set the program options.
You can input the registered device broadcast code and decide whether to save the log file.
*/
void SetProgramOption(int argc, const char *argv[]) {
cmdline::parser cmd;
cmd.addstd::string("code", 'c', "Register device broadcast code", false);
cmd.add("log", 'l', "Save the log file");
cmd.add("time", 't', "Time to save point cloud to the lvx file", false);
cmd.add("param", 'p', "Get the extrinsic parameter from extrinsic.xml file");
cmd.add("help", 'h', "Show help");
cmd.parse_check(argc, const_cast<char **>(argv));
if (cmd.exist("code")) {
std::string sn_list = cmd.getstd::string("code");
printf("Register broadcast code: %s\n", sn_list.c_str());
size_t pos = 0;
broadcast_code_list.clear();
while ((pos = sn_list.find("&")) != std::string::npos) {
broadcast_code_list.push_back(sn_list.substr(0, pos));
sn_list.erase(0, pos + 1);
}
broadcast_code_list.push_back(sn_list);
}
if (cmd.exist("log")) {
printf("Save the log file.\n");
SaveLoggerFile();
}
if (cmd.exist("time")) {
printf("Time to save point cloud to the lvx file:%d.\n", cmd.get("time"));
lvx_file_save_time = cmd.get("time");
}
if (cmd.exist("param")) {
printf("Get the extrinsic parameter from extrinsic.xml file.\n");
is_read_extrinsic_from_xml = true;
}
return;
}
int main(int argc, const char argv[]) {
/* Set the program options. */
SetProgramOption(argc, argv);
LdsLidar& read_lidar = LdsLidar::GetInstance();
int ret = read_lidar.InitLdsLidar(cmdline_broadcast_code);
if (!ret) {
printf("Init lds lidar success!\n");
} else {
printf("Init lds lidar fail!\n");
return 0;
}
printf("Start discovering device.\n");
Synchro& synchro = Synchro::GetInstance();
#ifdef WIN32
synchro.SetPortName("COM1");
#else
synchro.SetPortName("/dev/ttyUSB0");
#endif
/** Set Synchro's Baudrate: 115200. /
synchro.SetBaudRate(BR115200);
/* Set Synchro's Parity: No parity (8N1). /
synchro.SetParity(P_8N1);
/* SyncTimer Callback will trigger when Synchro's GPRMC/GNRMC signal is ready. */
synchro.SetSyncTimerCallback(read_lidar.SetRmcSyncTime);
if (synchro.Start()) {
printf("Synchro start success\n");
} else {
printf("Synchro start failed\n");
return 0;
}
std::this_thread::sleep_for(std::chrono::seconds(2));
//synchro.Stop();
read_lidar.DeInitLdsLidar();
//printf("Livox lidar demo end!\n");
std::this_thread::sleep_for(std::chrono::seconds(2));
/*********************************************************/
printf("Livox SDK initializing.\n");
//Initialize Livox-SDK.
if (!Init()) {
return -1;
}
printf("Livox SDK has been initialized.\n");
LivoxSdkVersion _sdkversion;
GetLivoxSdkVersion(&_sdkversion);
printf("Livox SDK version %d.%d.%d .\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
memset(devices, 0, sizeof(devices));
/** Set the callback function receiving broadcast message from Livox LiDAR. */
SetBroadcastCallback(OnDeviceBroadcast);
/** Set the callback function called when device state change,
which means connection/disconnection and changing of LiDAR state.
*/
SetDeviceStateUpdateCallback(OnDeviceInfoChange);
/** Start the device discovering routine. */
if (!Start()) {
Uninit();
return -1;
}
printf("Start discovering device.\n");
WaitForDevicesReady();
AddDevicesToConnect();
if (connected_lidar_count == 0) {
printf("No device will be connected.\n");
Uninit();
return -1;
}
WaitForExtrinsicParameter();
/等待GPS同步后, 才记录点云数据生成.lvx文件*******/
printf("Start initialize lvx file.\n");
if (!lvx_file_handler.InitLvxFile()) {
Uninit();
return -1;
}
std::this_thread::sleep_for(std::chrono::seconds(5));
lvx_file_handler.InitLvxFileHeader();
int i = 0;
steady_clock::time_point last_time = steady_clock::now();
for (i = 0; i < lvx_file_save_time * FRAME_RATE; ++i) {
std::list point_packet_list_temp;
{
std::unique_lockstd::mutex lock(mtx);
point_pack_condition.wait_for(lock, milliseconds(kDefaultFrameDurationTime) - (steady_clock::now() - last_time));
last_time = steady_clock::now();
point_packet_list_temp.swap(point_packet_list);
}
if(point_packet_list_temp.empty()) {
printf("Point cloud packet is empty.\n");
break;
}
printf("Finish save %d frame to lvx file.\n", i);
lvx_file_handler.SaveFrameToLvxFile(point_packet_list_temp);
}
lvx_file_handler.CloseLvxFile();
for (i = 0; i < kMaxLidarCount; ++i) {
if (devices[i].device_state == kDeviceStateSampling) {
/** Stop the sampling of Livox LiDAR. */
LidarStopSampling(devices[i].handle, OnStopSampleCallback, nullptr);
}
}
/** Uninitialize Livox-SDK. */
Uninit();
}
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
非常抱歉又打扰您,我最近两天尝试编译了您发给我的代码,但我发现里面有很多错误,您发给我的应该是替换后的main.cpp,我已经把ample_cc\lidar_utc_sync下的lds_lidar和synchro代码复制到了sample\lidar_lvx_file文件夹下,运行还是会出错,请教下是我的过程有误吗,如果方便能在邮件附件里附上所有的文件吗? 十分抱歉浪费您的时间了!
------------------ 原始邮件 ------------------
发件人: "Livox-SDK/Livox-SDK" @.>;
发送时间: 2021年6月18日(星期五) 下午5:17
@.>;
@.@.>;
主题: Re: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123)
我的是先确认收到GPS信号,用GPS信号同步TX2本机时钟localtime,之后再运行lidar_utc_sync与lidar_lvx_sample的整合代码。 来自 Outlookhttp://aka.ms/weboutlook
…
________________________________ 发件人: Fei Wei @.> 发送时间: 2021年6月11日 9:12 收件人: Livox-SDK/Livox-SDK @**.> 主题: 回复: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123) 不知道你用的是那种同步方式,我用的是GPS同步,你的是最新版的Livox-SDK吗? 来自 Outlookhttp://aka.ms/weboutlook
________________________________ 发件人: Gitwlmai @.> 发送时间: 2021年6月10日 10:55 收件人: Livox-SDK/Livox-SDK @._> 抄送: feiwei93 @.>; State change @.**_> 主题: Re: [Livox-SDK/Livox-SDK] 如何使用SDK进行UTC时间同步 (#123) 兄弟,我看你把这个问题关闭了,你是解决了吗?能分享一下吗?问题一直卡在这里 ― You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub<#123 (comment)>, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ARFAWKUY5AY25REHKZPVK5LTSASQRANCNFSM43LQXVZA.
您好,我最近也碰到了这个问题,我想先通过lidar_utc_sync进行雷达和UTC时间同步,然后使用lidar_lvx_sample保存lvx文件,但我发现两个不能同时运行,端口冲突,请问下您是通过什么方法解决的这个问题,把lidar_utc_sync和lidar_lvx_sample整合成一个代码运行吗? 可以提供下参考吗 感谢!
你好,这是我整合后的完整代码,已经测试过可以运行希望对你有所帮助。大家相互学习,欢迎交流!
#include
#include <string.h>
#include "lvx_file.h"
#include "cmdline.h"
#include <stdio.h>
#include <stdlib.h>
#include
#include
#include "lds_lidar.h"
#include "synchro.h"
DeviceItem devices[kMaxLidarCount];
LvxFileHandle lvx_file_handler;
std::list point_packet_list;
std::vectorstd::string broadcast_code_rev;
std::condition_variable lidar_arrive_condition;
std::condition_variable extrinsic_condition;
std::condition_variable point_pack_condition;
std::mutex mtx;
int lvx_file_save_time =10; //设置运行时间(s)
bool is_finish_extrinsic_parameter = false;
bool is_read_extrinsic_from_xml = false;
uint8_t connected_lidar_count = 0;
#define FRAME_RATE 20
using namespace std::chrono;
/** Cmdline input broadcast code */
static std::vectorstd::string cmdline_broadcast_code;
/** Connect all the broadcast device in default and connect specific device when use program options or broadcast_code_list is not empty. */
std::vectorstd::string broadcast_code_list = {
"3GGDJ3300100351"
};
/** Receiving error message from Livox Lidar. */
void OnLidarErrorStatusCallback(livox_status status, uint8_t handle, ErrorMessage *message) {
static uint32_t error_message_count = 0;
if (message != NULL) {
++error_message_count;
if (0 == (error_message_count % 100)) {
printf("handle: %u\n", handle);
printf("temp_status : %u\n", message->lidar_error_code.temp_status);
printf("volt_status : %u\n", message->lidar_error_code.volt_status);
printf("motor_status : %u\n", message->lidar_error_code.motor_status);
printf("dirty_warn : %u\n", message->lidar_error_code.dirty_warn);
printf("firmware_err : %u\n", message->lidar_error_code.firmware_err);
printf("pps_status : %u\n", message->lidar_error_code.device_status);
printf("fan_status : %u\n", message->lidar_error_code.fan_status);
printf("self_heating : %u\n", message->lidar_error_code.self_heating);
printf("ptp_status : %u\n", message->lidar_error_code.ptp_status);
printf("time_sync_status : %u\n", message->lidar_error_code.time_sync_status);
printf("system_status : %u\n", message->lidar_error_code.system_status);
}
}
}
/** Receiving point cloud data from Livox LiDAR. */
void GetLidarData(uint8_t handle, LivoxEthPacket *data, uint32_t data_num, void *client_data) {
if (data) {
if (handle < connected_lidar_count && is_finish_extrinsic_parameter) {
std::unique_lockstd::mutex lock(mtx);
LvxBasePackDetail packet;
packet.device_index = handle;
lvx_file_handler.BasePointsHandle(data, packet);
point_packet_list.push_back(packet);
}
}
}
/** Callback function of starting sampling. */
void OnSampleCallback(livox_status status, uint8_t handle, uint8_t response, void *data) {
printf("OnSampleCallback statues %d handle %d response %d \n", status, handle, response);
if (status == kStatusSuccess) {
if (response != 0) {
devices[handle].device_state = kDeviceStateConnect;
}
} else if (status == kStatusTimeout) {
devices[handle].device_state = kDeviceStateConnect;
}
}
/** Callback function of stopping sampling. */
void OnStopSampleCallback(livox_status status, uint8_t handle, uint8_t response, void *data) {
}
/** Callback function of get LiDARs' extrinsic parameter. */
void OnGetLidarExtrinsicParameter(livox_status status, uint8_t handle, LidarGetExtrinsicParameterResponse *response, void *data) {
if (status == kStatusSuccess) {
if (response != 0) {
printf("OnGetLidarExtrinsicParameter statue %d handle %d response %d \n", status, handle, response->ret_code);
std::unique_lockstd::mutex lock(mtx);
LvxDeviceInfo lidar_info;
strncpy((char *)lidar_info.lidar_broadcast_code, devices[handle].info.broadcast_code, kBroadcastCodeSize);
memset(lidar_info.hub_broadcast_code, 0, kBroadcastCodeSize);
lidar_info.device_index = handle;
lidar_info.device_type = devices[handle].info.type;
lidar_info.extrinsic_enable = true;
lidar_info.pitch = response->pitch;
lidar_info.roll = response->roll;
lidar_info.yaw = response->yaw;
lidar_info.x = static_cast(response->x / 1000.0);
lidar_info.y = static_cast(response->y / 1000.0);
lidar_info.z = static_cast(response->z / 1000.0);
lvx_file_handler.AddDeviceInfo(lidar_info);
if (lvx_file_handler.GetDeviceInfoListSize() == connected_lidar_count) {
is_finish_extrinsic_parameter = true;
extrinsic_condition.notify_one();
}
}
}
else if (status == kStatusTimeout) {
printf("GetLidarExtrinsicParameter timeout! \n");
}
}
/** Get LiDARs' extrinsic parameter from file named "extrinsic.xml". */
void LidarGetExtrinsicFromXml(uint8_t handle) {
LvxDeviceInfo lidar_info;
ParseExtrinsicXml(devices[handle], lidar_info);
lvx_file_handler.AddDeviceInfo(lidar_info);
lidar_info.extrinsic_enable = true;
if (lvx_file_handler.GetDeviceInfoListSize() == broadcast_code_list.size()) {
is_finish_extrinsic_parameter = true;
extrinsic_condition.notify_one();
}
}
/** Query the firmware version of Livox LiDAR. */
void OnDeviceInformation(livox_status status, uint8_t handle, DeviceInformationResponse *ack, void *data) {
if (status != kStatusSuccess) {
printf("Device Query Informations Failed %d\n", status);
}
if (ack) {
printf("firm ver: %d.%d.%d.%d\n",
ack->firmware_version[0],
ack->firmware_version[1],
ack->firmware_version[2],
ack->firmware_version[3]);
}
}
void LidarConnect(const DeviceInfo *info) {
uint8_t handle = info->handle;
QueryDeviceInformation(handle, OnDeviceInformation, NULL);
if (devices[handle].device_state == kDeviceStateDisconnect) {
devices[handle].device_state = kDeviceStateConnect;
devices[handle].info = *info;
}
}
void LidarDisConnect(const DeviceInfo *info) {
uint8_t handle = info->handle;
devices[handle].device_state = kDeviceStateDisconnect;
}
void LidarStateChange(const DeviceInfo *info) {
uint8_t handle = info->handle;
devices[handle].info = *info;
}
/** Callback function of changing of device state. */
void OnDeviceInfoChange(const DeviceInfo *info, DeviceEvent type) {
if (info == nullptr) {
return;
}
printf("OnDeviceChange broadcast code %s update type %d\n", info->broadcast_code, type);
uint8_t handle = info->handle;
if (handle >= kMaxLidarCount) {
return;
}
if (type == kEventConnect) {
LidarConnect(info);
printf("[WARNING] Lidar sn: [%s] Connect!!!\n", info->broadcast_code);
} else if (type == kEventDisconnect) {
LidarDisConnect(info);
printf("[WARNING] Lidar sn: [%s] Disconnect!!!\n", info->broadcast_code);
} else if (type == kEventStateChange) {
LidarStateChange(info);
printf("[WARNING] Lidar sn: [%s] StateChange!!!\n", info->broadcast_code);
}
if (devices[handle].device_state == kDeviceStateConnect) {
printf("Device Working State %d\n", devices[handle].info.state);
if (devices[handle].info.state == kLidarStateInit) {
printf("Device State Change Progress %u\n", devices[handle].info.status.progress);
} else {
printf("Device State Error Code 0X%08x\n", devices[handle].info.status.status_code.error_code);
}
printf("Device feature %d\n", devices[handle].info.feature);
SetErrorMessageCallback(handle, OnLidarErrorStatusCallback);
if (devices[handle].info.state == kLidarStateNormal) {
if (!is_read_extrinsic_from_xml) {
LidarGetExtrinsicParameter(handle, OnGetLidarExtrinsicParameter, nullptr);
} else {
LidarGetExtrinsicFromXml(handle);
}
LidarStartSampling(handle, OnSampleCallback, nullptr);
devices[handle].device_state = kDeviceStateSampling;
}
}
}
/** Callback function when broadcast message received.
You need to add listening device broadcast code and set the point cloud data callback in this function.
*/
void OnDeviceBroadcast(const BroadcastDeviceInfo *info) {
if (info == nullptr || info->dev_type == kDeviceTypeHub) {
return;
}
printf("Receive Broadcast Code %s\n", info->broadcast_code);
if ((broadcast_code_rev.size() == 0) ||
(std::find(broadcast_code_rev.begin(), broadcast_code_rev.end(), info->broadcast_code) == broadcast_code_rev.end())) {
broadcast_code_rev.push_back(info->broadcast_code);
lidar_arrive_condition.notify_one();
}
}
/** Wait until no new device arriving in 2 second. */
void WaitForDevicesReady( ) {
bool device_ready = false;
seconds wait_time = seconds(2);
steady_clock::time_point last_time = steady_clock::now();
while (!device_ready) {
std::unique_lockstd::mutex lock(mtx);
lidar_arrive_condition.wait_for(lock,wait_time);
if ((steady_clock::now() - last_time + milliseconds(50)) >= wait_time) {
device_ready = true;
} else {
last_time = steady_clock::now();
}
}
}
void WaitForExtrinsicParameter() {
std::unique_lockstd::mutex lock(mtx);
extrinsic_condition.wait(lock);
}
void AddDevicesToConnect() {
if (broadcast_code_rev.size() == 0)
return;
for (int i = 0; i < broadcast_code_rev.size(); ++i) {
if ((broadcast_code_list.size() != 0) &&
(std::find(broadcast_code_list.begin(), broadcast_code_list.end(), broadcast_code_rev[i]) == broadcast_code_list.end())) {
continue;
}
uint8_t handle = 0;
livox_status result = AddLidarToConnect(broadcast_code_rev[i].c_str(), &handle);
if (result == kStatusSuccess) {
/** Set the point cloud data for a specific Livox LiDAR. */
SetDataCallback(handle, GetLidarData, nullptr);
devices[handle].handle = handle;
devices[handle].device_state = kDeviceStateDisconnect;
connected_lidar_count++;
}
}
}
/** Set the program options.
You can input the registered device broadcast code and decide whether to save the log file.
*/
void SetProgramOption(int argc, const char *argv[]) {
cmdline::parser cmd;
cmd.addstd::string("code", 'c', "Register device broadcast code", false);
cmd.add("log", 'l', "Save the log file");
cmd.add("time", 't', "Time to save point cloud to the lvx file", false);
cmd.add("param", 'p', "Get the extrinsic parameter from extrinsic.xml file");
cmd.add("help", 'h', "Show help");
cmd.parse_check(argc, const_cast<char **>(argv));
if (cmd.exist("code")) {
std::string sn_list = cmd.getstd::string("code");
printf("Register broadcast code: %s\n", sn_list.c_str());
size_t pos = 0;
broadcast_code_list.clear();
while ((pos = sn_list.find("&")) != std::string::npos) {
broadcast_code_list.push_back(sn_list.substr(0, pos));
sn_list.erase(0, pos + 1);
}
broadcast_code_list.push_back(sn_list);
}
if (cmd.exist("log")) {
printf("Save the log file.\n");
SaveLoggerFile();
}
if (cmd.exist("time")) {
printf("Time to save point cloud to the lvx file:%d.\n", cmd.get("time"));
lvx_file_save_time = cmd.get("time");
}
if (cmd.exist("param")) {
printf("Get the extrinsic parameter from extrinsic.xml file.\n");
is_read_extrinsic_from_xml = true;
}
return;
}
int main(int argc, const char argv[]) {
/* Set the program options. */
SetProgramOption(argc, argv);
LdsLidar& read_lidar = LdsLidar::GetInstance();
int ret = read_lidar.InitLdsLidar(cmdline_broadcast_code);
if (!ret) {
printf("Init lds lidar success!\n");
} else {
printf("Init lds lidar fail!\n");
return 0;
}
printf("Start discovering device.\n");
Synchro& synchro = Synchro::GetInstance();
#ifdef WIN32
synchro.SetPortName("COM1");
#else
synchro.SetPortName("/dev/ttyUSB0");
#endif
/** Set Synchro's Baudrate: 115200. /
synchro.SetBaudRate(BR115200);
/* Set Synchro's Parity: No parity (8N1). /
synchro.SetParity(P_8N1);
/* SyncTimer Callback will trigger when Synchro's GPRMC/GNRMC signal is ready. */
synchro.SetSyncTimerCallback(read_lidar.SetRmcSyncTime);
if (synchro.Start()) {
printf("Synchro start success\n");
} else {
printf("Synchro start failed\n");
return 0;
}
std::this_thread::sleep_for(std::chrono::seconds(2));
//synchro.Stop();
read_lidar.DeInitLdsLidar();
//printf("Livox lidar demo end!\n");
std::this_thread::sleep_for(std::chrono::seconds(2));
/*********************************************************/
printf("Livox SDK initializing.\n");
//Initialize Livox-SDK.
if (!Init()) {
return -1;
}
printf("Livox SDK has been initialized.\n");
LivoxSdkVersion _sdkversion;
GetLivoxSdkVersion(&_sdkversion);
printf("Livox SDK version %d.%d.%d .\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch);
memset(devices, 0, sizeof(devices));
/** Set the callback function receiving broadcast message from Livox LiDAR. */
SetBroadcastCallback(OnDeviceBroadcast);
/** Set the callback function called when device state change,
which means connection/disconnection and changing of LiDAR state.
*/
SetDeviceStateUpdateCallback(OnDeviceInfoChange);
/** Start the device discovering routine. */
if (!Start()) {
Uninit();
return -1;
}
printf("Start discovering device.\n");
WaitForDevicesReady();
AddDevicesToConnect();
if (connected_lidar_count == 0) {
printf("No device will be connected.\n");
Uninit();
return -1;
}
WaitForExtrinsicParameter();
/等待GPS同步后, 才记录点云数据生成.lvx文件*******/
printf("Start initialize lvx file.\n");
if (!lvx_file_handler.InitLvxFile()) {
Uninit();
return -1;
}
std::this_thread::sleep_for(std::chrono::seconds(5));
lvx_file_handler.InitLvxFileHeader();
int i = 0;
steady_clock::time_point last_time = steady_clock::now();
for (i = 0; i < lvx_file_save_time * FRAME_RATE; ++i) {
std::list point_packet_list_temp;
{
std::unique_lockstd::mutex lock(mtx);
point_pack_condition.wait_for(lock, milliseconds(kDefaultFrameDurationTime) - (steady_clock::now() - last_time));
last_time = steady_clock::now();
point_packet_list_temp.swap(point_packet_list);
}
if(point_packet_list_temp.empty()) {
printf("Point cloud packet is empty.\n");
break;
}
printf("Finish save %d frame to lvx file.\n", i);
lvx_file_handler.SaveFrameToLvxFile(point_packet_list_temp);
}
lvx_file_handler.CloseLvxFile();
for (i = 0; i < kMaxLidarCount; ++i) {
if (devices[i].device_state == kDeviceStateSampling) {
/** Stop the sampling of Livox LiDAR. */
LidarStopSampling(devices[i].handle, OnStopSampleCallback, nullptr);
}
}
/** Uninitialize Livox-SDK. */
Uninit();
}
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.