本文主要是记录ARS_408毫米波雷达协议解读与简单实现过程。仍在学习过程中,难免存在理解误区,欢迎批评指正,共同进步。
文章目录
引言:
传感器发送和接收的CAN信息类型如下表所示,下面主要用到的协议包括2个输入信息部分(RadarCfg 和 Motion Input Signals)和3个输出信息部分(RadarState 以及Cluster List 和Object List)。
1、RadarCfg部分
- 定义Union共用体变量用于存储数据
namespace radar_cfg {
typedef union radar_cfg {
struct { // ":"表示机构内位域的定义,即该变量占几个bit空间
uint64_t RadarCfg_MaxDistance_valid:1;
uint64_t RadarCfg_SensorID_valid:1;
uint64_t RadarCfg_RadarPower_valid:1;
uint64_t RadarCfg_OutputType_valid:1;
uint64_t RadarCfg_SendQuality_valid:1;
uint64_t RadarCfg_SendExtInfo_valid:1;
uint64_t RadarCfg_SortIndex_valid:1;
uint64_t RadarCfg_StoreInNVM_valid:1;
uint64_t RadarCfg_MaxDistance1:8;
uint64_t Reserved:6;
uint64_t RadarCfg_MaxDistance2:2;
uint64_t Reserved2:8;
uint64_t RadarCfg_SensorID:3;
uint64_t RadarCfg_OutputType:2;
uint64_t RadarCfg_RadarPower:3;
uint64_t RadarCfg_CtrlRelay_valid:1;
uint64_t RadarCfg_CtrlRelay:1;
uint64_t RadarCfg_SendQuality:1;
uint64_t RadarCfg_SendExtInfo:1;
uint64_t RadarCfg_SortIndex:3;
uint64_t RadarCfg_StoreInNVM:1;
uint64_t RadarCfg_RCS_Threshold_valid:1;
uint64_t RadarCfg_RCS_Threshold:3;
uint64_t Reserved3:4;
uint64_t Reserved4:8;
} data = {};
uint8_t raw_data[8];
} radar_cfg;
}
- 定义RadarCfg类
namespace radar_cfg {
class RadarCfg {
public:
RadarCfg();
~RadarCfg();
bool set_max_distance(uint64_t distance, bool valid = true); //最大距离
bool set_sensor_id(int id, bool valid = true); //传感器ID
bool set_radar_power(int power, bool valid = true); //雷达发射功率
bool set_output_type(int output_type, bool valid = true); //数据输出模式
void set_send_quality(bool quality, bool valid = true); //quality信息
void set_send_ext_info(bool send_ext, bool valid = true); //Extended信息
bool set_sort_index(int sort_index, bool valid = true); //为object list选择排序索引(clusters list默认按照距离进行排列)
void set_ctrl_relay_cfg(bool ctrl_relay, bool valid = true); //Relay control message
void set_store_in_nvm(bool store_in_nvm, bool valid = true); //将配置信息保存到non-volatile memory(NVM),以便传感器启动时读取和配置
bool set_rcs_threshold(int rcs_threshold, bool valid = true); //cluster检测的灵敏度设置,标准(0x0)或高灵敏度(0x1)
radar_cfg *get_radar_cfg();
private:
radar_cfg radar_cfg_msg;
};
}
- RadarCfg类的实现
namespace radar_cfg {
RadarCfg::RadarCfg() {
radar_cfg_msg.data.RadarCfg_MaxDistance_valid = 0;
radar_cfg_msg.data.RadarCfg_SensorID_valid = 0;
radar_cfg_msg.data.RadarCfg_RadarPower_valid = 0;
radar_cfg_msg.data.RadarCfg_OutputType_valid = 0;
radar_cfg_msg.data.RadarCfg_SendQuality_valid = 0;
radar_cfg_msg.data.RadarCfg_SendExtInfo_valid = 0;
radar_cfg_msg.data.RadarCfg_SortIndex_valid = 0;
radar_cfg_msg.data.RadarCfg_CtrlRelay_valid = 0;
radar_cfg_msg.data.RadarCfg_StoreInNVM_valid = 0;
radar_cfg_msg.data.RadarCfg_RCS_Threshold_valid = 0;
}
RadarCfg::~RadarCfg() {
}
bool RadarCfg::set_max_distance(uint64_t distance, bool valid) {
if (distance < 90 || distance > 1000) {
return false; //Extended Range ARS408:196m~1200m ARS404:90m~1000m
}
distance /= 2;
radar_cfg_msg.data.RadarCfg_MaxDistance1 = distance >> 2; // 二进制值按位右移2位,表示取数据的去掉2位后的高位部分
radar_cfg_msg.data.RadarCfg_MaxDistance2 = distance & 0b11; //取数据的最后2位地位部分
radar_cfg_msg.data.RadarCfg_MaxDistance_valid = static_cast<uint64_t>(valid);
return true;
}
bool RadarCfg::set_sensor_id(int id, bool valid) {
if (id < 0 || id > 7) {
return false;
}
radar_cfg_msg.data.RadarCfg_SensorID = static_cast<uint64_t>(id);
radar_cfg_msg.data.RadarCfg_SensorID_valid = static_cast<uint64_t>(valid);
return true;
}
bool RadarCfg::set_radar_power(int power, bool valid) {
if (power < 0 || power > 3) {
return false; //0x0: Standard 0x1: -3dB Tx gain 0x2: -6dB Tx gain 0x3: -9dB Tx gain
}
radar_cfg_msg.data.RadarCfg_RadarPower = static_cast<uint64_t>(power);
radar_cfg_msg.data.RadarCfg_RadarPower_valid = static_cast<uint64_t>(valid);
return true;
}
bool RadarCfg::set_output_type(int output_type, bool valid) {
if (output_type < 0 || output_type > 2) { //Clusters (0x2) or Objects (0x1) or “Stand By” (0x0)
return false;
}
radar_cfg_msg.data.RadarCfg_OutputType = static_cast<uint64_t>(output_type);
radar_cfg_msg.data.RadarCfg_OutputType_valid = static_cast<uint64_t>(valid);
return true;
}
void RadarCfg::set_send_quality(bool quality, bool valid) {
radar_cfg_msg.data.RadarCfg_SendQuality = static_cast<uint64_t>(quality);
radar_cfg_msg.data.RadarCfg_SendQuality_valid = static_cast<uint64_t>(valid); //Cluster or object quality information (message 0x60C or 0x702) is sent if true
}
void RadarCfg::set_send_ext_info(bool send_ext, bool valid) {
radar_cfg_msg.data.RadarCfg_SendExtInfo = static_cast<uint64_t>(send_ext);
radar_cfg_msg.data.RadarCfg_SendExtInfo_valid = static_cast<uint64_t>(valid); //Extended information (message 0x60D) is sent for objects if true (if clusters are selected as output type this value is ignored)
}
bool RadarCfg::set_sort_index(int sort_index, bool valid) {
if (sort_index < 0 || sort_index > 2) {
return false; //Selects the sorting index for the object list (ignored for clusters as they are always sorted by range)
}
radar_cfg_msg.data.RadarCfg_SortIndex = static_cast<uint64_t>(sort_index);
radar_cfg_msg.data.RadarCfg_SortIndex_valid = static_cast<uint64_t>(valid);
return true;
}
void RadarCfg::set_ctrl_relay_cfg(bool ctrl_relay, bool valid) {
radar_cfg_msg.data.RadarCfg_CtrlRelay = static_cast<uint64_t>(ctrl_relay);
radar_cfg_msg.data.RadarCfg_CtrlRelay_valid = static_cast<uint64_t>(valid); //Relay control message (0x8) is sent if true and the collision detection is activated
}
void RadarCfg::set_store_in_nvm(bool store_in_nvm, bool valid) {
radar_cfg_msg.data.RadarCfg_StoreInNVM = static_cast<uint64_t>(store_in_nvm);
radar_cfg_msg.data.RadarCfg_StoreInNVM_valid = static_cast<uint64_t>(valid); //Stores the current configuration to non-volatile memory to be read and set at sensor startup
}
bool RadarCfg::set_rcs_threshold(int rcs_threshold, bool valid) {
if (rcs_threshold != 0 && rcs_threshold != 1) {
return false; //Sets the sensitivity of the cluster detection to standard (0x0) or high sensitivity (0x1)
}
radar_cfg_msg.data.RadarCfg_RCS_Threshold = static_cast<uint64_t>(rcs_threshold);
radar_cfg_msg.data.RadarCfg_RCS_Threshold_valid = static_cast<uint64_t>(valid);
return true;
}
radar_cfg *RadarCfg::get_radar_cfg() {
return &radar_cfg_msg;
}
}
2、RadarState部分
- RadarState(0x201)消息是由传感器周期性的发送,每秒一次。在RadarCfg(0x200)参数配置后,可以检查消息0x201中的相应信号,以确认配置更改是否已完成。
- 定义Union共用体用于存储数据
namespace radar_state {
typedef union radar_state {
struct {
uint64_t Reserved:6;
uint64_t RadarState_NVMReadStatus:1;
uint64_t RadarState_NVMwriteStatus:1;
uint64_t RadarState_MaxDistanceCfg1:8;
uint64_t Reserved2:1;
uint64_t RadarState_Voltage_Error:1;
uint64_t RadarState_Temporary_Error:1;
uint64_t RadarState_Temperature_Error:1;
uint64_t RadarState_Interference:1;
uint64_t RadarState_Persistent_Error:1;
uint64_t RadarState_MaxDistanceCfg2:2;
uint64_t RadarState_RadarPowerCfg1:2;
uint64_t Reserved3:6;
uint64_t RadarState_SensorID:3;
uint64_t Reserved4:1;
uint64_t RadarState_SortIndex:3;
uint64_t RadarState_RadarPowerCfg2:1;
uint64_t Reserved5:1;
uint64_t RadarState_CtrlRelayCfg:1;
uint64_t RadarState_OutputTypeCfg:2;
uint64_t RadarState_SendQualityCfg:1;
uint64_t RadarState_SendExtInfoCfg:1;
uint64_t RadarState_MotionRxState:2;
uint64_t Reserved6:8;
uint64_t Reserved7:2;
uint64_t RadarState_RCS_Threshold:3;
uint64_t Reserved8:3;
} data = {};
uint8_t raw_data[8];
} radar_state;
}
- 定义RadarState类
namespace radar_state {
class RadarState {
public:
RadarState();
~RadarState();
bool get_read_status(); //启动时从 NVM 中读取配置参数的结果状态
bool get_write_status(); //将配置参数保存到 NVM 中的结果状态
uint64_t get_max_distance(); //当前far scan最大距离的配置参数
bool get_persistent_error_status(); //检测到复位后可能不会消失的内部错误
bool get_interference_status(); //检测到与另一个雷达传感器的干扰
bool get_temperature_error_status(); //如果温度低于或高于定义的范围,错误将激活。离开后会自动退出
bool get_temporary_error_status(); //检测到传感器复位后最有可能消失的临时错误
bool get_voltage_error_status(); //如果工作电压低于或高于规定范围5秒以上,则错误将激活
int get_sensor_id(); //当前传感器ID (0-7)
int get_sort_index(); //当前目标列表的排序方式0x0: no sorting 0x1: sorted by range 0x2: sorted by RCS
int get_radar_power_cfg(); //当前雷达发射功率的参数配置0x0: Standard 0x1: -3dB Tx gain 0x2: -6dB Tx gain 0x3: -9dB Tx gain
bool get_ctrl_relay_cfg(); //0x0: inactive 0x1: active
int get_output_type_cfg(); //当前输出模式为Clusters 或者Objects
bool get_send_quality_cfg(); //0x0: inactive 0x1: active
bool get_ext_info_cfg(); //0x0: inactive 0x1: active
int get_motion_rx_state(); //显示速度和角速度输入信号的状态,0x0: input ok 0x1: speed missing 0x2: yaw rate missing 0x3: speed and yaw rate missing
int get_rcs_threshold(); //0x0 Standard 0x1 High sensitivity
radar_state *get_radar_state();
private:
radar_state radar_state_msg;
};
}
- RadarState类的实现
namespace radar_state {
RadarState::RadarState() {
}
RadarState::~RadarState() {
}
bool RadarState::get_read_status() {
return static_cast<bool>(radar_state_msg.data.RadarState_NVMReadStatus);
}
bool RadarState::get_write_status() {
return static_cast<bool>(radar_state_msg.data.RadarState_NVMwriteStatus);
}
uint64_t RadarState::get_max_distance() {
return (radar_state_msg.data.RadarState_MaxDistanceCfg1 << 2 |
radar_state_msg.data.RadarState_MaxDistanceCfg2) * 2;
} //数据在Union的存储位置是二进制位中的22-23位(cfg2),8-15位(cfg1),取数据时是cfg1和cfg2的拼接结果*2
bool RadarState::get_persistent_error_status() {
return static_cast<bool>(radar_state_msg.data.RadarState_Persistent_Error);
}
bool RadarState::get_interference_status() {
return static_cast<bool>(radar_state_msg.data.RadarState_Interference);
}
bool RadarState::get_temperature_error_status() {
return static_cast<bool>(radar_state_msg.data.RadarState_Temperature_Error);
}
bool RadarState::get_temporary_error_status() {
return static_cast<bool>(radar_state_msg.data.RadarState_Temporary_Error);
}
bool RadarState::get_voltage_error_status() {
return static_cast<bool>(radar_state_msg.data.RadarState_Voltage_Error);
}
int RadarState::get_sensor_id() {
return static_cast<int>(radar_state_msg.data.RadarState_SensorID);
}
int RadarState::get_sort_index() {
return static_cast<int>(radar_state_msg.data.RadarState_SortIndex);
}
int RadarState::get_radar_power_cfg() {
return static_cast<int>((radar_state_msg.data.RadarState_RadarPowerCfg1 << 1)
| radar_state_msg.data.RadarState_RadarPowerCfg2);
}
bool RadarState::get_ctrl_relay_cfg() {
return static_cast<bool>(radar_state_msg.data.RadarState_CtrlRelayCfg);
}
int RadarState::get_output_type_cfg() {
return static_cast<int>(radar_state_msg.data.RadarState_OutputTypeCfg);
}
bool RadarState::get_send_quality_cfg() {
return static_cast<bool>(radar_state_msg.data.RadarState_SendQualityCfg);
}
bool RadarState::get_ext_info_cfg() {
return static_cast<bool>(radar_state_msg.data.RadarState_SendExtInfoCfg);
}
int RadarState::get_motion_rx_state() {
return static_cast<int>(radar_state_msg.data.RadarState_MotionRxState);
}
int RadarState::get_rcs_threshold() {
return static_cast<int>(radar_state_msg.data.RadarState_RCS_Threshold);
}
radar_state *RadarState::get_radar_state() {
return &radar_state_msg;
}
}
3、Motion Input Signals部分
-
传感器接收输入信号 0x300 和 0x301,但在没有这两部分信号信息的的情况下仍能正常工作。超时***500ms***后,传感器将其默认为以下状态:
- Speed 0 m/s 和 standstill
- Yaw rate 0 deg/s
-
每条消息都有独立的超时监听。超时状态反映在信号***RadarState_MotionRxState (0x201)*** 中。
-
输入信号用于评估车辆行驶路线,并用于确定检测到的 Clusters 和 Objects 的移动。
- 定义用于存储数据的Union共用体和enum变量
namespace motion_input_signals {
typedef union speed_information {
struct {
uint64_t RadarDevice_Speed1:5;
uint64_t Reserved:1;
uint64_t RadarDevice_SpeedDirection:2;
uint64_t RadarDevice_Speed2:8;
} data = {};
uint8_t raw_data[2];
} speed_information;
typedef enum RadarDevice_SpeedDirection { //指示雷达移动的方向,参照前进方向
STANDSTILL = 0x0,
FORWARD = 0x1,
BACKWARD = 0x2,
} RadarDevice_SpeedDirection;
typedef union yaw_rate_information { //参照前进方向角速度的变化率。假设旋转中心位于传感器后面1.95 m处。
struct {
uint64_t RadarDevice_YawRate1:8;
uint64_t RadarDevice_YawRate2:8;
} data = {};
uint8_t raw_data[2];
} yaw_rate_information;
}
- ***SpeedInformation***类和***YawRateInformation***类的定义
namespace motion_input_signals {
class SpeedInformation {
public:
SpeedInformation();
~SpeedInformation();
void set_speed(double speed);
void set_speed_direction(RadarDevice_SpeedDirection direction);
speed_information *get_speed_information();
private:
speed_information speed_information_msg;
};
class YawRateInformation {
public:
YawRateInformation();
~YawRateInformation();
void set_yaw_rate(double yaw_rate);
yaw_rate_information *get_yaw_rate_information();
private:
speed_information speed_information_msg;
yaw_rate_information yaw_rate_information_msg;
};
}
- 类的实现
namespace motion_input_signals {
SpeedInformation::SpeedInformation() {
}
SpeedInformation::~SpeedInformation() {
}
void SpeedInformation::set_speed(double speed) {
int radar_speed = static_cast<int>(speed / 0.02); //表中Res为0.02
speed_information_msg.data.RadarDevice_Speed1 = static_cast<uint64_t>(radar_speed >> 8); //存储位置方向从8-15位,0-4位。>>8表示取出数据中的高位部分,存储到0-4位;
speed_information_msg.data.RadarDevice_Speed2 = static_cast<uint64_t>(radar_speed & 255); //&255表示取出数据低位的8位数据,存储到8-15位。
}
void SpeedInformation::set_speed_direction(RadarDevice_SpeedDirection direction) {
speed_information_msg.data.RadarDevice_SpeedDirection = direction;
}
speed_information *SpeedInformation::get_speed_information() {
return &speed_information_msg;
}
YawRateInformation::YawRateInformation() {
}
YawRateInformation::~YawRateInformation() {
}
void YawRateInformation::set_yaw_rate(double yaw_rate) {
int radar_yaw_rate = static_cast<int>((yaw_rate + 327.68) / 0.01);//表中Offset为 +327.68,Res为0.01
yaw_rate_information_msg.data.RadarDevice_YawRate1 = static_cast<uint64_t>(radar_yaw_rate >> 8); //数据存储位置从8-15位,0-8位。 >>8表示取出数据的取出8二进制位之前的高位数据,存储到0-8位;
yaw_rate_information_msg.data.RadarDevice_YawRate2 = static_cast<uint64_t>(radar_yaw_rate & 255); //&255表示取出数据的低8位部分,存储到8-15位。
}
yaw_rate_information *YawRateInformation::get_yaw_rate_information() {
return &yaw_rate_information_msg;
}
}
4、Cluster List部分
- 首先基于对象的反射信号创建簇(clusters)。每个粒子将被检测为簇。最近的粒子将是第一个被检测到并被带到结合点的粒子。随着集群(clusters)数量的增加,距离也会增加。
- 如果在信号***RadarCfg_OutputType*** (0x200) 中选择了***clusters*** 模式,Cluster list的输出由三种消息定义,这些消息以固定间隔(大约70-80 ms)发送。
- Cluster_0_Status (0x600) — 第一部分消息包含列表头信息,即之后要发送的近扫描clusters 的数目和远扫描 clusters 的数目;
- Cluster_1_General (0x701) — 此消息包含 clusters 的位置和速度,并针对所有检测到的 clusters 重复发送(首先是近扫描,然后是远扫描)。两个集群列表中的每一个都是距离排序的。 如果超过 250 个 clusters,则只发送前 250 个 clusters。
- Cluster_2_Quality (0x702) — 此消息包含 clusters 的质量信息,并且仅当它在信号***RadarCfg_SendQuality*** (0x200) 中被激活时才会发送。它以与消息 Cluster_1_General (0x701) 相同的方式为所有 clusters 重复发送。
- 如果发送质量信息,首先发送所有类型为 Cluster_1_General (0x701) 的消息,然后发送所有类型为 Cluster_2_Quality (0x702) 的消息。
4.1、Cluster list status (0x600)
- 这部分包含 cluster 列表头信息,作为 cluster 列表输出的第一条消息发送,且每个测量周期仅发送一次。
- 定义用于存储数据的Union
namespace cluster_list {
typedef union cluster_0_status {
struct {
uint64_t Cluster_NofClustersNear:8;
uint64_t Cluster_NofClustersFar:8;
uint64_t Cluster_MeasCounter1:8;
uint64_t Cluster_MeasCounter2:8;
uint64_t Reserved:4;
uint64_t Cluster_InterfaceVersion:4;
} data = {};
uint8_t raw_data[5];
} cluster_0_status;
}
- 定义Cluster_0_Status类
namespace cluster_list {
class Cluster_0_Status {
public:
Cluster_0_Status();
~Cluster_0_Status();
int get_no_of_clusters_near(); //获取近扫描点数
int get_no_of_clusters_far(); //获取远扫描点数。近扫和远扫一起最多250个clusters。如何激活quality模块,为避免CAN总线超限,将最大 clusters数量限制为 125
int get_measurement_cycle_counter(); //获取测量周期计数,从传感器启动开始向上计数,当 > 65535 时从 0 重新开始
int get_interface_version(); //Cluster列表 CAN 接口版本号。在未更改Cluster标识符之前,它始终为“1”
cluster_0_status *get_cluster_0_status();
private:
cluster_0_status cluster_0_status_msg;
};
}
- Cluster_0_Status类的实现
namespace cluster_list {
Cluster_0_Status::Cluster_0_Status() {
}
Cluster_0_Status::~Cluster_0_Status() {
}
int Cluster_0_Status::get_no_of_clusters_near() {
return static_cast<int>(cluster_0_status_msg.data.Cluster_NofClustersNear);
}
int Cluster_0_Status::get_no_of_clusters_far() {
return static_cast<int>(cluster_0_status_msg.data.Cluster_NofClustersFar);
}
int Cluster_0_Status::get_measurement_cycle_counter() {
return static_cast<int>(cluster_0_status_msg.data.Cluster_MeasCounter1 << 8
| cluster_0_status_msg.data.Cluster_MeasCounter2);
} // <<8 表示获取数据8位以外的高位部分, | MeasCounter2表示获取数据的后8位
int Cluster_0_Status::get_interface_version() {
return static_cast<int>(cluster_0_status_msg.data.Cluster_InterfaceVersion);
}
cluster_0_status *Cluster_0_Status::get_cluster_0_status() {
return &cluster_0_status_msg;
}
}
4.2、Cluster general information (0x701)
- 该消息包含 clusters 的位置和速度,并针对所有检测到的 clusters 重复发送(首先是近扫描,然后是远扫描)。 两个集群列表中的每一个都是距离排序的。 如果超过 250 个clusters,则只发送前 250 个clusters。
- 定义用于存储数据的Union
namespace cluster_list {
typedef union cluster_1_general {
struct {
uint64_t Cluster_ID:8;
uint64_t Cluster_DistLong1:8;
uint64_t Cluster_DistLat1:2;
uint64_t Reserved:1;
uint64_t Cluster_DistLong2:5;
uint64_t Cluster_DistLat2:8;
uint64_t Cluster_VrelLong1:8;
uint64_t Cluster_VrelLat1:6;
uint64_t Cluster_VrelLong2:2;
uint64_t Cluster_DynProp:3;
uint64_t Reserved2:2;
uint64_t Cluster_VrelLat2:3;
uint64_t Cluster_RCS:8;
} data = {};
uint8_t raw_data[8];
} cluster_1_general;
}
- 定义 Cluster_1_General类
namespace cluster_list {
class Cluster_1_General {
public:
Cluster_1_General();
~Cluster_1_General();
int get_cluster_id(); //获取 Cluster number
double get_cluster_long_dist(); //获取Longitudinal(x)坐标 单位:m
double get_cluster_lat_dist(); //获取Lateral(y)坐标 单位:m
double get_cluster_long_rel_vel(); //获取 x 方向的相对速度 单位:m/s
double get_cluster_lat_rel_vel(); //获取 y 方向的相对速度,该值恒置为0 单位:m/s
int get_cluster_dyn_prop(); //获取cluster的动态属性,来表示其是否在移动。0x0:moving 0x1:stationary 0x2:oncoming 0x3:stationary candidate 0x4:unknown 0x5:crossing stationary 0x6:crossing moving 0x7:stopped
double get_cluster_rcs(); //RCS(Radar cross section)雷达散射截面 单位:dBm2
cluster_1_general *get_cluster_1_general();
private:
cluster_1_general cluster_1_general_msg;
};
}
- Cluster_1_General类实现
namespace cluster_list {
Cluster_1_General::Cluster_1_General() {
}
Cluster_1_General::~Cluster_1_General() {
}
int Cluster_1_General::get_cluster_id() {
return static_cast<int>(cluster_1_general_msg.data.Cluster_ID);
}
double Cluster_1_General::get_cluster_long_dist() {
return (cluster_1_general_msg.data.Cluster_DistLong1 << 5 |
cluster_1_general_msg.data.Cluster_DistLong2) * 0.2 - 500.0;
} //存储位置为19-23位,8-15位。<<5取的是数据8-15位的高位部分,| 取的是数据19-23位的低位部分。Offset为 -500,Res为 0.2。
double Cluster_1_General::get_cluster_lat_dist() {
return (cluster_1_general_msg.data.Cluster_DistLat1 << 8 |
cluster_1_general_msg.data.Cluster_DistLat2) * 0.2 - 102.3;
} //存储位置为24-31位,16-17位。<<8取的是数据16-17位的高位部分,| 取的是数据24-31位的低位部分。Offset为 -102.3,Res为 0.2。
double Cluster_1_General::get_cluster_long_rel_vel() {
return (cluster_1_general_msg.data.Cluster_VrelLong1 << 2 |
cluster_1_general_msg.data.Cluster_VrelLong2) * 0.25 - 128.0;
} //存储位置为46-47位,32-39位。<<2取的是数据32-39位的高位部分,| 取的是数据46-47位的低位部分。Offset为 -128.00,Res位 0.25。
double Cluster_1_General::get_cluster_lat_rel_vel() {
return (cluster_1_general_msg.data.Cluster_VrelLat1 << 3 |
cluster_1_general_msg.data.Cluster_VrelLat2) * 0.25 - 64.0;
} //存储位置为53-55位,40-45位。<<3取的是数据40-45位的高位部分,| 取的是数据53-55位的低位部分。Offset为 -64.00,Res位 0.25。
int Cluster_1_General::get_cluster_dyn_prop() {
return static_cast<int>(cluster_1_general_msg.data.Cluster_DynProp);
}
double Cluster_1_General::get_cluster_rcs() {
return cluster_1_general_msg.data.Cluster_RCS * 0.5 - 64.0;
} //Offset为 -64.0,Res为 0.5。
cluster_1_general *Cluster_1_General::get_cluster_1_general() {
return &cluster_1_general_msg;
}
}
4.3、Cluster quality information (0x702)
- 该消息包含 clusters 的质量信息,只有在信号***RadarCfg_SendQuality*** (0x200) 中激活时才发送。它以与消息***Cluster_1_General*** (0x701)相同的方式为所有 clusters 重复发送。如果此消息被激活,则必须通过 filter 或 environment 将最大 clusters 数量限制为 125。
- 定义用于存储数据的 Union
namespace cluster_list {
typedef union cluster_2_quality {
struct {
uint64_t Cluster_ID:8;
uint64_t Cluster_DistLat_rms1:3;
uint64_t Cluster_DistLong_rms:5;
uint64_t Cluster_VrelLat_rms1:1;
uint64_t Cluster_VrelLong_rms:5;
uint64_t Cluster_DistLat_rms2:2;
uint64_t Cluster_Pdh0:3;
uint64_t Reserved:1;
uint64_t Cluster_VrelLat_rms2:4;
uint64_t Cluster_AmbigState:3;
uint64_t Cluster_InvalidState:5;
} data = {};
uint8_t raw_data[5];
} cluster_2_quality;
}
- 定义 Cluster_2_Quality类
namespace cluster_list {
class Cluster_2_Quality {
public:
Cluster_2_Quality();
~Cluster_2_Quality();
int get_cluster_id(); //获取 Cluster number
double get_cluster_long_dist_rms(); //获取Longitudinal(x)坐标标准差 单位:m
double get_cluster_long_rel_vel_rms(); //获取 x 方向的相对速度的标准差 单位:m/s
double get_cluster_lat_dist_rms(); //获取Lateral(y)坐标标准差 单位:m
int get_cluster_pdh0(); //获取Cluster的虚警概率,(即由多径或类似引起的虚假的概率)
double get_cluster_lat_rel_vel_rms(); //获取 y 方向的相对速度的标准差 单位:m/s
int get_cluster_ambiguity_state(); //获取多普勒(径向速度)模糊解的状态
int get_cluster_validity_state(); //获取Cluster有效性的状态
cluster_2_quality *get_cluster_2_quality();
private:
cluster_2_quality cluster_2_quality_msg;
double signal_value_table[32] = {
0.005, 0.006, 0.008, 0.011,
0.014, 0.018, 0.023, 0.029,
0.038, 0.049, 0.063, 0.081,
0.105, 0.135, 0.174, 0.224,
0.288, 0.371, 0.478, 0.616,
0.794, 1.023, 1.317, 1.697,
2.187, 2.817, 3.630, 4.676,
6.025, 7.762, 10.000
}; //(0x702)中Cluster_DistLong_rms, Cluster_DistLat_rms [m] Cluster_VrelLong_rms, Cluster_VrelLat_rms [m/s]的信号值表
};
}
5、Object List部分
-
Objects是由雷达构建的第二个元素(the history of the clusters)。换句话说,objects是我们感兴趣的真正主体,可以定义为一连串反射信号的合成。最近的Object将首先建立,以此类推。随着objects数量的增加,距离也在增加。
-
如果在信号***RadarCfg_OutputType*** (0x200) 中选择了***objects*** 模式,Object list的输出由五种消息定义,这些消息以固定间隔发送。
- Object_0_Status (0x60A) — 第一部分消息包含列表头信息,即之后要发送的 objects的数目;
- Object_1_General (0x60B) — 此消息包含 objects 的位置和速度,并为所有被跟踪的 objects 重复发送。
- Object_2_Quality (0x60C) — 此消息包含 objects 的质量信息,并且仅当它在信号***RadarCfg_SendQuality*** (0x200) 中被激活时才会发送。它以与消息 Object_1_General (0x60B) 相同的方式为所有 objects 重复发送。
- Object_3_Extended (0x60D) — 此消息包含 object 的扩展属性,并且仅当它在信号***RadarCfg_SendExtInfo*** (0x200) 中被激活时才会发送。它以与消息 Object_1_General (0x60B) 相同的方式为所有 objects 重复发送。
- Object_4_Warning (0x60E) — 此消息包含碰撞检测警告状态,仅当碰撞检测在消息 CollDetCfg (0 x400) 中被激活时发送。它以与消息 Object_1_General (0x60B) 相同的方式为所有 objects 重复发送。
- 如果发送质量信息、扩展信息和/或警告状态,首先发送所有类型为***Object_1_General*** (0x60B)的消息,然后发送所有类型为***Object_2_Quality*** (0x60C)的消息,然后发送类型为***Object_3_Extended*** (0x60D)的消息和/或之后发送类型为***Object_4_Warning*** (0x60E)的消息。
5.1、Object list status (0x60A)
- 消息***Object_0_Status*** (0x60A)包含 object 列表头信息,并作为 cluster 列表输出的第一个消息发送,并且每个测量周期只发送一次。
- 定义用于存储数据的Union
namespace object_list {
typedef union object_0_status {
struct {
uint64_t Object_NofObjects:8;
uint64_t Object_MeasCounter1:8;
uint64_t Object_MeasCounter2:8;
uint64_t Reserved:4;
uint64_t Object_InterfaceVersion:4;
} data = {};
uint8_t raw_data[4];
} object_0_status;
}
- 定义 Object_0_Status 类
namespace object_list {
class Object_0_Status {
public:
Object_0_Status();
~Object_0_Status();
int get_no_of_objects(); //获取objects的数量(最大为100)
int get_measurement_cycle_counter(); //获取测量周期计数,从传感器启动开始向上计数,当 > 65535 时从 0 重新开始
int get_interface_version(); //Object列表 CAN 接口版本号。在未更改Object标识符之前,它始终为“1”。
object_0_status *get_object_0_status();
private:
object_0_status object_0_status_msg;
};
}
- Object_0_Status 类的实现
namespace object_list {
Object_0_Status::Object_0_Status() {
}
Object_0_Status::~Object_0_Status() {
}
int Object_0_Status::get_no_of_objects() {
return static_cast<int>(object_0_status_msg.data.Object_NofObjects);
}
int Object_0_Status::get_measurement_cycle_counter() {
return static_cast<int>(object_0_status_msg.data.Object_MeasCounter1 << 8
| object_0_status_msg.data.Object_MeasCounter2);
} //存储位置从18-23位,8-15位。 <<8得到的是8位以外的高位数据,| 得到的是低8位数据
int Object_0_Status::get_interface_version() {
return static_cast<int>(object_0_status_msg.data.Object_InterfaceVersion);
}
object_0_status *Object_0_Status::get_object_0_status() {
return &object_0_status_msg;
}
}
5.2、Object general information (0x60B)
- 此消息包含 objects 的位置和速度,并为所有被跟踪的 objects 重复发送。
- 定义用于存储数据的Union
namespace object_list {
typedef union object_1_general {
struct {
uint64_t Object_ID:8;
uint64_t Object_DistLong1:8;
uint64_t Object_DistLat1:3;
uint64_t Object_DistLong2:5;
uint64_t Object_DistLat2:8;
uint64_t Object_VrelLong1:8;
uint64_t Object_VrelLat1:6;
uint64_t Object_VrelLong2:2;
uint64_t Object_DynProp:3;
uint64_t Reserved:2;
uint64_t Object_VrelLat2:3;
uint64_t Object_RCS:8;
} data = {};
uint8_t raw_data[8];
} object_1_general;
}
- 定义 Object_1_General 类
namespace object_list {
class Object_1_General {
public:
Object_1_General();
~Object_1_General();
int get_object_id(); //ObjectID(因为objects是被跟踪的,所以ID会在整个测量周期中保持,并且不必是连续的)
double get_object_long_dist(); //获取Longitudinal(x)坐标 单位:m
double get_object_lat_dist(); //获取Lateral(y)坐标 单位:m
double get_object_long_rel_vel(); //获取Longitudinal(x)方向相对速度 单位:m/s
int get_object_dyn_prop(); //object的动态属性,表示object是运动的还是静止的(只有在正确给出speed和yaw rate时,才能正确确定该值)。0x0:moving 0x1:stationary 0x2:oncoming 0x3:stationary candidate 0x4:unknown 0x5:crossing stationary 0x6:crossing moving 0x7:stopped
double get_object_lat_rel_vel(); //获取Lateral(y)方向相对速度 单位:m/s
double get_object_rcs(); //RCS(Radar cross section)雷达散射截面 单位:dBm2
object_1_general *get_object_1_general();
private:
object_1_general object_1_general_msg;
};
}
- Object_1_General 类的实现
namespace object_list {
Object_1_General::Object_1_General() {
}
Object_1_General::~Object_1_General() {
}
int Object_1_General::get_object_id() {
return static_cast<int>(object_1_general_msg.data.Object_ID);
}
double Object_1_General::get_object_long_dist() {
return (object_1_general_msg.data.Object_DistLong1 << 5 |
object_1_general_msg.data.Object_DistLong2) * 0.2 - 500.0;
} //Offset为 -500,Res为 0.2
double Object_1_General::get_object_lat_dist() {
return (object_1_general_msg.data.Object_DistLat1 << 8 |
object_1_general_msg.data.Object_DistLat2) * 0.2 - 204.6;
} //Offset为 -204.6,Res为 0.2
double Object_1_General::get_object_long_rel_vel() {
return (object_1_general_msg.data.Object_VrelLong1 << 2 |
object_1_general_msg.data.Object_VrelLong2) * 0.25 - 128.0;
} //Offset为 -128.0,Res为 0.25
double Object_1_General::get_object_lat_rel_vel() {
return (object_1_general_msg.data.Object_VrelLat1 << 3 |
object_1_general_msg.data.Object_VrelLat2) * 0.25 - 64.0;
} //Offset为 -64.0,Res为 0.25
int Object_1_General::get_object_dyn_prop() {
return static_cast<int>(object_1_general_msg.data.Object_DynProp);
}
double Object_1_General::get_object_rcs() {
return object_1_general_msg.data.Object_RCS * 0.5 - 64.0;
} //Offset为 -64,Res为 0.5
object_1_general *Object_1_General::get_object_1_general() {
return &object_1_general_msg;
}
}
5.3、Object quality information (0x60C)
- 此消息包含 objects 的质量信息,并且仅当它在信号***RadarCfg_SendQuality*** (0x200) 中被激活时才会发送。它以与消息 Object_1_General (0x60B) 相同的方式为所有 objects 重复发送。
- 定义用于存储数据的Union
namespace object_list {
typedef union object_2_quality {
struct {
uint64_t Obj_ID:8;
uint64_t Obj_DistLat_rms1:3;
uint64_t Obj_DistLong_rms:5;
uint64_t Obj_VrelLat_rms1:1;
uint64_t Obj_VrelLong_rms:5;
uint64_t Obj_DistLat_rms2:2;
uint64_t Obj_ArelLong_rms1:4;
uint64_t Obj_VrelLat_rms2:4;
uint64_t Obj_Orientation_rms1:2;
uint64_t Obj_ArelLat_rms:5;
uint64_t Obj_ArelLong_rms2:1;
uint64_t Reserved1:5;
uint64_t Obj_Orientation_rms2:3;
uint64_t Reserved2:2;
uint64_t Obj_MeasState:3;
uint64_t Obj_ProbOfExist:3;
} data = {};
uint8_t raw_data[8];
} object_2_quality;
}
- 定义 Object_2_Quality 类
namespace object_list {
class Object_2_Quality {
public:
Object_2_Quality();
~Object_2_Quality();
int get_object_id();
double get_object_long_dist_rms(); //获取Longitudinal(x)坐标标准差 单位:m
double get_object_long_rel_vel_rms(); //获取 x 方向的相对速度的标准差 单位:m/s
double get_object_lat_dist_rms(); //获取Lateral(y)坐标标准差 单位:m
double get_object_lat_rel_vel_rms(); //获取 y 方向的相对速度的标准差 单位:m/s
double get_object_long_rel_accel_rms(); //获取 x 方向的相对加速度的标准差 单位:m/s2
double get_object_lat_rel_accel_rms(); //获取 y 方向的相对加速度的标准差 单位:m/s2
double get_object_orientation_rms(); //获取方位角标准差 单位:deg
int get_object_meas_state(); //测量状态:在新的测量周期内 object 是否有效,是否被 clusters 确认。0x0:deleted 0x1:new 0x2:measured 0x3: predicted 0x4:deleted for merge 0x5:new from merge
int get_object_prob_of_exist(); //存在的概率。0x0:invalid 0x1:<25% 0x2:<50% 0x3:<75% 0x4:<90% 0x5:<99% 0x6:<99.9% 0x7:<=100%
object_2_quality *get_object_2_quality();
private:
object_2_quality object_2_quality_msg;
double signal_value_table[32] = {
0.005, 0.006, 0.008, 0.011,
0.014, 0.018, 0.023, 0.029,
0.038, 0.049, 0.063, 0.081,
0.105, 0.135, 0.174, 0.224,
0.288, 0.371, 0.478, 0.616,
0.794, 1.023, 1.317, 1.697,
2.187, 2.817, 3.630, 4.676,
6.025, 7.762, 10.000
}; //Obj_Orientation_rms[deg]的信号值表
double orientation_signal_value_table[32] = {
0.005, 0.007, 0.010, 0.014,
0.020, 0.029, 0.041, 0.058,
0.082, 0.116, 0.165, 0.234,
0.332, 0.471, 0.669, 0.949,
1.346, 1.909, 2.709, 3.843,
5.451, 7.734, 10.971, 15.565,
22.081, 31.325, 44.439, 63.044,
89.437, 126.881, 180.000
}; //Obj_DistLong_rms, Obj_DistLat_rms [m] Obj_VrelLong_rms, Obj_VrelLat_rms [m/s] Obj_ArelLat_rms, Obj_ArelLong_rms [m/s2]信号值表
};
}
- Object_2_Quality 类的实现
namespace object_list {
Object_2_Quality::Object_2_Quality() {
}
Object_2_Quality::~Object_2_Quality() {
}
int Object_2_Quality::get_object_id() {
return static_cast<int>(object_2_quality_msg.data.Obj_ID);
}
double Object_2_Quality::get_object_lat_dist_rms() {
return signal_value_table[static_cast<int>(object_2_quality_msg.data.Obj_DistLat_rms1 << 2 |
object_2_quality_msg.data.Obj_DistLat_rms2)];
} //存储位置从22-23位,8-10位。 <<2取的是高位部分(8-10位)数据,| rms2取的是剩下的2位(22-23位)数据
double Object_2_Quality::get_object_long_dist_rms() {
return signal_value_table[static_cast<int>(object_2_quality_msg.data.Obj_DistLong_rms)];
}
double Object_2_Quality::get_object_lat_rel_vel_rms() {
return signal_value_table[static_cast<int>(
object_2_quality_msg.data.Obj_VrelLat_rms1 << 4
| object_2_quality_msg.data.Obj_VrelLat_rms2)];
} //存储位置从28-31位,16位。<<4取的是高位部分16位数据,| rms2取的是剩下的4位(28-32位)数据
double Object_2_Quality::get_object_long_rel_vel_rms() {
return signal_value_table[static_cast<int>(object_2_quality_msg.data.Obj_VrelLong_rms)];
}
double Object_2_Quality::get_object_long_rel_accel_rms() {
return signal_value_table[static_cast<int>(object_2_quality_msg.data.Obj_ArelLong_rms1 << 1 |
object_2_quality_msg.data.Obj_ArelLong_rms2)];
} //存储位置从39位,24-27位。<<1取的是高位部分(24-27位)数据,| rms2取的是剩下的低位(39位)的数据
double Object_2_Quality::get_object_lat_rel_accel_rms() {
return signal_value_table[static_cast<int>(object_2_quality_msg.data.Obj_ArelLat_rms)];
}
int Object_2_Quality::get_object_meas_state() {
return static_cast<int>(object_2_quality_msg.data.Obj_MeasState);
}
int Object_2_Quality::get_object_prob_of_exist() {
return static_cast<int>(object_2_quality_msg.data.Obj_ProbOfExist);
}
double Object_2_Quality::get_object_orientation_rms() {
return orientation_signal_value_table[
static_cast<int>(object_2_quality_msg.data.Obj_Orientation_rms1 << 3 |
object_2_quality_msg.data.Obj_Orientation_rms2)];
} //存储位置从45-47位,32-33位。<<3取的是高位部分(32-33位)的数据,| rms2取的是剩下的低位(45-47位)的数据。
object_2_quality *Object_2_Quality::get_object_2_quality() {
return &object_2_quality_msg;
}
}
5.4、Object extended information (0x60D)
- 此消息包含 object 的扩展属性,并且仅当它在信号***RadarCfg_SendExtInfo*** (0x200) 中被激活时才会发送。它以与消息 Object_1_General (0x60B) 相同的方式为所有 objects 重复发送。
- 定义用于存储数据的Union
namespace object_list {
typedef union object_3_extended {
struct {
uint64_t Object_ID:8;
uint64_t Object_ArelLong1:8;
uint64_t Object_ArelLat1:5;
uint64_t Object_ArelLong2:3;
uint64_t Object_Class:3;
uint64_t Reserved:1;
uint64_t Object_ArelLat2:4;
uint64_t Object_OrientationAngle1:8;
uint64_t Reserved2:6;
uint64_t Object_OrientationAngle2:2;
uint64_t Object_Length:8;
uint64_t Object_Width:8;
} data = {};
uint8_t raw_data[8];
} object_3_extended;
}
- 定义 Object_3_Extended 类
namespace object_list {
class Object_3_Extended {
public:
Object_3_Extended();
~Object_3_Extended();
int get_object_id();
double get_object_long_rel_accel(); //获取 x 方向的相对加速度 单位:m/s2
double get_object_lat_rel_accel(); //获取 y 方向的相对加速度,该值恒置为0 单位:m/s2
int get_object_class(); //获取目标类别,0x0:point 0x1:car 0x2:truck 0x3:not in use 0x4:motorcycle 0x5:bicycle 0x6:wide 0x7:reserved
double get_object_orientation_angle(); //获取object的方位角。随着时间的推移,被追踪的障碍物的旋转运动所产生的角度变化。这个值的创建总是从“0”开始,并随着障碍物的旋转而增加。如果没有发生旋转,它将保持“0”。 单位:deg
double get_object_length(); //获取被跟踪object的长度 单位:m
double get_object_width(); //获取被跟踪object的宽度 单位:m
object_3_extended *get_object_3_extended();
private:
object_3_extended object_3_extended_msg;
};
}
- Object_3_Extended 类的实现
namespace object_list {
Object_3_Extended::Object_3_Extended() {
}
Object_3_Extended::~Object_3_Extended() {
}
int Object_3_Extended::get_object_id() {
return static_cast<int>(object_3_extended_msg.data.Object_ID);
}
double Object_3_Extended::get_object_long_rel_accel() {
return (object_3_extended_msg.data.Object_ArelLong1 << 3 |
object_3_extended_msg.data.Object_ArelLong2) * 0.01 - 10.0;
} //存储位置从21-23位,8-15位。<<3取的是高位部分(8-15位)数据,| Long2取的是剩下的低位部分(21-23位)数据。Offset为 -10.0,Res为 0.01
double Object_3_Extended::get_object_lat_rel_accel() {
return (object_3_extended_msg.data.Object_ArelLat1 << 4 |
object_3_extended_msg.data.Object_ArelLat2) * 0.01 - 2.50;
} //存储位置从28-31位,16-20位。<<4取的是高位部分(16-20位)数据,| Long2取的是剩下的低位部分(28-31位)数据。Offset为 -2.50,Res为 0.01
double Object_3_Extended::get_object_orientation_angle() {
return (object_3_extended_msg.data.Object_OrientationAngle1 << 2 |
object_3_extended_msg.data.Object_OrientationAngle2) * 0.4 - 180.0;
} //存储位置从46-47位,32-39位。<<2取的是高位部分(32-39位)数据,| Long2取的是剩下的低位部分(46-47位)数据。Offset为 -180.00,Res为 0.4
int Object_3_Extended::get_object_class() {
return static_cast<int>(object_3_extended_msg.data.Object_Class);
}
double Object_3_Extended::get_object_length() {
return object_3_extended_msg.data.Object_Length * 0.2;
} //Res为 0.2
double Object_3_Extended::get_object_width() {
return object_3_extended_msg.data.Object_Width * 0.2;
} //Res为 0.2
object_3_extended *Object_3_Extended::get_object_3_extended() {
return &object_3_extended_msg;
}
}
5.5、Object collision detection warning (0x60E)
- 此消息包含碰撞检测警告状态,仅当碰撞检测在消息 CollDetCfg (0 x400) 中被激活时发送。它以与消息 Object_1_General (0x60B) 相同的方式为所有 objects 重复发送。
6、利用SocketCAN接收数据并存储及协议解析
-
之前已经提到过,ARS_408毫米波雷达利用CAN口进行数据传输。前一部分已经实现了利用SocketCAN类来接收CAN口的数据,这部分将会把从CAN口接收的数据交由各部分协议进行处理,完成两部分的拼接工作。
-
创建ars_40X_can.hpp文件
- 引入SocketCAN类以及各个协议的头文件
- 由于后续的数据是根据CAN messages的类型进行选择处理的,因此还需要定义enum类型的can_messages变量
- 定义封装Socket接口及雷达协议的接口类:ARS_40X_CAN
#ifndef ARS_40X_ARS_40X_HPP
#define ARS_40X_ARS_40X_HPP
#include <socket_can/socket_can.hpp> //使用SocketCAN进行CAN总线通信
#include "ars_40X/cluster_list.hpp" //解析雷达的cluster模式数据
#include "ars_40X/motion_input_signals.hpp" //雷达的运动输入信号
#include "ars_40X/object_list.hpp" //解析雷达的object模式数据
#include "ars_40X/radar_cfg.hpp" //雷达配置信息
#include "ars_40X/radar_state.hpp" //雷达状态信息
#include <cstdint>
#include <string>
#include <iostream>
namespace ars_40X {
typedef enum can_messages { //参照传感器 CAN messages表(传感器ID为 0)
RadarCfg = 0x200,
RadarState = 0x201,
FilterCfg = 0x202,
FilterState_Header = 0x203,
FilterState_Cfg = 0x204,
CollDetCfg = 0x400,
CollDetRegionCfg = 0x401,
CollDetState = 0x408,
CollDetRegionState = 0x402,
SpeedInformation = 0x300,
YawRateInformation = 0x301,
Cluster_0_Status = 0x600,
Cluster_1_General = 0x701,
Cluster_2_Quality = 0x702,
Object_0_Status = 0x60A,
Object_1_General = 0x60B,
Object_2_Quality = 0x60C,
Object_3_Extended = 0x60D,
Object_4_Warning = 0x60E,
VersionID = 0x700,
CollDetRelayCtrl = 0x8,
} can_messages;
class ARS_40X_CAN {
public:
ARS_40X_CAN();
ARS_40X_CAN(std::string port); //用于接收传入的端口号,该端口号主要用于socket的初始化
~ARS_40X_CAN();
virtual bool receive_radar_data(); //虚函数,用于继承使用的该类的对象进行重写使用
virtual bool send_radar_data(uint32_t frame_id);
cluster_list::Cluster_0_Status *get_cluster_0_status();
cluster_list::Cluster_1_General *get_cluster_1_general();
cluster_list::Cluster_2_Quality *get_cluster_2_quality();
motion_input_signals::SpeedInformation *get_speed_information();
motion_input_signals::YawRateInformation *get_yaw_rate_information();
object_list::Object_0_Status *get_object_0_status();
object_list::Object_1_General *get_object_1_general();
object_list::Object_2_Quality *get_object_2_quality();
object_list::Object_3_Extended *get_object_3_extended();
radar_state::RadarState *get_radar_state();
radar_cfg::RadarCfg *get_radar_cfg(); //各部分协议的状态返回函数
virtual void send_cluster_0_status() {};
virtual void send_cluster_1_general() {};
virtual void send_cluster_2_quality() {};
virtual void send_object_0_status() {};
virtual void send_object_1_general() {};
virtual void send_object_2_quality() {};
virtual void send_object_3_extended() {};
virtual void send_radar_state() {}; //虚函数,用于各部分数据解析之后的发送操作
private:
socket_can::SocketCAN can_; //构建SocketCAN类对象
cluster_list::Cluster_0_Status cluster_0_status_;
cluster_list::Cluster_1_General cluster_1_general_;
cluster_list::Cluster_2_Quality cluster_2_quality_;
motion_input_signals::SpeedInformation speed_information_;
motion_input_signals::YawRateInformation yaw_rate_information_;
object_list::Object_0_Status object_0_status_;
object_list::Object_1_General object_1_general_;
object_list::Object_2_Quality object_2_quality_;
object_list::Object_3_Extended object_3_extended_;
radar_state::RadarState radar_state_;
radar_cfg::RadarCfg radar_cfg_; //构建各部分协议的类对象
};
}
#endif //ARS_40X_ARS_40X_HPP
- 接口类 ARS_40X_CAN的实现
#include "ars_40X/ars_40X_can.hpp"
namespace ars_40X {
ARS_40X_CAN::ARS_40X_CAN() :
can_("can1") { //默认构造函数,指定默认的CAN口设备
}
ARS_40X_CAN::ARS_40X_CAN(std::string port) :
can_(port.c_str()) { //带参构造函数,从函数调用出获取需要绑定的设备端口号
}
ARS_40X_CAN::~ARS_40X_CAN() {
}
bool ARS_40X_CAN::receive_radar_data() {
uint32_t frame_id;
uint8_t dlc;
uint8_t data[8] = {0}; //定义用于接收CAN口数据的变量
bool read_status = can_.read(&frame_id, &dlc, data); //读取CAN口数据,并对读取状态进行判断
if (!read_status) {
return false;
}
switch (frame_id) { //根据获取的数据的frame_id来对其CAN messages类型进行判断,并交由相应解析部分处理
case RadarState:memcpy(radar_state_.get_radar_state()->raw_data, data, dlc);
send_radar_state();
break; //memcpy()为内存拷贝函数,表示将数据从data中拷贝dlc个字节到raw_data中。之后通过调用send()函数将数据解析后得到的结果发送出去
case Cluster_0_Status:memcpy(cluster_0_status_.get_cluster_0_status()->raw_data, data, dlc);
send_cluster_0_status();
break;
case Cluster_1_General:memcpy(cluster_1_general_.get_cluster_1_general()->raw_data, data, dlc);
send_cluster_1_general();
break;
case Cluster_2_Quality:memcpy(cluster_2_quality_.get_cluster_2_quality()->raw_data, data, dlc);
send_cluster_2_quality();
break;
case Object_0_Status:memcpy(object_0_status_.get_object_0_status()->raw_data, data, dlc);
send_object_0_status();
break;
case Object_1_General:memcpy(object_1_general_.get_object_1_general()->raw_data, data, dlc);
send_object_1_general();
break;
case Object_2_Quality:memcpy(object_2_quality_.get_object_2_quality()->raw_data, data, dlc);
send_object_2_quality();
break;
case Object_3_Extended:memcpy(object_3_extended_.get_object_3_extended()->raw_data, data, dlc);
send_object_3_extended();
break;
default: {
#if DEBUG
printf("Unidentified Message: %d\n", frame_id); //如果frame_id不属于以上CAN messages类型,则输出错误信息。
#endif
break;
}
}
return true;
}
bool ARS_40X_CAN::send_radar_data(uint32_t frame_id) { //向雷达发送数据的函数
switch (frame_id) {
case RadarCfg:can_.write(frame_id, 8, radar_cfg_.get_radar_cfg()->raw_data);
break; //发送雷达配置信息
case SpeedInformation:
can_.write(frame_id,
2,
speed_information_.get_speed_information()->raw_data);
break; //发送雷达速度信息
case YawRateInformation:
can_.write(frame_id,
2,
yaw_rate_information_.get_yaw_rate_information()->raw_data);
break; //发送雷达角速度信息
#if DEBUG
default: printf("Frame ID not supported\n"); //发送不符合要求信息时的错误输出
#endif
}
return true;
}
cluster_list::Cluster_0_Status *ARS_40X_CAN::get_cluster_0_status() {
return &cluster_0_status_; //返回类对象,便于函数调用
}
cluster_list::Cluster_1_General *ARS_40X_CAN::get_cluster_1_general() {
return &cluster_1_general_;
}
cluster_list::Cluster_2_Quality *ARS_40X_CAN::get_cluster_2_quality() {
return &cluster_2_quality_;
}
motion_input_signals::SpeedInformation *ARS_40X_CAN::get_speed_information() {
return &speed_information_;
}
motion_input_signals::YawRateInformation *ARS_40X_CAN::get_yaw_rate_information() {
return &yaw_rate_information_;
}
object_list::Object_0_Status *ARS_40X_CAN::get_object_0_status() {
return &object_0_status_;
}
object_list::Object_1_General *ARS_40X_CAN::get_object_1_general() {
return &object_1_general_;
}
object_list::Object_2_Quality *ARS_40X_CAN::get_object_2_quality() {
return &object_2_quality_;
}
object_list::Object_3_Extended *ARS_40X_CAN::get_object_3_extended() {
return &object_3_extended_;
}
radar_state::RadarState *ARS_40X_CAN::get_radar_state() {
return &radar_state_;
}
radar_cfg::RadarCfg *ARS_40X_CAN::get_radar_cfg() {
return &radar_cfg_;
}
}
参考:
- 源码地址
- ARS40X_协议_V 1.91_18.05.2018