diff --git a/pandora/pandora_driver/launch/pandora_driver_apollo.launch b/pandora/pandora_driver/launch/pandora_driver_apollo.launch
index aecaed5..f212e91 100755
--- a/pandora/pandora_driver/launch/pandora_driver_apollo.launch
+++ b/pandora/pandora_driver/launch/pandora_driver_apollo.launch
@@ -8,8 +8,8 @@
-
-
+
+
diff --git a/pandora/pandora_driver/src/Pandar40P/CMakeLists.txt b/pandora/pandora_driver/src/Pandar40P/CMakeLists.txt
index 1e0af55..f1e021f 100644
--- a/pandora/pandora_driver/src/Pandar40P/CMakeLists.txt
+++ b/pandora/pandora_driver/src/Pandar40P/CMakeLists.txt
@@ -5,7 +5,7 @@ project(Pandar40P)
find_package( Boost REQUIRED )
find_package(PCL REQUIRED COMPONENTS common)
-set (CMAKE_CXX_FLAGS "-fPIC -std=c++11")
+set (CMAKE_CXX_FLAGS "-fPIC --std=c++11")
include_directories(
diff --git a/pandora/pandora_driver/src/Pandar40P/include/pandar40p/pandar40p.h b/pandora/pandora_driver/src/Pandar40P/include/pandar40p/pandar40p.h
index d936938..de2c689 100644
--- a/pandora/pandora_driver/src/Pandar40P/include/pandar40p/pandar40p.h
+++ b/pandora/pandora_driver/src/Pandar40P/include/pandar40p/pandar40p.h
@@ -17,7 +17,6 @@
#ifndef INCLUDE_PANDAR40P_H_
#define INCLUDE_PANDAR40P_H_
-#include
#include
#include
#include
@@ -25,6 +24,8 @@
#include
+#include
+
#include "pandar40p/point_types.h"
namespace apollo {
@@ -45,15 +46,14 @@ class Pandar40P {
* start_angle The start angle of every point cloud ,
* should be * 100.
*/
- Pandar40P(const std::string &device_ip,
- uint16_t lidar_port, uint16_t gps_port,
+ Pandar40P(const std::string &device_ip, uint16_t lidar_port, uint16_t gps_port,
boost::function, double)>
pcl_callback,
boost::function gps_callback, uint16_t start_angle,
int tz, std::string frame_id);
/**
- * @brief destructor
+ * @brief deconstructor
*/
~Pandar40P();
diff --git a/pandora/pandora_driver/src/Pandar40P/src/input.cc b/pandora/pandora_driver/src/Pandar40P/src/input.cc
index 25a4d26..701ff44 100644
--- a/pandora/pandora_driver/src/Pandar40P/src/input.cc
+++ b/pandora/pandora_driver/src/Pandar40P/src/input.cc
@@ -32,9 +32,7 @@ namespace drivers {
namespace hesai {
Input::Input(uint16_t port, uint16_t gpsPort) {
- socketForGPS = -1;
socketForLidar = -1;
-
socketForLidar = socket(PF_INET, SOCK_DGRAM, 0);
if (socketForLidar == -1) {
perror("socket"); // TODO(Philip.Pi): perror errno.
@@ -63,6 +61,7 @@ Input::Input(uint16_t port, uint16_t gpsPort) {
return;
}
// gps socket
+ socketForGPS = -1;
socketForGPS = socket(PF_INET, SOCK_DGRAM, 0);
if (socketForGPS == -1) {
perror("socket"); // TODO(Philip.Pi): perror errno.
@@ -128,7 +127,7 @@ int Input::getPacket(PandarPacket *pkt) {
}
senderAddressLen = sizeof(senderAddress);
- ssize_t nbytes = 0;
+ ssize_t nbytes;
for (int i = 0; i != socketNumber; ++i) {
if (fds[i].revents & POLLIN) {
nbytes = recvfrom(fds[i].fd, &pkt->data[0], ETHERNET_MTU, 0,
diff --git a/pandora/pandora_driver/src/Pandar40P/src/input.h b/pandora/pandora_driver/src/Pandar40P/src/input.h
index dfcca66..bbdf596 100644
--- a/pandora/pandora_driver/src/Pandar40P/src/input.h
+++ b/pandora/pandora_driver/src/Pandar40P/src/input.h
@@ -18,7 +18,6 @@
#define SRC_INPUT_H_
#include
-#include
#include
#include
#include
@@ -39,9 +38,8 @@ class Input {
public:
Input(uint16_t port, uint16_t gpsPort);
~Input();
- Input(std::string filePath, int type); // not implemented
+ Input(std::string filePath, int type);
int getPacket(PandarPacket *pkt);
- int getPacketFromPcap(PandarPacket *pkt); // not implemented
private:
int socketForLidar;
diff --git a/pandora/pandora_driver/src/Pandar40P/src/pandar40p.cc b/pandora/pandora_driver/src/Pandar40P/src/pandar40p.cc
index 5889b06..4182143 100644
--- a/pandora/pandora_driver/src/Pandar40P/src/pandar40p.cc
+++ b/pandora/pandora_driver/src/Pandar40P/src/pandar40p.cc
@@ -41,7 +41,7 @@ Pandar40P::Pandar40P(
}
/**
- * @brief destructor
+ * @brief deconstructor
*/
Pandar40P::~Pandar40P() { delete internal_; }
diff --git a/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.cc b/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.cc
index 44e0aa7..3732ca6 100644
--- a/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.cc
+++ b/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.cc
@@ -14,7 +14,6 @@
* limitations under the License.
*****************************************************************************/
-#include
#include
#include "src/input.h"
@@ -38,7 +37,7 @@ static const float pandar40p_elev_angle_map[] = {
-4.321, -4.657, -4.986, -5.311, -5.647, -5.974, -6.957, -7.934,
-8.908, -9.871, -10.826, -11.772, -12.705, -13.63, -14.543, -15.444};
-// Line 40 Lidar azimuth Horizontal offset , Line 1 - Line 40
+// Line 40 Lidar azimuth Horizatal offset , Line 1 - Line 40
static const float pandar40p_horizatal_azimuth_offset_map[] = {
0.005, 0.006, 0.006, 0.006, -2.479, -2.479, 2.491, -4.953,
-2.479, 2.492, -4.953, -2.479, 2.492, -4.953, 0.007, 2.491,
@@ -47,7 +46,7 @@ static const float pandar40p_horizatal_azimuth_offset_map[] = {
0.004, 0.004, 0.003, 0.003, -2.466, -2.463, -2.46, -2.457};
Pandar40P_Internal::Pandar40P_Internal(
- const std::string &device_ip, uint16_t lidar_port, uint16_t gps_port,
+ std::string device_ip, uint16_t lidar_port, uint16_t gps_port,
boost::function, double)> pcl_callback,
boost::function gps_callback, uint16_t start_angle, int tz,
std::string frame_id) {
@@ -60,7 +59,7 @@ Pandar40P_Internal::Pandar40P_Internal(
enable_lidar_recv_thr_ = false;
enable_lidar_process_thr_ = false;
- start_angle_ = start_angle > 36000 ? 0 : start_angle;
+ start_angle_ = start_angle;
for (uint16_t rotIndex = 0; rotIndex < ROTATION_MAX_UNITS; ++rotIndex) {
float rotation = degreeToRadian(0.01 * static_cast(rotIndex));
@@ -73,6 +72,8 @@ Pandar40P_Internal::Pandar40P_Internal(
pcl_callback_ = pcl_callback;
gps_callback_ = gps_callback;
+ last_azimuth_ = 0;
+
// init the block time offset, us
blockOffset_[9] = 55.1f * 0.0 + 45.18f;
blockOffset_[8] = 55.1f * 1.0 + 45.18f;
@@ -148,7 +149,7 @@ Pandar40P_Internal::~Pandar40P_Internal() {
* @brief load the correction file
* @param file The path of correction file
*/
-int Pandar40P_Internal::LoadCorrectionFile(const std::string &correction_content) { // NOLINT
+int Pandar40P_Internal::LoadCorrectionFile(std::string correction_content) {
std::istringstream ifs(correction_content);
std::string line;
@@ -193,7 +194,7 @@ int Pandar40P_Internal::LoadCorrectionFile(const std::string &correction_content
}
/**
- * @brief reset the start angle
+ * @brief load the correction file
* @param angle The start angle
*/
void Pandar40P_Internal::ResetStartAngle(uint16_t start_angle) {
@@ -251,9 +252,9 @@ void Pandar40P_Internal::RecvTask() {
}
void Pandar40P_Internal::ProcessLiarPacket() {
+ double lastTimestamp = 0.0f;
struct timespec ts;
int ret = 0;
- static int packetIndex = 0;
boost::shared_ptr outMsg(new PPointCloud());
@@ -279,31 +280,29 @@ void Pandar40P_Internal::ProcessLiarPacket() {
continue;
}
- packetIndex++;
-
for (int i = 0; i < BLOCKS_PER_PACKET; ++i) {
- /* ready a round ? */
- uint16_t current_azimuth = pkt.blocks[i].azimuth;
- int limit_degree = RATE_PER_PACKET * 100/2;
- int gap = std::min(std::abs(current_azimuth - start_angle_),
- 36000 - std::abs(current_azimuth - start_angle_));
-
- // at lease 150 packets, no more than 182
- if ((packetIndex > PACKETS_PER_ROUND * 5/6 && gap <= limit_degree) ||
- packetIndex > PACKETS_PER_ROUND + 1) {
- // ok
- if (pcl_callback_ && outMsg->points.size() > 0) {
- // std::cout << std::fixed << std::setprecision(18)
- // << "Size: " << packetIndex << ", current: " << current_azimuth
- // << ", timestamp_: " << timestamp_ << std::endl;
- pcl_callback_(outMsg, timestamp_);
- outMsg.reset(new PPointCloud());
- // reset
- packetIndex = 0; timestamp_ = 0;
+ int azimuthGap = 0; /* To do */
+ if(last_azimuth_ > pkt.blocks[i].azimuth) {
+ azimuthGap = static_cast(pkt.blocks[i].azimuth) + (36000 - static_cast(last_azimuth_));
+ } else {
+ azimuthGap = static_cast(pkt.blocks[i].azimuth) - static_cast(last_azimuth_);
+ }
+
+ if (last_azimuth_ != pkt.blocks[i].azimuth &&
+ azimuthGap < 600 /* 6 degree*/) {
+ /* for all the blocks */
+ if ((last_azimuth_ > pkt.blocks[i].azimuth &&
+ start_angle_ <= pkt.blocks[i].azimuth) ||
+ (last_azimuth_ < start_angle_ &&
+ start_angle_ <= pkt.blocks[i].azimuth)) {
+ if (pcl_callback_ && outMsg->points.size() > 0) {
+ pcl_callback_(outMsg, outMsg->points[0].timestamp);
+ outMsg.reset(new PPointCloud());
+ }
}
}
-
CalcPointXYZIT(&pkt, i, outMsg);
+ last_azimuth_ = pkt.blocks[i].azimuth;
}
} else {
continue;
@@ -331,13 +330,13 @@ void Pandar40P_Internal::ProcessGps(const PandarGPS &gpsMsg) {
// UTC's month start from 1, but mktime only accept month from 0.
t.tm_mon = gpsMsg.month - 1;
- // UTC's year only include 0 - 99 year , which indicates 2000 to 2099.
- // and mktime's year start from 1900 which is 0, so we need to add 100 years.
+ // UTC's year only include 0 - 99 year , which indicate 2000 to 2099.
+ // and mktime's year start from 1900 which is 0. so we need add 100 year.
t.tm_year = gpsMsg.year + 100;
t.tm_isdst = 0;
if (gps_callback_) {
- gps_callback_(static_cast(mktime(&t) + tz_second_) + 1);
+ gps_callback_(static_cast(mktime(&t) + tz_second_));
}
}
@@ -393,7 +392,7 @@ int Pandar40P_Internal::ParseRawData(Pandar40PPacket *packet,
// parse the UTC Time.
// UTC's year only include 0 - 99 year , which indicate 2000 to 2099.
- // and mktime's year start from 1900 which is 0, so we need to add 100 years.
+ // and mktime's year start from 1900 which is 0. so we need add 100 year.
packet->t.tm_year = (buf[index + 0] & 0xff) + 100;
// UTC's month start from 1, but mktime only accept month from 0.
packet->t.tm_mon = (buf[index + 1] & 0xff) - 1;
@@ -458,7 +457,7 @@ void Pandar40P_Internal::CalcPointXYZIT(Pandar40PPacket *pkt, int blockid,
Pandar40PBlock *block = &pkt->blocks[blockid];
double unix_second =
- static_cast(mktime(&pkt->t) + 1 + tz_second_); // 1 second offset
+ static_cast(mktime(&pkt->t) + tz_second_);
for (int i = 0; i < LASER_COUNT; ++i) {
/* for all the units in a block */
@@ -499,7 +498,7 @@ void Pandar40P_Internal::CalcPointXYZIT(Pandar40PPacket *pkt, int blockid,
// dual return, block 0&1 (2&3 , 4*5 ...)'s timestamp is the same.
point.timestamp =
point.timestamp - (static_cast(blockOffset_[blockid / 2] +
- laserOffset_[i / 2]) /
+ laserOffset_[i]) /
1000000.0f);
} else {
point.timestamp =
@@ -509,11 +508,6 @@ void Pandar40P_Internal::CalcPointXYZIT(Pandar40PPacket *pkt, int blockid,
}
point.ring = i;
- // get smallest timestamp
- if ((timestamp_ > 0 && timestamp_ < point.timestamp)
- || timestamp_ <= 0) {
- timestamp_ = point.timestamp;
- }
cld->push_back(point);
}
diff --git a/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.h b/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.h
index 3fd46c9..ac68bfc 100644
--- a/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.h
+++ b/pandora/pandora_driver/src/Pandar40P/src/pandar40p_internal.h
@@ -17,7 +17,6 @@
#ifndef SRC_PANDAR40P_INTERNAL_H_
#define SRC_PANDAR40P_INTERNAL_H_
-#include
#include
#include
#include
@@ -26,11 +25,11 @@
#include
#include
+#include
+
#include "pandar40p/point_types.h"
#include "src/input.h"
-#define RATE_PER_PACKET (2)
-#define PACKETS_PER_ROUND (360 / RATE_PER_PACKET)
#define SOB_ANGLE_SIZE (4)
#define RAW_MEASURE_SIZE (3)
#define LASER_COUNT (40)
@@ -43,7 +42,7 @@
#define REVOLUTION_SIZE (2)
#define INFO_SIZE \
(TIMESTAMP_SIZE + FACTORY_INFO_SIZE + ECHO_SIZE + RESERVE_SIZE + \
- REVOLUTION_SIZE)
+ REVOLUTION_SIZE)
#define UTC_TIME (6)
#define PACKET_SIZE (BLOCK_SIZE * BLOCKS_PER_PACKET + INFO_SIZE + UTC_TIME)
#define LASER_RETURN_TO_DISTANCE_RATE (0.004)
@@ -112,7 +111,7 @@ class Pandar40P_Internal {
* type The device type
*/
Pandar40P_Internal(
- const std::string &device_ip, uint16_t lidar_port, uint16_t gps_port,
+ std::string device_ip, uint16_t lidar_port, uint16_t gps_port,
boost::function, double)>
pcl_callback,
boost::function gps_callback, uint16_t start_angle, int tz,
@@ -122,10 +121,10 @@ class Pandar40P_Internal {
* @brief load the correction file
* @param correction The path of correction file
*/
- int LoadCorrectionFile(const std::string &correction);
+ int LoadCorrectionFile(std::string correction);
/**
- * @brief reset the start angle.
+ * @brief load the correction file
* @param angle The start angle
*/
void ResetStartAngle(uint16_t start_angle);
@@ -151,8 +150,7 @@ class Pandar40P_Internal {
boost::thread *lidar_process_thr_;
bool enable_lidar_recv_thr_;
bool enable_lidar_process_thr_;
- int start_angle_ = 0;
- double timestamp_ = 0;
+ int start_angle_;
std::list lidar_packets_;
@@ -164,6 +162,8 @@ class Pandar40P_Internal {
float sin_lookup_table_[ROTATION_MAX_UNITS];
float cos_lookup_table_[ROTATION_MAX_UNITS];
+ uint16_t last_azimuth_;
+
float elev_angle_map_[LASER_COUNT];
float horizatal_azimuth_offset_map_[LASER_COUNT];
diff --git a/pandora/pandora_driver/src/Pandar40P/test/test.cc b/pandora/pandora_driver/src/Pandar40P/test/test.cc
index f4a9035..b92da5c 100644
--- a/pandora/pandora_driver/src/Pandar40P/test/test.cc
+++ b/pandora/pandora_driver/src/Pandar40P/test/test.cc
@@ -16,7 +16,7 @@
#include "pandar40p/pandar40p.h"
-using apollo::drivers::hesai;
+using namespace apollo::drivers::hesai;
FILE* lidarTimestampFile = fopen("lidar-timestamp.txt", "w");
@@ -27,10 +27,8 @@ void gpsCallback(int timestamp) {
struct timeval ts;
gettimeofday(&ts, NULL);
gpsTimestamp = timestamp;
- double sec = static_cast(ts.tv_sec);
- double usec = static_cast(ts.tv_usec);
- double t = static_cast(timestamp);
- pandoraToSysTimeGap = tv_sec + (tv_usec / 1000000.0) - timestamp;
+ pandoraToSysTimeGap =
+ (double)ts.tv_sec + ((double)ts.tv_usec / 1000000.0) - (double)timestamp;
printf("gps: %d, gap: %f\n", timestamp, pandoraToSysTimeGap);
}
@@ -38,17 +36,16 @@ void lidarCallback(boost::shared_ptr cld, double timestamp) {
struct timeval ts;
gettimeofday(&ts, NULL);
printf("lidar: %lf\n", timestamp);
- double usec = static_cast(ts.tv_usec);
fprintf(lidarTimestampFile, "%d, %f,%f\n", gpsTimestamp, timestamp,
- ts.tv_sec + tv_usec / 1000000 - pandoraToSysTimeGap - timestamp);
+ ts.tv_sec + (double)ts.tv_usec / 1000000 - pandoraToSysTimeGap -
+ timestamp);
}
int main(int argc, char** argv) {
Pandar40P pandar40p(std::string("192.168.20.51"), 2368, 10110, lidarCallback,
- gpsCallback, 0);
+ gpsCallback, 13500, 0, std::string("hesai40"));
pandar40p.Start();
while (true) {
sleep(100);
}
-}
-
+}
\ No newline at end of file
diff --git a/pandora/pandora_driver/src/main.cc b/pandora/pandora_driver/src/main.cc
index 4a446e8..65db2a8 100755
--- a/pandora/pandora_driver/src/main.cc
+++ b/pandora/pandora_driver/src/main.cc
@@ -146,11 +146,22 @@ class PandoraHesaiClient {
int pic_id, bool distortion) {
sensor_msgs::ImagePtr imgMsg;
- if (pic_id > 4 || pic_id < 0) {
- ROS_INFO("picid wrong in getImageToPub");
+ if (pic_id > 1 || pic_id < 0) {
+ //ROS_INFO("picid wrong in getImageToPub");
return;
}
- imgMsg = cv_bridge::CvImage(std_msgs::Header(), "rgb8", *matp).toImageMsg();
+
+ if (0 == pic_id)
+ {
+ imgMsg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", *matp).toImageMsg();
+ }
+ else
+ {
+ cv::Mat grayMat;
+ cv::cvtColor(*matp, grayMat, CV_RGB2GRAY);
+ imgMsg = cv_bridge::CvImage(std_msgs::Header(), "mono8", grayMat).toImageMsg();
+ }
+
imgMsg->header.stamp = ros::Time(timestamp);
imgPublishers[pic_id].publish(imgMsg);
}
diff --git a/pandora/pandora_driver/src/pandora.cc b/pandora/pandora_driver/src/pandora.cc
index cd171a6..38a7398 100644
--- a/pandora/pandora_driver/src/pandora.cc
+++ b/pandora/pandora_driver/src/pandora.cc
@@ -29,8 +29,7 @@ namespace hesai {
class Pandora_Internal {
public:
Pandora_Internal(
- const std::string &device_ip,
- const uint16_t lidar_port, const uint16_t gps_port,
+ std::string device_ip, const uint16_t lidar_port, const uint16_t gps_port,
boost::function, double)>
pcl_callback,
boost::function gps_callback, uint16_t start_angle,
@@ -46,7 +45,7 @@ class Pandora_Internal {
int GetCameraCalibration(CameraCalibration calibs[5]);
int ResetCameraClibration();
void GetCalibrationFromDevice();
- int ParseCameraCalibration(const std::string &contents,
+ int ParseCameraCalibration(const std::string contents,
CameraCalibration calibs[5]);
int GenerateCameraCalibration(const CameraCalibration calibs[5],
std::string *contents);
@@ -69,8 +68,7 @@ class Pandora_Internal {
};
Pandora_Internal::Pandora_Internal(
- const std::string &device_ip,
- const uint16_t lidar_port, const uint16_t gps_port,
+ std::string device_ip, const uint16_t lidar_port, const uint16_t gps_port,
boost::function, double)> pcl_callback,
boost::function gps_callback, uint16_t start_angle,
const uint16_t pandoraCameraPort,
@@ -117,7 +115,7 @@ Pandora_Internal::~Pandora_Internal() {
* @brief load the correction file
* @param file The path of correction file
*/
-int Pandora_Internal::LoadLidarCorrectionFile(const std::string &correction_content) { // NOLINT
+int Pandora_Internal::LoadLidarCorrectionFile(const std::string &correction_content) {
return pandar40p_->LoadCorrectionFile(correction_content);
}
@@ -200,8 +198,8 @@ void Pandora_Internal::GetCalibrationFromDevice() {
!got_camera_calibration_) {
if (!got_lidar_calibration_) {
// get lidar calibration.
- char *buffer;
- uint32_t len;
+ char *buffer = NULL;
+ uint32_t len = 0;
ret = TcpCommandGetLidarCalibration(tcp_command_client_, &buffer, &len);
if (ret == 0 && buffer) {
@@ -226,8 +224,8 @@ void Pandora_Internal::GetCalibrationFromDevice() {
if (!got_camera_calibration_) {
// get camera calibration.
- char *buffer;
- uint32_t len;
+ char *buffer = NULL;
+ uint32_t len = 0;
ret = TcpCommandGetCalibration(tcp_command_client_, &buffer, &len);
if (ret == 0 && buffer) {
@@ -262,7 +260,7 @@ void Pandora_Internal::GetCalibrationFromDevice() {
}
}
-int Pandora_Internal::ParseCameraCalibration(const std::string &contents,
+int Pandora_Internal::ParseCameraCalibration(const std::string contents,
CameraCalibration calibs[5]) {
std::cout << "Parse Camera Calibration..." << std::endl;
if (contents.empty()) {
@@ -392,8 +390,7 @@ Pandora Part
* cameraCallback the call back for camera data
*/
Pandora::Pandora(
- const std::string &device_ip,
- const uint16_t lidar_port, const uint16_t gps_port,
+ const std::string &device_ip, const uint16_t lidar_port, const uint16_t gps_port,
boost::function, double)> pcl_callback,
boost::function gps_callback, uint16_t start_angle,
const uint16_t pandoraCameraPort,
@@ -407,7 +404,7 @@ Pandora::Pandora(
}
/**
- * @brief destructor
+ * @brief deconstructor
*/
Pandora::~Pandora() { delete internal_; }
diff --git a/pandora/pandora_driver/src/pandora_camera.cc b/pandora/pandora_driver/src/pandora_camera.cc
index f229965..bec0046 100644
--- a/pandora/pandora_driver/src/pandora_camera.cc
+++ b/pandora/pandora_driver/src/pandora_camera.cc
@@ -38,15 +38,20 @@ static int CameraClientCallback(void *handle, int cmd, void *param,
}
PandoraCamera::PandoraCamera(
- const std::string &device_ip, const uint16_t pandoraCameraPort,
+ std::string device_ip, const uint16_t pandoraCameraPort,
boost::function matp, double timestamp,
int picid, bool distortion)>
camera_callback,
boost::function connectionChanged, int tz) {
ip_ = device_ip;
- sem_init(&pic_sem_, 0, 0);
- pthread_mutex_init(&pic_lock_, NULL);
- process_pic_thread_ = NULL;
+
+ for (int i = 0; i < CAMERA_NUM; ++i) {
+ /* init pic lock / sem */
+ sem_init(&pic_sem_[i], 0, 0);
+ pthread_mutex_init(&pic_lock_[i], NULL);
+ process_pic_thread_[i] = NULL;
+ }
+
continue_process_pic_ = false;
need_remap_ = false;
camera_port_ = pandoraCameraPort;
@@ -58,8 +63,11 @@ PandoraCamera::PandoraCamera(
PandoraCamera::~PandoraCamera() {
Stop();
- sem_destroy(&pic_sem_);
- pthread_mutex_destroy(&pic_lock_);
+ for (int i = 0; i < CAMERA_NUM; ++i)
+ {
+ sem_destroy(&pic_sem_[i]);
+ pthread_mutex_destroy(&pic_lock_[i]);
+ }
}
int PandoraCamera::Start() {
@@ -71,12 +79,16 @@ int PandoraCamera::Start() {
continue_process_pic_ = false;
return -1;
}
- process_pic_thread_ =
- new boost::thread(boost::bind(&PandoraCamera::processPic, this));
- if (!process_pic_thread_) {
- continue_process_pic_ = false;
- PandoraClientDestroy(pandora_client_);
- return -1;
+
+ for (int i = 0; i < CAMERA_NUM; ++i) {
+ process_pic_thread_[i] =
+ new boost::thread(boost::bind(&PandoraCamera::processPic, this , i));
+ if (!process_pic_thread_[i]) {
+ continue_process_pic_ = false;
+ PandoraClientDestroy(pandora_client_);
+ pandora_client_ = NULL;
+ return -1;
+ }
}
return 0;
}
@@ -88,21 +100,24 @@ void PandoraCamera::Stop() {
}
pandora_client_ = NULL;
- if (process_pic_thread_) {
- process_pic_thread_->join();
- delete process_pic_thread_;
+ for (int i = 0; i < CAMERA_NUM; ++i) {
+ if (process_pic_thread_[i]) {
+ process_pic_thread_[i]->join();
+ delete process_pic_thread_[i];
+ }
+ process_pic_thread_[i] = NULL;
}
- process_pic_thread_ = NULL;
+
}
void PandoraCamera::pushPicture(PandoraPic *pic) {
- pthread_mutex_lock(&pic_lock_);
- pic_list_.push_back(pic);
- pthread_mutex_unlock(&pic_lock_);
- sem_post(&pic_sem_);
+ pthread_mutex_lock(&pic_lock_[pic->header.pic_id]);
+ pic_list_[pic->header.pic_id].push_back(pic);
+ pthread_mutex_unlock(&pic_lock_[pic->header.pic_id]);
+ sem_post(&pic_sem_[pic->header.pic_id]);
}
-void PandoraCamera::processPic() {
+void PandoraCamera::processPic(int pic_id) {
while (continue_process_pic_) {
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
@@ -110,14 +125,14 @@ void PandoraCamera::processPic() {
}
ts.tv_sec += 1;
- if (sem_timedwait(&pic_sem_, &ts) == -1) {
+ if (sem_timedwait(&pic_sem_[pic_id], &ts) == -1) {
continue;
}
- pthread_mutex_lock(&pic_lock_);
- PandoraPic *pic = pic_list_.front();
- pic_list_.pop_front();
- pthread_mutex_unlock(&pic_lock_);
+ pthread_mutex_lock(&pic_lock_[pic_id]);
+ PandoraPic *pic = pic_list_[pic_id].front();
+ pic_list_[pic_id].pop_front();
+ pthread_mutex_unlock(&pic_lock_[pic_id]);
if (pic == NULL) {
printf("pic is NULL\n");
@@ -136,16 +151,13 @@ void PandoraCamera::processPic() {
boost::shared_ptr cvMatPic(new cv::Mat());
switch (pic->header.pic_id) {
case 0:
- yuv422ToCvmat(cvMatPic, pic->yuv, pic->header.width, pic->header.height,
- 8);
- if (need_remap_)
- remap(cvMatPic->clone(), *cvMatPic, mapx_[pic->header.pic_id],
- mapy_[pic->header.pic_id], CV_INTER_LINEAR);
- break;
+ //yuv422ToCvmat(cvMatPic, pic->yuv, pic->header.width, pic->header.height,
+ // 8);
+ //if (need_remap_)
+ // remap(cvMatPic->clone(), *cvMatPic, mapx_[pic->header.pic_id],
+ // mapy_[pic->header.pic_id], CV_INTER_LINEAR);
+ //break;
case 1:
- case 2:
- case 3:
- case 4:
uint8_t *bmp;
uint32_t bmpSize;
decompressJpeg(static_cast(pic->yuv), pic->header.len, &bmp,
@@ -157,18 +169,22 @@ void PandoraCamera::processPic() {
mapy_[pic->header.pic_id], CV_INTER_LINEAR);
free(bmp);
+ bmp = NULL;
break;
+ case 2:
+ case 3:
+ case 4:
default:
free(pic->yuv);
+ pic->yuv = NULL;
free(pic);
+ pic = NULL;
printf("wrong pic id\n");
return;
}
if (camera_callback_) {
- // Add 2 seconds to correct the timestamp, Reason? No reason.
- // liuxingwei@hesaitech.com
- camera_callback_(cvMatPic, timestamp + 2 + tz_second_, pic->header.pic_id,
+ camera_callback_(cvMatPic, timestamp + tz_second_, pic->header.pic_id,
need_remap_);
}
free(pic->yuv);
@@ -178,8 +194,8 @@ void PandoraCamera::processPic() {
}
}
-bool PandoraCamera::loadIntrinsics(const std::vector &cameras_k,
- const std::vector &cameras_d) {
+bool PandoraCamera::loadIntrinsics(const std::vector cameras_k,
+ const std::vector cameras_d) {
for (int i = 0; i < CAMERA_NUM; i++) {
cv::Mat mapx = cv::Mat(HesaiLidarSDK_IMAGE_SIZE, CV_32FC1);
cv::Mat mapy = cv::Mat(HesaiLidarSDK_IMAGE_SIZE, CV_32FC1);
diff --git a/pandora/pandora_driver/src/pandora_camera.h b/pandora/pandora_driver/src/pandora_camera.h
index 059ce72..b39393d 100644
--- a/pandora/pandora_driver/src/pandora_camera.h
+++ b/pandora/pandora_driver/src/pandora_camera.h
@@ -17,8 +17,6 @@
#ifndef SRC_PANDORA_CAMERA_H_
#define SRC_PANDORA_CAMERA_H_
-#include
-#include
#include
#include
#include
@@ -28,6 +26,9 @@
#include
#include
+#include
+#include
+
#include "src/pandora_client.h"
namespace apollo {
@@ -50,7 +51,7 @@ class PandoraCamera {
* type The device type
*/
PandoraCamera(
- const std::string &device_ip, const uint16_t pandoraCameraPort,
+ std::string device_ip, const uint16_t pandoraCameraPort,
boost::function matp, double timestamp,
int picid, bool distortion)>
camera_callback,
@@ -62,15 +63,15 @@ class PandoraCamera {
* @param angle The start angle
*/
- bool loadIntrinsics(const std::vector &cameras_k,
- const std::vector &cameras_d);
+ bool loadIntrinsics(const std::vector cameras_k,
+ const std::vector cameras_d);
int Start();
void Stop();
void pushPicture(PandoraPic *pic);
private:
- void processPic();
+ void processPic(int pic_id);
int decompressJpeg(uint8_t *jpgBuffer, const uint32_t jpgSize, uint8_t **bmp,
uint32_t *bmpSize);
@@ -81,15 +82,15 @@ class PandoraCamera {
void yuvToRgb(const int iY, const int iU, const int iV, int *iR, int *iG,
int *iB);
- pthread_mutex_t pic_lock_;
- sem_t pic_sem_;
- boost::thread *process_pic_thread_;
+ pthread_mutex_t pic_lock_[CAMERA_NUM];
+ sem_t pic_sem_[CAMERA_NUM];
+ boost::thread *process_pic_thread_[CAMERA_NUM];
bool continue_process_pic_;
bool need_remap_;
std::string ip_;
uint16_t camera_port_;
void *pandora_client_;
- std::list pic_list_;
+ std::list pic_list_[CAMERA_NUM];
std::vector mapx_;
std::vector mapy_;
boost::function matp, double timestamp,
diff --git a/pandora/pandora_driver/src/pandora_client.c b/pandora/pandora_driver/src/pandora_client.c
index f8badd6..9151652 100644
--- a/pandora/pandora_driver/src/pandora_client.c
+++ b/pandora/pandora_driver/src/pandora_client.c
@@ -171,17 +171,26 @@ void PandoraClientHeartBeatTask(void* handle) {
return;
}
int ret = 0;
+
while (!client->exit) {
- if (-1 == client->cliSocket) {
+ int clifd = -1;
+
+ pthread_mutex_lock(&client->cliSocketLock);
+ if(client->cliSocket != -1) {
+ clifd = client->cliSocket;
+ } else {
+ pthread_mutex_unlock(&client->cliSocketLock);
sleep(1);
continue;
}
- ret = select_fd(client->cliSocket, 1, WAIT_FOR_WRITE);
+ pthread_mutex_unlock(&client->cliSocketLock);
+
+ ret = select_fd(clifd, 1, WAIT_FOR_WRITE);
if (ret > 0) {
- ret = write(client->cliSocket, "HEARTBEAT", strlen("HEARTBEAT"));
+ ret = write(clifd, "HEARTBEAT", strlen("HEARTBEAT"));
if (ret < 0) {
- printf("Write Error\n");
+ // printf("Write Error\n");
}
}
@@ -296,7 +305,7 @@ void PandoraClientTask(void* handle) {
continue;
}
- // check the desired frame position packet.
+ // check the desired frame postion packet.
if (pic->header.position != client->position[pic->header.pic_id]) {
client->position[pic->header.pic_id] = 0;
free(pic->yuv);
diff --git a/pandora/pandora_driver/src/tcp_command_client.c b/pandora/pandora_driver/src/tcp_command_client.c
index 13b69c8..22efef0 100644
--- a/pandora/pandora_driver/src/tcp_command_client.c
+++ b/pandora/pandora_driver/src/tcp_command_client.c
@@ -14,12 +14,9 @@
* limitations under the License.
*****************************************************************************/
-#include "src/tcp_command_client.h"
#include
#include
#include
-#include
-#include
#include
#include
#include
@@ -28,14 +25,17 @@
#include
#include
#include
-#include
#include
#include
#include
#include
#include
#include
+#include
+#include
+#include
#include "src/util.h"
+#include "src/tcp_command_client.h"
typedef struct TcpCommandClient_s {
pthread_mutex_t lock;
@@ -136,7 +136,7 @@ static int TcpCommand_buildHeader(char* buffer, TC_Command* cmd) {
static PTC_ErrCode tcpCommandClient_SendCmd(TcpCommandClient* client,
TC_Command* cmd) {
- if (!client || !cmd) {
+ if (!client && !cmd) {
printf("Bad Parameter\n");
return PTC_ERROR_BAD_PARAMETER;
}
diff --git a/pandora/pandora_pointcloud/include/pandora_pointcloud/compensator.h b/pandora/pandora_pointcloud/include/pandora_pointcloud/compensator.h
index 097520b..f997dae 100644
--- a/pandora/pandora_pointcloud/include/pandora_pointcloud/compensator.h
+++ b/pandora/pandora_pointcloud/include/pandora_pointcloud/compensator.h
@@ -24,7 +24,6 @@
#include
#include
#include
-#include
namespace apollo {
namespace drivers {
@@ -32,8 +31,8 @@ namespace pandora {
class Compensator {
public:
- Compensator(ros::NodeHandle node, ros::NodeHandle private_nh);
- virtual ~Compensator() {}
+ Compensator(ros::NodeHandle& node, ros::NodeHandle& private_nh);
+ virtual ~Compensator() = default;
private:
/**
@@ -46,9 +45,9 @@ class Compensator {
* novatel-preprocess broadcast the tf2 transfrom.
*/
bool query_pose_affine_from_tf2(const double timestamp,
- Eigen::Affine3d* pose);
+ Eigen::Affine3d& pose);
/**
- * @brief check if message is valid, check width, height, timesatmp.
+ * @brief check if message is valid, check width, height, timestamp.
* set timestamp_offset and point data type
*/
bool check_message(sensor_msgs::PointCloud2ConstPtr msg);
@@ -56,7 +55,7 @@ class Compensator {
* @brief motion compensation for point cloud
*/
template
- void motion_compensation(sensor_msgs::PointCloud2::Ptr msg,
+ void motion_compensation(sensor_msgs::PointCloud2::Ptr& msg,
const double timestamp_min,
const double timestamp_max,
const Eigen::Affine3d& pose_min_time,
@@ -65,14 +64,14 @@ class Compensator {
* @brief get min timestamp and max timestamp from points in pointcloud2
*/
inline void get_timestamp_interval(
- sensor_msgs::PointCloud2ConstPtr msg, double* timestamp_min,
- double* timestamp_max);
+ sensor_msgs::PointCloud2ConstPtr msg, double& timestamp_min,
+ double& timestamp_max);
/**
* @brief get point field size by sensor_msgs::datatype
*/
inline uint get_field_size(const int data_type);
- // subsrcibe pandora pointcloud2 msg.
+ // subscribe pandora pointcloud2 msg.
ros::Subscriber pointcloud_sub_;
// publish point cloud2 after motion compensation
ros::Publisher compensation_pub_;
diff --git a/pandora/pandora_pointcloud/src/compensator.cc b/pandora/pandora_pointcloud/src/compensator.cc
index 0b75810..4c802a2 100644
--- a/pandora/pandora_pointcloud/src/compensator.cc
+++ b/pandora/pandora_pointcloud/src/compensator.cc
@@ -14,8 +14,6 @@
* limitations under the License.
*****************************************************************************/
-#include
-#include
#include "pandora_pointcloud/compensator.h"
#include "ros/this_node.h"
@@ -23,7 +21,7 @@ namespace apollo {
namespace drivers {
namespace pandora {
-Compensator::Compensator(ros::NodeHandle node, ros::NodeHandle private_nh)
+Compensator::Compensator(ros::NodeHandle& node, ros::NodeHandle& private_nh)
: tf2_transform_listener_(tf2_buffer_, node),
x_offset_(-1),
y_offset_(-1),
@@ -38,15 +36,14 @@ Compensator::Compensator(ros::NodeHandle node, ros::NodeHandle private_nh)
private_nh.param("topic_pointcloud", topic_pointcloud_,
std::string("/apollo/sensor/pandora/hesai40/PointCloud2"));
private_nh.param("queue_size", queue_size_, 10);
- private_nh.param("tf_query_timeout", tf_timeout_, 0.1f);
+ private_nh.param("tf_query_timeout", tf_timeout_, float(0.1));
// advertise output point cloud (before subscribing to input data)
compensation_pub_ = node.advertise(
topic_compensated_pointcloud_, queue_size_);
pointcloud_sub_ =
node.subscribe(topic_pointcloud_, queue_size_,
- &Compensator::pointcloud_callback,
- reinterpret_cast(this));
+ &Compensator::pointcloud_callback, (Compensator*)this);
}
void Compensator::pointcloud_callback(
@@ -59,13 +56,13 @@ void Compensator::pointcloud_callback(
Eigen::Affine3d pose_min_time;
Eigen::Affine3d pose_max_time;
- double timestamp_min = 0;
- double timestamp_max = 0;
- get_timestamp_interval(msg, ×tamp_min, ×tamp_max);
+ double timestamp_min = 0.0;
+ double timestamp_max = 0.0;
+ get_timestamp_interval(msg, timestamp_min, timestamp_max);
// compensate point cloud, remove nan point
- if (query_pose_affine_from_tf2(timestamp_min, &pose_min_time) &&
- query_pose_affine_from_tf2(timestamp_max, &pose_max_time)) {
+ if (query_pose_affine_from_tf2(timestamp_min, pose_min_time) &&
+ query_pose_affine_from_tf2(timestamp_max, pose_max_time)) {
// we change message after motion compensation
sensor_msgs::PointCloud2::Ptr q_msg(new sensor_msgs::PointCloud2());
*q_msg = *msg;
@@ -77,10 +74,10 @@ void Compensator::pointcloud_callback(
}
inline void Compensator::get_timestamp_interval(
- sensor_msgs::PointCloud2ConstPtr msg, double* timestamp_min,
- double* timestamp_max) {
- *timestamp_max = 0.0;
- *timestamp_min = std::numeric_limits::max();
+ sensor_msgs::PointCloud2ConstPtr msg, double& timestamp_min,
+ double& timestamp_max) {
+ timestamp_max = 0.0;
+ timestamp_min = std::numeric_limits::max();
int total = msg->width * msg->height;
// get min time and max time
@@ -89,16 +86,16 @@ inline void Compensator::get_timestamp_interval(
memcpy(×tamp, &msg->data[i * msg->point_step + timestamp_offset_],
timestamp_data_size_);
- if (timestamp < *timestamp_min) {
- *timestamp_min = timestamp;
+ if (timestamp < timestamp_min) {
+ timestamp_min = timestamp;
}
- if (timestamp > *timestamp_max) {
- *timestamp_max = timestamp;
+ if (timestamp > timestamp_max) {
+ timestamp_max = timestamp;
}
}
}
-// TODO(a): if point type is always float, and timestamp is always double?
+// TODO: if point type is always float, and timestamp is always double?
inline bool Compensator::check_message(
sensor_msgs::PointCloud2ConstPtr msg) {
// check msg width and height
@@ -110,7 +107,7 @@ inline bool Compensator::check_message(
int y_data_type = 0;
int z_data_type = 0;
- // TODO(a): will use a new datastruct with interface to get offset,
+ // TODO: will use a new datastruct with interface to get offset,
// datatype,datasize...
for (size_t i = 0; i < msg->fields.size(); ++i) {
const sensor_msgs::PointField& f = msg->fields[i];
@@ -157,7 +154,7 @@ inline bool Compensator::check_message(
}
bool Compensator::query_pose_affine_from_tf2(const double timestamp,
- Eigen::Affine3d* pose) {
+ Eigen::Affine3d& pose) {
ros::Time query_time(timestamp);
std::string err_string;
if (!tf2_buffer_.canTransform("world", child_frame_id_, query_time,
@@ -178,7 +175,7 @@ bool Compensator::query_pose_affine_from_tf2(const double timestamp,
return false;
}
- tf::transformMsgToEigen(stamped_transform.transform, *pose);
+ tf::transformMsgToEigen(stamped_transform.transform, pose);
// ROS_DEBUG_STREAM("pose matrix : " << pose);
return true;
}
@@ -211,7 +208,7 @@ inline uint Compensator::get_field_size(const int datatype) {
}
template
-void Compensator::motion_compensation(sensor_msgs::PointCloud2::Ptr msg,
+void Compensator::motion_compensation(sensor_msgs::PointCloud2::Ptr& msg,
const double timestamp_min,
const double timestamp_max,
const Eigen::Affine3d& pose_min_time,
@@ -237,72 +234,48 @@ void Compensator::motion_compensation(sensor_msgs::PointCloud2::Ptr msg,
// Threshold for a "significant" rotation from min_time to max_time:
// The LiDAR range accuracy is ~2 cm. Over 70 meters range, it means an angle
- // of 0.02 / 70 =
- // 0.0003 rad. So, we consider a rotation "significant" only if the scalar
- // part of quaternion is
- // less than cos(0.0003 / 2) = 1 - 1e-8.
- if (abs_d < 1.0 - 1.0e-8) {
- double theta = acos(abs_d);
- double sin_theta = sin(theta);
- double c1_sign = (d > 0) ? 1 : -1;
- for (int i = 0; i < total; ++i) {
- size_t offset = i * msg->point_step;
- Scalar* x_scalar =
- reinterpret_cast(&msg->data[offset + x_offset_]);
- if (std::isnan(*x_scalar)) {
- ROS_DEBUG_STREAM("nan point do not need motion compensation");
- continue;
- }
- Scalar* y_scalar =
- reinterpret_cast(&msg->data[offset + y_offset_]);
- Scalar* z_scalar =
- reinterpret_cast(&msg->data[offset + z_offset_]);
- Eigen::Vector3d p(*x_scalar, *y_scalar, *z_scalar);
-
- double tp = 0.0;
- memcpy(&tp, &msg->data[i * msg->point_step + timestamp_offset_],
- timestamp_data_size_);
- double t = (timestamp_max - tp) * f;
-
- Eigen::Translation3d ti(t * translation);
-
- double c0 = sin((1 - t) * theta) / sin_theta;
- double c1 = sin(t * theta) / sin_theta * c1_sign;
- Eigen::Quaterniond qi(c0 * q0.coeffs() + c1 * q1.coeffs());
-
- Eigen::Affine3d trans = ti * qi;
- p = trans * p;
- *x_scalar = p.x();
- *y_scalar = p.y();
- *z_scalar = p.z();
- }
- return;
- }
- // Not a "significant" rotation. Do translation only.
+ // of 0.02 / 70 = 0.0003 rad. So, we consider a rotation "significant" only if
+ // the scalar part of quaternion is less than cos(0.0003 / 2) = 1 - 1e-8.
+ const double theta = acos(abs_d);
+ const double sin_theta = sin(theta);
+ const double c1_sign = (d > 0) ? 1 : -1;
for (int i = 0; i < total; ++i) {
+ size_t offset = i * msg->point_step;
Scalar* x_scalar =
- reinterpret_cast(&msg->data[i * msg->point_step + x_offset_]);
+ reinterpret_cast(&msg->data[offset + x_offset_]);
if (std::isnan(*x_scalar)) {
ROS_DEBUG_STREAM("nan point do not need motion compensation");
continue;
}
Scalar* y_scalar =
- reinterpret_cast(&msg->data[i * msg->point_step + y_offset_]);
+ reinterpret_cast(&msg->data[offset + y_offset_]);
Scalar* z_scalar =
- reinterpret_cast(&msg->data[i * msg->point_step + z_offset_]);
+ reinterpret_cast(&msg->data[offset + z_offset_]);
Eigen::Vector3d p(*x_scalar, *y_scalar, *z_scalar);
double tp = 0.0;
memcpy(&tp, &msg->data[i * msg->point_step + timestamp_offset_],
timestamp_data_size_);
double t = (timestamp_max - tp) * f;
+
Eigen::Translation3d ti(t * translation);
- p = ti * p;
+ if (abs_d < 1.0 - 1.0e-8) {
+ // "significant". Do both rotation and translation.
+ double c0 = sin((1 - t) * theta) / sin_theta;
+ double c1 = sin(t * theta) / sin_theta * c1_sign;
+ Eigen::Quaterniond qi(c0 * q0.coeffs() + c1 * q1.coeffs());
+ Eigen::Affine3d trans = ti * qi;
+ p = trans * p;
+ } else {
+ // Not a "significant" rotation. Do translation only.
+ p = ti * p;
+ }
*x_scalar = p.x();
*y_scalar = p.y();
*z_scalar = p.z();
}
+ return;
}
} // namespace pandora