2021-10-27 21:56:21 +00:00
# include "autoware_v2x/cpm_application.hpp"
# include "autoware_v2x/positioning.hpp"
# include "autoware_v2x/security.hpp"
# include "autoware_v2x/link_layer.hpp"
2021-11-10 15:21:32 +00:00
# include "autoware_v2x/v2x_node.hpp"
2021-10-27 21:56:21 +00:00
2021-11-14 04:26:18 +00:00
# include "tf2/LinearMath/Quaternion.h"
# include "tf2/LinearMath/Matrix3x3.h"
2021-10-27 21:56:21 +00:00
# include "rclcpp/rclcpp.hpp"
# include <vanetza/btp/ports.hpp>
# include <vanetza/asn1/cpm.hpp>
# include <vanetza/asn1/packet_visitor.hpp>
# include <vanetza/facilities/cpm_functions.hpp>
# include <chrono>
# include <functional>
# include <iostream>
# include <sstream>
# include <exception>
2021-11-10 15:21:32 +00:00
# include <GeographicLib/UTMUPS.hpp>
# include <GeographicLib/MGRS.hpp>
# include <string>
2021-10-27 21:56:21 +00:00
2022-02-27 03:26:28 +00:00
# include <boost/units/cmath.hpp>
# include <boost/units/systems/si/prefixes.hpp>
2022-04-01 06:33:41 +00:00
# include <sqlite3.h>
2021-11-10 08:14:01 +00:00
# define _USE_MATH_DEFINES
# include <math.h>
2021-10-27 21:56:21 +00:00
using namespace vanetza ;
using namespace vanetza : : facilities ;
using namespace std : : chrono ;
2022-02-16 07:53:45 +00:00
namespace v2x {
2022-02-27 03:26:28 +00:00
CpmApplication : : CpmApplication ( V2XNode * node , Runtime & rt , bool is_sender ) :
2021-11-10 15:21:32 +00:00
node_ ( node ) ,
runtime_ ( rt ) ,
2022-02-16 07:53:45 +00:00
ego_ ( ) ,
2021-11-10 15:21:32 +00:00
generationDeltaTime_ ( 0 ) ,
2022-03-30 05:51:02 +00:00
updating_objects_list_ ( false ) ,
2022-01-21 13:07:33 +00:00
sending_ ( false ) ,
2022-02-27 03:26:28 +00:00
is_sender_ ( is_sender ) ,
2022-03-30 05:51:02 +00:00
reflect_packet_ ( false ) ,
objectConfidenceThreshold_ ( 0.0 ) ,
2022-04-01 05:51:10 +00:00
include_all_persons_and_animals_ ( false ) ,
cpm_num_ ( 0 ) ,
received_cpm_num_ ( 0 ) ,
cpm_object_id_ ( 0 )
2021-11-10 15:21:32 +00:00
{
2022-02-27 03:26:28 +00:00
RCLCPP_INFO ( node_ - > get_logger ( ) , " CpmApplication started. is_sender: %d " , is_sender_ ) ;
2022-04-01 05:51:10 +00:00
set_interval ( milliseconds ( 100 ) ) ;
2022-04-01 06:33:41 +00:00
createTables ( ) ;
2021-11-10 15:21:32 +00:00
}
2021-10-27 21:56:21 +00:00
2022-01-21 13:07:33 +00:00
void CpmApplication : : set_interval ( Clock : : duration interval ) {
2021-11-10 15:21:32 +00:00
cpm_interval_ = interval ;
runtime_ . cancel ( this ) ;
schedule_timer ( ) ;
2021-11-10 08:14:01 +00:00
}
2021-11-10 15:21:32 +00:00
2022-01-21 13:07:33 +00:00
void CpmApplication : : schedule_timer ( ) {
2021-11-10 15:21:32 +00:00
runtime_ . schedule ( cpm_interval_ , std : : bind ( & CpmApplication : : on_timer , this , std : : placeholders : : _1 ) , this ) ;
2021-10-27 21:56:21 +00:00
}
2022-01-21 13:07:33 +00:00
void CpmApplication : : on_timer ( Clock : : time_point ) {
2021-11-10 15:21:32 +00:00
schedule_timer ( ) ;
send ( ) ;
}
2021-11-10 08:14:01 +00:00
2022-01-21 13:07:33 +00:00
CpmApplication : : PortType CpmApplication : : port ( ) {
2021-11-10 15:21:32 +00:00
return btp : : ports : : CPM ;
}
2021-10-27 21:56:21 +00:00
2022-03-28 02:17:51 +00:00
std : : string CpmApplication : : uuidToHexString ( const unique_identifier_msgs : : msg : : UUID & id ) {
std : : stringstream ss ;
for ( auto i = 0 ; i < 16 ; + + i ) {
ss < < std : : hex < < std : : setfill ( ' 0 ' ) < < std : : setw ( 2 ) < < + id . uuid [ i ] ;
}
return ss . str ( ) ;
}
2022-01-15 07:14:17 +00:00
void CpmApplication : : indicate ( const DataIndication & indication , UpPacketPtr packet ) {
2022-01-21 13:07:33 +00:00
2021-11-10 15:21:32 +00:00
asn1 : : PacketVisitor < asn1 : : Cpm > visitor ;
std : : shared_ptr < const asn1 : : Cpm > cpm = boost : : apply_visitor ( visitor , * packet ) ;
2022-01-21 13:07:33 +00:00
2021-11-17 08:58:41 +00:00
if ( cpm ) {
2022-04-01 05:51:10 +00:00
RCLCPP_INFO ( node_ - > get_logger ( ) , " [INDICATE] Received CPM #%d " , received_cpm_num_ ) ;
2022-01-15 07:14:17 +00:00
rclcpp : : Time current_time = node_ - > now ( ) ;
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::indicate] [measure] T_receive_r1 %ld", current_time.nanoseconds());
2022-01-15 07:14:17 +00:00
2021-11-10 15:21:32 +00:00
asn1 : : Cpm message = * cpm ;
ItsPduHeader_t & header = message - > header ;
2021-12-05 06:22:00 +00:00
// Calculate GDT and get GDT from CPM and calculate the "Age of CPM"
GenerationDeltaTime_t gdt_cpm = message - > cpm . generationDeltaTime ;
const auto time_now = duration_cast < milliseconds > ( runtime_ . now ( ) . time_since_epoch ( ) ) ;
uint16_t gdt = time_now . count ( ) ;
int gdt_diff = ( 65536 + ( gdt - gdt_cpm ) % 65536 ) % 65536 ;
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::indicate] [measure] GDT_CPM: %ld", gdt_cpm);
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::indicate] [measure] GDT: %u", gdt);
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::indicate] [measure] T_R1R2: %d", gdt_diff);
2022-01-20 10:39:51 +00:00
2021-12-05 06:22:00 +00:00
2021-11-10 15:21:32 +00:00
CpmManagementContainer_t & management = message - > cpm . cpmParameters . managementContainer ;
double lat = management . referencePosition . latitude / 1.0e7 ;
double lon = management . referencePosition . longitude / 1.0e7 ;
int zone ;
2022-02-25 09:38:23 +00:00
int grid_num_x = 4 ;
int grid_num_y = 39 ;
int grid_size = 100000 ;
2021-11-10 15:21:32 +00:00
bool northp ;
double x , y ;
2022-02-27 03:26:28 +00:00
GeographicLib : : UTMUPS : : Forward ( lat , lon , zone , northp , x , y ) ;
2022-02-25 09:38:23 +00:00
double x_mgrs = x - grid_num_x * grid_size ;
double y_mgrs = y - grid_num_y * grid_size ;
2021-11-10 15:21:32 +00:00
OriginatingVehicleContainer_t & ovc = message - > cpm . cpmParameters . stationDataContainer - > choice . originatingVehicleContainer ;
2022-02-27 03:26:28 +00:00
// Calculate ego-vehicle orientation (radians) from heading (degree).
// orientation: True-East, counter-clockwise angle. (0.1 degree accuracy)
2021-11-10 15:21:32 +00:00
int heading = ovc . heading . headingValue ;
2022-02-27 03:26:28 +00:00
double orientation = ( 90.0 - ( double ) heading / 10.0 ) * M_PI / 180.0 ;
if ( orientation < 0.0 ) orientation + = ( 2.0 * M_PI ) ;
// double orientation = heading / 10.0;
2022-03-28 02:17:51 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::indicate] heading: %d", heading);
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::indicate] orientation: %f", orientation);
2021-11-10 15:21:32 +00:00
// Get PerceivedObjects
receivedObjectsStack . clear ( ) ;
2021-11-14 04:26:18 +00:00
2021-11-17 08:58:41 +00:00
PerceivedObjectContainer_t * & poc = message - > cpm . cpmParameters . perceivedObjectContainer ;
2021-11-14 04:26:18 +00:00
2021-11-17 08:58:41 +00:00
if ( poc ! = NULL ) {
for ( int i = 0 ; i < poc - > list . count ; + + i ) {
2022-04-06 02:10:25 +00:00
// RCLCPP_INFO(node_->get_logger(), "[INDICATE] Object: #%d", poc->list.array[i]->objectID);
2021-11-17 08:58:41 +00:00
CpmApplication : : Object object ;
double x1 = poc - > list . array [ i ] - > xDistance . value ;
double y1 = poc - > list . array [ i ] - > yDistance . value ;
x1 = x1 / 100.0 ;
y1 = y1 / 100.0 ;
object . position_x = x_mgrs + ( cos ( orientation ) * x1 - sin ( orientation ) * y1 ) ;
2022-02-27 03:26:28 +00:00
object . position_y = y_mgrs + ( sin ( orientation ) * x1 + cos ( orientation ) * y1 ) ;
2021-11-17 08:58:41 +00:00
object . shape_x = poc - > list . array [ i ] - > planarObjectDimension2 - > value ;
object . shape_y = poc - > list . array [ i ] - > planarObjectDimension1 - > value ;
object . shape_z = poc - > list . array [ i ] - > verticalObjectDimension - > value ;
object . yawAngle = poc - > list . array [ i ] - > yawAngle - > value ;
2022-02-27 03:26:28 +00:00
double yaw_radian = ( M_PI * object . yawAngle / 10.0 ) / 180.0 ;
2021-11-17 08:58:41 +00:00
tf2 : : Quaternion quat ;
quat . setRPY ( 0 , 0 , yaw_radian ) ;
object . orientation_x = quat . x ( ) ;
object . orientation_y = quat . y ( ) ;
object . orientation_z = quat . z ( ) ;
object . orientation_w = quat . w ( ) ;
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::indicate] object.quat: %f, %f, %f, %f", object.orientation_x, object.orientation_y, object.orientation_z, object.orientation_w);
2021-11-17 08:58:41 +00:00
receivedObjectsStack . push_back ( object ) ;
}
node_ - > publishObjects ( & receivedObjectsStack ) ;
} else {
2022-03-28 02:17:51 +00:00
// RCLCPP_INFO(node_->get_logger(), "[INDICATE] Empty POC");
2021-11-10 15:21:32 +00:00
}
2022-01-21 13:07:33 +00:00
2022-04-01 07:42:16 +00:00
insertCpmToCpmTable ( message , ( char * ) " cpm_received " ) ;
2022-01-21 13:07:33 +00:00
if ( reflect_packet_ ) {
Application : : DownPacketPtr packet { new DownPacket ( ) } ;
std : : unique_ptr < geonet : : DownPacket > payload { new geonet : : DownPacket ( ) } ;
payload - > layer ( OsiLayer : : Application ) = std : : move ( message ) ;
Application : : DataRequest request ;
request . its_aid = aid : : CP ;
request . transport_type = geonet : : TransportType : : SHB ;
request . communication_profile = geonet : : CommunicationProfile : : ITS_G5 ;
Application : : DataConfirm confirm = Application : : request ( request , std : : move ( payload ) , node_ ) ;
if ( ! confirm . accepted ( ) ) {
throw std : : runtime_error ( " [CpmApplication::indicate] Packet reflection failed " ) ;
}
}
2022-04-01 05:51:10 +00:00
+ + received_cpm_num_ ;
2022-01-21 13:07:33 +00:00
2021-11-17 08:58:41 +00:00
} else {
RCLCPP_INFO ( node_ - > get_logger ( ) , " [INDICATE] Received broken content " ) ;
2021-11-10 15:21:32 +00:00
}
}
2021-10-27 21:56:21 +00:00
2022-01-21 13:07:33 +00:00
void CpmApplication : : updateMGRS ( double * x , double * y ) {
2022-02-16 07:53:45 +00:00
ego_ . mgrs_x = * x ;
ego_ . mgrs_y = * y ;
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::updateMGRS] ego-vehicle.position: %.10f, %.10f", ego_.mgrs_x, ego_.mgrs_y);
2021-11-10 15:21:32 +00:00
}
2021-10-27 21:56:21 +00:00
2022-01-21 13:07:33 +00:00
void CpmApplication : : updateRP ( double * lat , double * lon , double * altitude ) {
2022-02-16 07:53:45 +00:00
ego_ . latitude = * lat ;
ego_ . longitude = * lon ;
ego_ . altitude = * altitude ;
2021-11-10 15:21:32 +00:00
}
2021-10-27 21:56:21 +00:00
2022-01-21 13:07:33 +00:00
void CpmApplication : : updateGenerationDeltaTime ( int * gdt , long long * gdt_timestamp ) {
2021-11-10 15:21:32 +00:00
generationDeltaTime_ = * gdt ;
2022-01-15 07:14:17 +00:00
gdt_timestamp_ = * gdt_timestamp ; // ETSI-epoch milliseconds timestamp
2021-11-10 08:14:01 +00:00
}
2022-01-21 13:07:33 +00:00
void CpmApplication : : updateHeading ( double * yaw ) {
2022-02-16 07:53:45 +00:00
ego_ . heading = * yaw ;
2021-11-10 15:21:32 +00:00
}
2021-10-27 21:56:21 +00:00
2022-03-30 05:51:02 +00:00
void CpmApplication : : setAllObjectsOfPersonsAnimalsToSend ( const autoware_auto_perception_msgs : : msg : : PredictedObjects : : ConstSharedPtr msg ) {
if ( msg - > objects . size ( ) > 0 ) {
for ( autoware_auto_perception_msgs : : msg : : PredictedObject obj : msg - > objects ) {
std : : string object_uuid = uuidToHexString ( obj . object_id ) ;
auto found_object = std : : find_if ( objectsList . begin ( ) , objectsList . end ( ) , [ & ] ( auto const & e ) {
return ! strcmp ( e . uuid . c_str ( ) , object_uuid . c_str ( ) ) ;
} ) ;
if ( found_object = = objectsList . end ( ) ) {
} else {
found_object - > to_send = true ;
}
}
}
}
void CpmApplication : : updateObjectsList ( const autoware_auto_perception_msgs : : msg : : PredictedObjects : : ConstSharedPtr msg ) {
updating_objects_list_ = true ;
2021-10-27 21:56:21 +00:00
2021-11-17 08:45:25 +00:00
if ( sending_ ) {
2021-11-10 15:21:32 +00:00
RCLCPP_INFO ( node_ - > get_logger ( ) , " updateObjectsStack Skipped... " ) ;
return ;
2021-11-17 08:45:25 +00:00
} else {
2022-03-30 05:51:02 +00:00
// objectsList.clear();
2021-11-17 08:45:25 +00:00
}
2021-11-10 15:21:32 +00:00
2021-11-17 08:45:25 +00:00
if ( msg - > objects . size ( ) > 0 ) {
2022-03-28 02:17:51 +00:00
for ( autoware_auto_perception_msgs : : msg : : PredictedObject obj : msg - > objects ) {
// RCLCPP_INFO(node_->get_logger(), "%d", obj.classification.front().label);
2022-03-30 05:51:02 +00:00
double existence_probability = obj . existence_probability ;
// RCLCPP_INFO(node_->get_logger(), "existence_probability: %f", existence_probability);
std : : string object_uuid = uuidToHexString ( obj . object_id ) ;
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "received object_id: %s", object_uuid.c_str());
2022-03-30 05:51:02 +00:00
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "ObjectsList count: %d", objectsList.size());
2022-03-30 05:51:02 +00:00
if ( existence_probability > = objectConfidenceThreshold_ ) {
// ObjectConfidence > ObjectConfidenceThreshold
// Object tracked in internal memory? (i.e. Is object included in ObjectsList?)
auto found_object = std : : find_if ( objectsList . begin ( ) , objectsList . end ( ) , [ & ] ( auto const & e ) {
return ! strcmp ( e . uuid . c_str ( ) , object_uuid . c_str ( ) ) ;
} ) ;
if ( found_object = = objectsList . end ( ) ) {
// Object is new to internal memory
2022-04-01 05:51:10 +00:00
if ( cpm_object_id_ > 255 ) {
cpm_object_id_ = 0 ;
}
2022-03-30 05:51:02 +00:00
// Add new object to ObjectsList
CpmApplication : : Object object ;
2022-04-01 05:51:10 +00:00
object . objectID = cpm_object_id_ ;
2022-03-30 05:51:02 +00:00
object . uuid = object_uuid ;
object . timestamp_ros = msg - > header . stamp ;
object . position_x = obj . kinematics . initial_pose_with_covariance . pose . position . x ;
object . position_y = obj . kinematics . initial_pose_with_covariance . pose . position . y ;
object . position_z = obj . kinematics . initial_pose_with_covariance . pose . position . z ;
object . orientation_x = obj . kinematics . initial_pose_with_covariance . pose . orientation . x ;
object . orientation_y = obj . kinematics . initial_pose_with_covariance . pose . orientation . y ;
object . orientation_z = obj . kinematics . initial_pose_with_covariance . pose . orientation . z ;
object . orientation_w = obj . kinematics . initial_pose_with_covariance . pose . orientation . w ;
object . shape_x = std : : lround ( obj . shape . dimensions . x * 10.0 ) ;
object . shape_y = std : : lround ( obj . shape . dimensions . y * 10.0 ) ;
object . shape_z = std : : lround ( obj . shape . dimensions . z * 10.0 ) ;
long long msg_timestamp_sec = msg - > header . stamp . sec ;
long long msg_timestamp_nsec = msg - > header . stamp . nanosec ;
msg_timestamp_sec - = 1072915200 ; // convert to etsi-epoch
long long msg_timestamp_msec = msg_timestamp_sec * 1000 + msg_timestamp_nsec / 1000000 ;
object . timeOfMeasurement = gdt_timestamp_ - msg_timestamp_msec ;
if ( object . timeOfMeasurement < - 1500 | | object . timeOfMeasurement > 1500 ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " [updateObjectsStack] timeOfMeasurement out of bounds: %d " , object . timeOfMeasurement ) ;
continue ;
}
object . to_send = false ;
2022-04-01 05:51:10 +00:00
object . to_send_trigger = 0 ;
2022-03-30 05:51:02 +00:00
object . timestamp = runtime_ . now ( ) ;
objectsList . push_back ( object ) ;
2022-04-01 05:51:10 +00:00
+ + cpm_object_id_ ;
2022-03-30 05:51:02 +00:00
} else {
// Object was already in internal memory
// Object belongs to class person or animal
if ( obj . classification . front ( ) . label = = autoware_auto_perception_msgs : : msg : : ObjectClassification : : PEDESTRIAN | | obj . classification . front ( ) . label = = autoware_auto_perception_msgs : : msg : : ObjectClassification : : UNKNOWN ) {
if ( include_all_persons_and_animals_ ) {
found_object - > to_send = true ;
2022-04-01 05:51:10 +00:00
found_object - > to_send_trigger = 5 ;
2022-03-30 05:51:02 +00:00
}
// Object has not been included in a CPM in the past 500 ms.
2022-04-01 05:51:10 +00:00
if ( runtime_ . now ( ) . time_since_epoch ( ) . count ( ) - found_object - > timestamp . time_since_epoch ( ) . count ( ) > 500000 ) {
2022-03-30 05:51:02 +00:00
// Include all objects of class person or animal in the current CPM
include_all_persons_and_animals_ = true ;
found_object - > to_send = true ;
2022-04-01 05:51:10 +00:00
found_object - > to_send_trigger = 5 ;
2022-03-30 05:51:02 +00:00
setAllObjectsOfPersonsAnimalsToSend ( msg ) ;
RCLCPP_INFO ( node_ - > get_logger ( ) , " Include all objects of person/animal class " ) ;
}
} else {
// Object does not belong to class person or animal
// Euclidean absolute distance has changed by more than 4m
double dist = pow ( obj . kinematics . initial_pose_with_covariance . pose . position . x - found_object - > position_x , 2 ) + pow ( obj . kinematics . initial_pose_with_covariance . pose . position . y - found_object - > position_y , 2 ) ;
dist = sqrt ( dist ) ;
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "Distance changed: %f", dist);
2022-03-30 05:51:02 +00:00
if ( dist > 4 ) {
found_object - > to_send = true ;
2022-04-01 05:51:10 +00:00
found_object - > to_send_trigger = 1 ;
2022-03-30 05:51:02 +00:00
} else {
}
// Absolute speed changed by more than 0.5 m/s
double speed = pow ( obj . kinematics . initial_twist_with_covariance . twist . linear . x - found_object - > twist_linear_x , 2 ) + pow ( obj . kinematics . initial_twist_with_covariance . twist . linear . x - found_object - > twist_linear_y , 2 ) ;
speed = sqrt ( speed ) ;
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "Speed changed: %f", dist);
2022-03-30 05:51:02 +00:00
if ( speed > 0.5 ) {
found_object - > to_send = true ;
2022-04-01 05:51:10 +00:00
found_object - > to_send_trigger = 2 ;
2022-03-30 05:51:02 +00:00
}
// Orientation of speed vector changed by more than 4 degrees
double twist_angular_x_diff = ( obj . kinematics . initial_twist_with_covariance . twist . angular . x - found_object - > twist_angular_x ) * 180 / M_PI ;
double twist_angular_y_diff = ( obj . kinematics . initial_twist_with_covariance . twist . angular . y - found_object - > twist_angular_y ) * 180 / M_PI ;
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "Orientation speed vector changed x: %f", twist_angular_x_diff);
// RCLCPP_INFO(node_->get_logger(), "Orientation speed vector changed y: %f", twist_angular_y_diff);
2022-03-30 05:51:02 +00:00
if ( twist_angular_x_diff > 4 | | twist_angular_y_diff > 4 ) {
found_object - > to_send = true ;
2022-04-01 05:51:10 +00:00
found_object - > to_send_trigger = 3 ;
2022-03-30 05:51:02 +00:00
}
// It has been more than 1 s since last transmission of this object
if ( runtime_ . now ( ) . time_since_epoch ( ) . count ( ) - found_object - > timestamp . time_since_epoch ( ) . count ( ) > 1000000 ) {
found_object - > to_send = true ;
2022-04-01 05:51:10 +00:00
found_object - > to_send_trigger = 4 ;
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "Been more than 1s: %ld", runtime_.now().time_since_epoch().count() - found_object->timestamp.time_since_epoch().count());
2022-03-30 05:51:02 +00:00
}
}
// Update found_object
found_object - > timestamp_ros = msg - > header . stamp ;
found_object - > position_x = obj . kinematics . initial_pose_with_covariance . pose . position . x ;
found_object - > position_y = obj . kinematics . initial_pose_with_covariance . pose . position . y ;
found_object - > position_z = obj . kinematics . initial_pose_with_covariance . pose . position . z ;
found_object - > orientation_x = obj . kinematics . initial_pose_with_covariance . pose . orientation . x ;
found_object - > orientation_y = obj . kinematics . initial_pose_with_covariance . pose . orientation . y ;
found_object - > orientation_z = obj . kinematics . initial_pose_with_covariance . pose . orientation . z ;
found_object - > orientation_w = obj . kinematics . initial_pose_with_covariance . pose . orientation . w ;
found_object - > shape_x = std : : lround ( obj . shape . dimensions . x * 10.0 ) ;
found_object - > shape_y = std : : lround ( obj . shape . dimensions . y * 10.0 ) ;
found_object - > shape_z = std : : lround ( obj . shape . dimensions . z * 10.0 ) ;
long long msg_timestamp_sec = msg - > header . stamp . sec ;
long long msg_timestamp_nsec = msg - > header . stamp . nanosec ;
msg_timestamp_sec - = 1072915200 ; // convert to etsi-epoch
long long msg_timestamp_msec = msg_timestamp_sec * 1000 + msg_timestamp_nsec / 1000000 ;
found_object - > timeOfMeasurement = gdt_timestamp_ - msg_timestamp_msec ;
if ( found_object - > timeOfMeasurement < - 1500 | | found_object - > timeOfMeasurement > 1500 ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " [updateObjectsStack] timeOfMeasurement out of bounds: %d " , found_object - > timeOfMeasurement ) ;
continue ;
}
found_object - > timestamp = runtime_ . now ( ) ;
}
2021-11-23 04:02:54 +00:00
}
2021-11-10 15:21:32 +00:00
}
2022-03-30 05:51:02 +00:00
} else {
// No objects detected
2021-11-10 08:14:01 +00:00
}
2022-03-28 02:17:51 +00:00
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "ObjectsStack: %d objects", objectsStack.size());
2022-01-23 06:38:33 +00:00
rclcpp : : Time current_time = node_ - > now ( ) ;
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::updateObjectsStack] [measure] T_objstack_updated %ld", current_time.nanoseconds());
2022-03-30 05:51:02 +00:00
updating_objects_list_ = false ;
2021-11-10 15:21:32 +00:00
}
2021-11-10 08:14:01 +00:00
2022-04-01 05:51:10 +00:00
void CpmApplication : : printObjectsList ( int cpm_num ) {
// RCLCPP_INFO(node_->get_logger(), "------------------------");
if ( objectsList . size ( ) > 0 ) {
for ( auto & object : objectsList ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " [objectsList] %d,%d,%s,%d,%d " , cpm_num , object . objectID , object . uuid . c_str ( ) , object . to_send , object . to_send_trigger ) ;
}
} else {
RCLCPP_INFO ( node_ - > get_logger ( ) , " [objectsList] %d,,,, " , cpm_num ) ;
2022-03-30 09:04:41 +00:00
}
2022-04-01 05:51:10 +00:00
// RCLCPP_INFO(node_->get_logger(), "------------------------");
2022-03-30 09:04:41 +00:00
}
2022-01-15 07:14:17 +00:00
void CpmApplication : : send ( ) {
2022-01-21 13:07:33 +00:00
if ( is_sender_ ) {
2022-03-30 09:04:41 +00:00
2022-01-21 13:07:33 +00:00
sending_ = true ;
2022-04-01 05:51:10 +00:00
2022-04-06 02:10:25 +00:00
// printObjectsList(cpm_num_);
2022-01-21 13:07:33 +00:00
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::send] Sending CPM...");
2022-01-21 13:07:33 +00:00
vanetza : : asn1 : : Cpm message ;
// ITS PDU Header
ItsPduHeader_t & header = message - > header ;
header . protocolVersion = 1 ;
header . messageID = 14 ;
header . stationID = 1 ;
CollectivePerceptionMessage_t & cpm = message - > cpm ;
// Set GenerationDeltaTime
cpm . generationDeltaTime = generationDeltaTime_ * GenerationDeltaTime_oneMilliSec ;
CpmManagementContainer_t & management = cpm . cpmParameters . managementContainer ;
management . stationType = StationType_passengerCar ;
2022-02-27 03:26:28 +00:00
management . referencePosition . latitude = ego_ . latitude * 1e7 ;
management . referencePosition . longitude = ego_ . longitude * 1e7 ;
2022-01-21 13:07:33 +00:00
StationDataContainer_t * & sdc = cpm . cpmParameters . stationDataContainer ;
sdc = vanetza : : asn1 : : allocate < StationDataContainer_t > ( ) ;
sdc - > present = StationDataContainer_PR_originatingVehicleContainer ;
OriginatingVehicleContainer_t & ovc = sdc - > choice . originatingVehicleContainer ;
ovc . speed . speedValue = 0 ;
ovc . speed . speedConfidence = 1 ;
2022-02-27 03:26:28 +00:00
// Calculate headingValue of ego-vehicle.
// Convert ego-vehicle yaw to True-North clockwise angle (heading). 0.1 degree accuracy.
2022-02-16 07:53:45 +00:00
int heading = std : : lround ( ( ( - ego_ . heading * 180.0 / M_PI ) + 90.0 ) * 10.0 ) ;
2022-01-21 13:07:33 +00:00
if ( heading < 0 ) heading + = 3600 ;
ovc . heading . headingValue = heading ;
ovc . heading . headingConfidence = 1 ;
2022-04-01 07:39:00 +00:00
int perceivedObjectsCount = 0 ;
2022-03-30 05:51:02 +00:00
if ( objectsList . size ( ) > 0 ) {
2022-01-21 13:07:33 +00:00
PerceivedObjectContainer_t * & poc = cpm . cpmParameters . perceivedObjectContainer ;
poc = vanetza : : asn1 : : allocate < PerceivedObjectContainer_t > ( ) ;
2022-03-30 05:51:02 +00:00
for ( auto & object : objectsList ) {
// RCLCPP_INFO(node_->get_logger(), "object.to_send: %d", object.to_send);
if ( object . to_send ) {
2022-04-01 07:39:00 +00:00
2022-03-30 05:51:02 +00:00
PerceivedObject * pObj = vanetza : : asn1 : : allocate < PerceivedObject > ( ) ;
// Update CPM-specific values for Object
object . xDistance = std : : lround ( (
( object . position_x - ego_ . mgrs_x ) * cos ( - ego_ . heading ) - ( object . position_y - ego_ . mgrs_y ) * sin ( - ego_ . heading )
) * 100.0 ) ;
object . yDistance = std : : lround ( (
( object . position_x - ego_ . mgrs_x ) * sin ( - ego_ . heading ) + ( object . position_y - ego_ . mgrs_y ) * cos ( - ego_ . heading )
) * 100.0 ) ;
if ( object . xDistance < - 132768 | | object . xDistance > 132767 ) {
2022-04-01 05:51:10 +00:00
RCLCPP_WARN ( node_ - > get_logger ( ) , " xDistance out of bounds. objectID: #%d " , object . objectID ) ;
2022-03-30 05:51:02 +00:00
continue ;
}
if ( object . yDistance < - 132768 | | object . yDistance > 132767 ) {
2022-04-01 05:51:10 +00:00
RCLCPP_WARN ( node_ - > get_logger ( ) , " yDistance out of bounds. objectID: #%d " , object . objectID ) ;
2022-03-30 05:51:02 +00:00
continue ;
}
// Calculate orientation of detected object
tf2 : : Quaternion quat ( object . orientation_x , object . orientation_y , object . orientation_z , object . orientation_w ) ;
tf2 : : Matrix3x3 matrix ( quat ) ;
double roll , pitch , yaw ;
matrix . getRPY ( roll , pitch , yaw ) ;
if ( yaw < 0 ) {
object . yawAngle = std : : lround ( ( ( yaw + 2 * M_PI ) * 180.0 / M_PI ) * 10.0 ) ; // 0 - 3600
} else {
object . yawAngle = std : : lround ( ( yaw * 180.0 / M_PI ) * 10.0 ) ; // 0 - 3600
}
object . xSpeed = 0 ;
object . ySpeed = 0 ;
pObj - > objectID = object . objectID ;
pObj - > timeOfMeasurement = object . timeOfMeasurement ;
pObj - > xDistance . value = object . xDistance ;
pObj - > xDistance . confidence = 1 ;
pObj - > yDistance . value = object . yDistance ;
pObj - > yDistance . confidence = 1 ;
pObj - > xSpeed . value = object . xSpeed ;
pObj - > xSpeed . confidence = 1 ;
pObj - > ySpeed . value = object . ySpeed ;
pObj - > ySpeed . confidence = 1 ;
pObj - > planarObjectDimension1 = vanetza : : asn1 : : allocate < ObjectDimension_t > ( ) ;
pObj - > planarObjectDimension2 = vanetza : : asn1 : : allocate < ObjectDimension_t > ( ) ;
pObj - > verticalObjectDimension = vanetza : : asn1 : : allocate < ObjectDimension_t > ( ) ;
( * ( pObj - > planarObjectDimension1 ) ) . value = object . shape_y ;
( * ( pObj - > planarObjectDimension1 ) ) . confidence = 1 ;
( * ( pObj - > planarObjectDimension2 ) ) . value = object . shape_x ;
( * ( pObj - > planarObjectDimension2 ) ) . confidence = 1 ;
( * ( pObj - > verticalObjectDimension ) ) . value = object . shape_z ;
( * ( pObj - > verticalObjectDimension ) ) . confidence = 1 ;
pObj - > yawAngle = vanetza : : asn1 : : allocate < CartesianAngle > ( ) ;
( * ( pObj - > yawAngle ) ) . value = object . yawAngle ;
( * ( pObj - > yawAngle ) ) . confidence = 1 ;
ASN_SEQUENCE_ADD ( poc , pObj ) ;
object . to_send = false ;
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "Sending object: %s", object.uuid.c_str());
2022-04-01 07:39:00 +00:00
+ + perceivedObjectsCount ;
2022-03-30 05:51:02 +00:00
} else {
// Object.to_send is set to False
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "Object: %s not being sent.", object.uuid.c_str());
2022-03-30 05:51:02 +00:00
}
2022-01-21 13:07:33 +00:00
}
2022-04-01 07:39:00 +00:00
cpm . cpmParameters . numberOfPerceivedObjects = perceivedObjectsCount ;
2022-01-21 13:07:33 +00:00
} else {
cpm . cpmParameters . perceivedObjectContainer = NULL ;
2022-03-30 09:04:41 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::send] Empty POC");
2021-11-10 15:21:32 +00:00
}
2022-04-01 07:39:00 +00:00
insertCpmToCpmTable ( message , ( char * ) " cpm_sent " ) ;
2022-01-21 13:07:33 +00:00
Application : : DownPacketPtr packet { new DownPacket ( ) } ;
std : : unique_ptr < geonet : : DownPacket > payload { new geonet : : DownPacket ( ) } ;
2021-11-17 08:45:25 +00:00
2022-01-21 13:07:33 +00:00
payload - > layer ( OsiLayer : : Application ) = std : : move ( message ) ;
2021-11-17 08:45:25 +00:00
2022-01-21 13:07:33 +00:00
Application : : DataRequest request ;
request . its_aid = aid : : CP ;
request . transport_type = geonet : : TransportType : : SHB ;
request . communication_profile = geonet : : CommunicationProfile : : ITS_G5 ;
2021-11-17 08:45:25 +00:00
2022-01-21 13:07:33 +00:00
Application : : DataConfirm confirm = Application : : request ( request , std : : move ( payload ) , node_ ) ;
2021-11-17 08:45:25 +00:00
2022-01-21 13:07:33 +00:00
if ( ! confirm . accepted ( ) ) {
throw std : : runtime_error ( " [CpmApplication::send] CPM application data request failed " ) ;
}
sending_ = false ;
rclcpp : : Time current_time = node_ - > now ( ) ;
2022-02-27 03:26:28 +00:00
// RCLCPP_INFO(node_->get_logger(), "[CpmApplication::send] [measure] T_depart_r1 %ld", current_time.nanoseconds());
2021-11-17 08:45:25 +00:00
2022-04-01 05:51:10 +00:00
+ + cpm_num_ ;
2022-01-21 13:07:33 +00:00
}
2021-10-27 21:56:21 +00:00
}
2022-04-01 06:07:11 +00:00
void CpmApplication : : createTables ( ) {
2022-04-01 06:33:41 +00:00
sqlite3 * db = NULL ;
char * err = NULL ;
int ret = sqlite3_open ( " ./src/autoware_v2x/db/autoware_v2x.db " , & db ) ;
if ( ret ! = SQLITE_OK ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " DB File Open Error " ) ;
return ;
}
char * sql_command ;
2022-04-01 07:39:00 +00:00
sql_command = ( char * ) " create table if not exists cpm_sent(id INTEGER PRIMARY KEY, timestamp BIGINT, perceivedObjectCount INTEGER); " ;
2022-04-01 06:33:41 +00:00
ret = sqlite3_exec ( db , sql_command , NULL , NULL , & err ) ;
if ( ret ! = SQLITE_OK ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " DB Execution Error " ) ;
sqlite3_close ( db ) ;
sqlite3_free ( err ) ;
return ;
}
2022-04-01 07:39:00 +00:00
sql_command = ( char * ) " create table if not exists cpm_received(id INTEGER PRIMARY KEY, timestamp BIGINT, perceivedObjectCount INTEGER); " ;
2022-04-01 06:33:41 +00:00
ret = sqlite3_exec ( db , sql_command , NULL , NULL , & err ) ;
if ( ret ! = SQLITE_OK ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " DB Execution Error " ) ;
sqlite3_close ( db ) ;
sqlite3_free ( err ) ;
return ;
}
2022-04-01 06:07:11 +00:00
2022-04-01 06:33:41 +00:00
sqlite3_close ( db ) ;
RCLCPP_INFO ( node_ - > get_logger ( ) , " CpmApplication::createTables Finished " ) ;
2022-04-01 06:07:11 +00:00
}
void CpmApplication : : insertCpmToCpmTable ( vanetza : : asn1 : : Cpm cpm , char * table_name ) {
2022-04-01 07:39:00 +00:00
sqlite3 * db = NULL ;
char * err = NULL ;
2022-04-01 06:07:11 +00:00
2022-04-01 07:39:00 +00:00
int ret = sqlite3_open ( " ./src/autoware_v2x/db/autoware_v2x.db " , & db ) ;
if ( ret ! = SQLITE_OK ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " DB File Open Error " ) ;
return ;
}
2022-04-06 02:10:25 +00:00
int64_t timestamp = std : : chrono : : duration_cast < std : : chrono : : milliseconds > ( std : : chrono : : system_clock : : now ( ) . time_since_epoch ( ) ) . count ( ) ;
2022-04-01 07:39:00 +00:00
int perceivedObjectCount = 0 ;
if ( cpm - > cpm . cpmParameters . numberOfPerceivedObjects ) {
perceivedObjectCount = cpm - > cpm . cpmParameters . numberOfPerceivedObjects ;
}
std : : stringstream sql_command ;
sql_command < < " insert into " < < table_name < < " (timestamp, perceivedObjectCount) values ( " < < timestamp < < " , " < < perceivedObjectCount < < " ); " ;
ret = sqlite3_exec ( db , sql_command . str ( ) . c_str ( ) , NULL , NULL , & err ) ;
if ( ret ! = SQLITE_OK ) {
RCLCPP_INFO ( node_ - > get_logger ( ) , " DB Execution Error " ) ;
sqlite3_close ( db ) ;
sqlite3_free ( err ) ;
return ;
}
sqlite3_close ( db ) ;
// RCLCPP_INFO(node_->get_logger(), "CpmApplication::insertCpmToCpmTable Finished");
2022-04-01 06:07:11 +00:00
}
2021-11-10 15:21:32 +00:00
}