10 #include <arpa/inet.h> 12 #include <sys/socket.h> 13 #include <sys/types.h> 21 using ns = std::chrono::nanoseconds;
44 int sock_fd = socket(PF_INET, SOCK_DGRAM, 0);
46 std::cerr <<
"socket: " << std::strerror(errno) << std::endl;
50 struct sockaddr_in my_addr;
51 memset((
char*)&my_addr, 0,
sizeof(my_addr));
52 my_addr.sin_family = AF_INET;
53 my_addr.sin_port = htons(port);
54 my_addr.sin_addr.s_addr = INADDR_ANY;
56 if (bind(sock_fd, (
struct sockaddr*)&my_addr,
sizeof(my_addr)) < 0) {
57 std::cerr <<
"bind: " << std::strerror(errno) << std::endl;
61 struct timeval timeout;
64 if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
65 sizeof(timeout)) < 0) {
66 std::cerr <<
"setsockopt: " << std::strerror(errno) << std::endl;
74 struct addrinfo hints, *info_start, *ai;
76 memset(&hints, 0,
sizeof hints);
77 hints.ai_family = AF_UNSPEC;
78 hints.ai_socktype = SOCK_STREAM;
80 int ret = getaddrinfo(addr,
"7501", &hints, &info_start);
82 std::cerr <<
"getaddrinfo: " << gai_strerror(ret) << std::endl;
85 if (info_start == NULL) {
86 std::cerr <<
"getaddrinfo: empty result" << std::endl;
91 for (ai = info_start; ai != NULL; ai = ai->ai_next) {
92 sock_fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
94 std::cerr <<
"socket: " << std::strerror(errno) << std::endl;
98 if (connect(sock_fd, ai->ai_addr, ai->ai_addrlen) == -1) {
106 freeaddrinfo(info_start);
115 const std::string& udp_dest_host,
116 int lidar_port,
int imu_port) {
119 if (sock_fd < 0)
return std::shared_ptr<client>();
123 auto do_cmd = [&](
const std::string& op,
const std::string& val) {
124 const size_t max_res_len = 4095;
125 char read_buf[max_res_len + 1];
128 std::string cmd = op +
" " + val +
"\n";
130 len = write(sock_fd, cmd.c_str(), cmd.length());
131 if (len != (ssize_t)cmd.length()) {
133 return std::string(
"[error] init_client: failed to send command");
136 len = read(sock_fd, read_buf, max_res_len);
139 return std::string(
"[error] read: ") + std::strerror(errno);
141 read_buf[len] =
'\0';
143 auto res = std::string(read_buf);
144 res.erase(res.find_last_not_of(
" \r\n\t") + 1);
149 auto do_cmd_chk = [&](
const std::string& op,
const std::string& val) {
150 auto res = do_cmd(op, val);
151 if (res.find(
"[error]") != std::string::npos) {
152 std::cerr << res << std::endl;
154 }
else if (res != op) {
155 std::cerr <<
"init_client: command \"" << op <<
" " << val <<
"\" failed with \"" 156 << res <<
"\"" << std::endl;
162 auto get_cmd = [&](
const std::string& op,
const std::string& val) {
163 auto res = do_cmd(op, val);
164 if (res.find(
"error") != std::string::npos) {
165 std::cerr << res << std::endl;
166 return std::string(
"");
171 auto str_tok = [&](
const std::string &str,
const std::string delim) {
172 auto start = str.find_first_not_of(delim);
174 std::vector<std::string> tokens;
176 while (start != std::string::npos){
177 end = str.find_first_of(delim, start);
178 tokens.push_back(str.substr(start, end-start));
179 start = str.find_first_not_of(delim, end);
186 success &= do_cmd_chk(
"set_udp_port_lidar", std::to_string(lidar_port));
187 success &= do_cmd_chk(
"set_udp_port_imu", std::to_string(imu_port));
188 success &= do_cmd_chk(
"set_udp_ip", udp_dest_host);
190 if (!success)
return std::shared_ptr<client>();
196 std::string version_str = std::string(
"");
197 std::string product_str = std::string(
"");
198 bool has_pulsemode =
true;
199 auto sensor_info_str = get_cmd(
"get_sensor_info",
"");
200 auto tokens = str_tok(sensor_info_str, std::string(
",: \""));
201 auto pos = std::find(tokens.begin(), tokens.end(),
"build_rev");
202 if (pos != tokens.end()) {
203 version_str = *(pos+1);
205 pos = std::find(tokens.begin(), tokens.end(),
"prod_line");
206 if (pos != tokens.end()) {
207 product_str = *(pos+1);
209 if (product_str == std::string(
"") || version_str == std::string(
"")) {
210 std::cout <<
"Error: Failed to read product name and firmware version." << std::endl;
211 return std::shared_ptr<client>();
213 std::cout <<
"Ouster model \"" << product_str <<
"\", firmware version \"" << version_str <<
"\"" << std::endl;
215 if (product_str != std::string(
"OS-1-64")) {
216 std::cout <<
"Error: this driver currently only supports Ouster model \"OS-1-64\"." << std::endl;
217 return std::shared_ptr<client>();
220 auto ver_numbers = str_tok(version_str, std::string(
"v."));
222 auto ver_major = std::stoi(ver_numbers[0],
nullptr);
223 auto ver_minor = std::stoi(ver_numbers[1],
nullptr);
224 if (ver_major < 1 || ver_minor < 7) {
225 std::cout <<
"Error: Firmware version \"" << version_str <<
"\" is not supported, please upgrade" << std::endl;
226 return std::shared_ptr<client>();
228 if (std::stoi(ver_numbers[1],
nullptr) >= 10) {
229 std::cout <<
"On firmware version \"" << version_str <<
"\" the \"pulse_mode\" parameter is no longer available, will ignore it." << std::endl;
230 has_pulsemode =
false;
234 auto curr_operation_mode_str = get_cmd(
"get_config_param",
"active lidar_mode");
235 auto curr_pulse_mode_str = std::string(
"");
237 curr_pulse_mode_str = get_cmd(
"get_config_param",
"active pulse_mode");
239 auto curr_window_rejection_str = get_cmd(
"get_config_param",
"active window_rejection_enable");
240 bool do_configure =
false;
244 if (curr_operation_mode_str != _operation_mode_str) {
245 success &= do_cmd_chk(
"set_config_param",
"lidar_mode " + _operation_mode_str);
248 if (has_pulsemode && (curr_pulse_mode_str != _pulse_mode_str)) {
249 success &= do_cmd_chk(
"set_config_param",
"pulse_mode " + _pulse_mode_str);
252 if (curr_window_rejection_str != _window_rejection_str) {
253 success &= do_cmd_chk(
"set_config_param",
"window_rejection_enable " + _window_rejection_str);
257 if (!success)
return std::shared_ptr<client>();
261 success &= do_cmd_chk(
"reinitialize",
"");
262 if (!success)
return std::shared_ptr<client>();
263 std::cout <<
"Parameters configured, reinitializing sensor" << std::endl;
265 std::cout <<
"Parameters already configured, no need to reinitialize" << std::endl;
273 auto cli = std::make_shared<client>();
287 int retval = select(max_fd + 1, &rfds, NULL, NULL, NULL);
291 std::cerr <<
"select: " << std::strerror(errno) << std::endl;
301 ssize_t n = recvfrom(fd, buf, len + 1, 0, NULL, NULL);
302 if (n == (ssize_t)len)
305 std::cerr <<
"recvfrom: " << std::strerror(errno) << std::endl;
307 std::cerr <<
"Unexpected udp packet length: " << n << std::endl;
323 void set_advanced_params(std::string operation_mode_str, std::string pulse_mode_str,
bool window_rejection)
325 _operation_mode_str = operation_mode_str;
326 _pulse_mode_str = pulse_mode_str;
327 _window_rejection = window_rejection;
330 if (_operation_mode_str == std::string(
"512x10")) {
332 }
else if (_operation_mode_str == std::string(
"1024x10")) {
334 }
else if (_operation_mode_str == std::string(
"2048x10")) {
336 }
else if (_operation_mode_str == std::string(
"512x20")) {
338 }
else if (_operation_mode_str == std::string(
"1024x20")) {
341 std::cout <<
"Selected operation mode " << _operation_mode_str <<
" is invalid, using default mode \"1024x10\"" << std::endl;
345 if (_pulse_mode_str == std::string(
"STANDARD")) {
347 }
else if (_pulse_mode_str == std::string(
"NARROW")) {
350 std::cout <<
"Selected pulse mode " << _pulse_mode_str <<
" is invalid, using default mode \"STANDARD\"" << std::endl;
353 _window_rejection_str = ((
_window_rejection) ? std::string(
"1") : std::string(
"0"));
const size_t imu_packet_bytes
std::shared_ptr< client > init_client(const std::string &hostname, const std::string &udp_dest_host, int lidar_port, int imu_port)
std::chrono::nanoseconds ns
void set_advanced_params(std::string operation_mode_str, std::string pulse_mode_str, bool window_rejection)
bool read_imu_packet(const client &cli, uint8_t *buf)
static std::string _window_rejection_str
static std::string _operation_mode_str
static bool recv_fixed(int fd, void *buf, size_t len)
static bool _window_rejection
const size_t lidar_packet_bytes
static int udp_data_socket(int port)
static std::string _pulse_mode_str
client_state poll_client(const client &cli)
bool read_lidar_packet(const client &cli, uint8_t *buf)
static PulseMode _pulse_mode
static int cfg_socket(const char *addr)
static OperationMode _operation_mode