newer files
This commit is contained in:
commit
fd33d987ba
|
@ -0,0 +1,61 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
project(autoware_v2x)
|
||||
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
# Default to C99
|
||||
if(NOT CMAKE_C_STANDARD)
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
endif()
|
||||
|
||||
# Default to C++14
|
||||
if(NOT CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
# find dependencies
|
||||
find_package(ament_cmake_auto REQUIRED)
|
||||
set(VANETZA_INSTALL ON)
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
find_package(Vanetza REQUIRED)
|
||||
find_package(GeographicLib 1.37 REQUIRED)
|
||||
find_package(Boost COMPONENTS thread REQUIRED)
|
||||
ament_auto_find_build_dependencies()
|
||||
find_package(std_msgs REQUIRED)
|
||||
|
||||
include_directories(
|
||||
include
|
||||
)
|
||||
|
||||
ament_auto_add_library(autoware_v2x SHARED
|
||||
src/cpm_sender.cpp
|
||||
src/application.cpp
|
||||
src/cpm_application.cpp
|
||||
src/ethernet_device.cpp
|
||||
src/link_layer.cpp
|
||||
src/raw_socket_link.cpp
|
||||
src/router_context.cpp
|
||||
src/dcc_passthrough.cpp
|
||||
src/time_trigger.cpp
|
||||
src/positioning.cpp
|
||||
src/security.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(autoware_v2x Vanetza::vanetza ${GeographicLib_LIBRARIES} Boost::thread)
|
||||
|
||||
rclcpp_components_register_node(autoware_v2x
|
||||
PLUGIN "v2x::V2XNode"
|
||||
EXECUTABLE autoware_v2x_node
|
||||
)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
find_package(ament_lint_auto REQUIRED)
|
||||
ament_lint_auto_find_test_dependencies()
|
||||
endif()
|
||||
|
||||
ament_auto_package(INSTALL_TO_SHARE
|
||||
launch
|
||||
)
|
|
@ -0,0 +1,54 @@
|
|||
option(GeographicLib_PREFER_PACKAGE_CONFIG "Prefer CMake config mode" ON)
|
||||
mark_as_advanced(GeographicLib_PREFER_PACKAGE_CONFIG)
|
||||
|
||||
if(GeographicLib_PREFER_PACKAGE_CONFIG)
|
||||
find_package(GeographicLib ${GeographicLib_FIND_VERSION} QUIET CONFIG)
|
||||
if (GeographicLib_FOUND)
|
||||
message(STATUS "GeographicLib: using found CMake configuration")
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
message(STATUS "GeographicLib: using lookup code by Vanetza")
|
||||
|
||||
find_path(GeographicLib_INCLUDE_DIR NAMES GeographicLib/Config.h DOC "GeographicLib include directory")
|
||||
find_library(GeographicLib_LIBRARY_RELEASE NAMES Geographic DOC "GeographicLib library (release)")
|
||||
find_library(GeographicLib_LIBRARY_DEBUG NAMES Geographic_d DOC "GeographicLib library (debug)")
|
||||
|
||||
include(SelectLibraryConfigurations)
|
||||
select_library_configurations(GeographicLib)
|
||||
|
||||
if(GeographicLib_INCLUDE_DIR)
|
||||
file(STRINGS ${GeographicLib_INCLUDE_DIR}/GeographicLib/Config.h _config_version REGEX "GEOGRAPHICLIB_VERSION_STRING")
|
||||
string(REGEX MATCH "\"([0-9.]+)\"$" _match_version ${_config_version})
|
||||
set(GeographicLib_VERSION_STRING ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GeographicLib
|
||||
REQUIRED_VARS GeographicLib_INCLUDE_DIR GeographicLib_LIBRARY
|
||||
FOUND_VAR GeographicLib_FOUND
|
||||
VERSION_VAR GeographicLib_VERSION_STRING)
|
||||
|
||||
if(GeographicLib_FOUND AND NOT TARGET GeographicLib::GeographicLib)
|
||||
add_library(GeographicLib::GeographicLib UNKNOWN IMPORTED)
|
||||
set_target_properties(GeographicLib::GeographicLib PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${GeographicLib_INCLUDE_DIR}"
|
||||
IMPORTED_LOCATION "${GeographicLib_LIBRARY}"
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX")
|
||||
if(EXISTS "${GeographicLib_LIBRARY_RELEASE}")
|
||||
set_property(TARGET GeographicLib::GeographicLib APPEND PROPERTY
|
||||
IMPORTED_CONFIGURATIONS RELEASE)
|
||||
set_target_properties(GeographicLib::GeographicLib PROPERTIES
|
||||
IMPORTED_LOCATION_RELEASE "${GeographicLib_LIBRARY_RELEASE}")
|
||||
endif()
|
||||
if(EXISTS "${GeographicLib_LIBRARY_DEBUG}")
|
||||
set_property(TARGET GeographicLib::GeographicLib APPEND PROPERTY
|
||||
IMPORTED_CONFIGURATIONS DEBUG)
|
||||
set_target_properties(GeographicLib::GeographicLib PROPERTIES
|
||||
IMPORTED_LOCATION_DEBUG "${GeographicLib_LIBRARY_DEBUG}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(GeographicLib_INCLUDE_DIR GeographicLib_LIBRARY)
|
||||
set(GeographicLib_INCLUDE_DIRS ${GeographicLib_INCLUDE_DIR})
|
||||
# GeographicLib_LIBRARIES is set by SelectLibraryConfigurations
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef APPLICATION_HPP_PSIGPUTG
|
||||
#define APPLICATION_HPP_PSIGPUTG
|
||||
|
||||
#include <vanetza/btp/data_interface.hpp>
|
||||
#include <vanetza/btp/data_indication.hpp>
|
||||
#include <vanetza/btp/data_request.hpp>
|
||||
#include <vanetza/btp/port_dispatcher.hpp>
|
||||
#include <vanetza/geonet/data_confirm.hpp>
|
||||
#include <vanetza/geonet/router.hpp>
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
class Application : public vanetza::btp::IndicationInterface
|
||||
{
|
||||
public:
|
||||
using DataConfirm = vanetza::geonet::DataConfirm;
|
||||
using DataIndication = vanetza::btp::DataIndication;
|
||||
using DataRequest = vanetza::btp::DataRequestGeoNetParams;
|
||||
using DownPacketPtr = vanetza::geonet::Router::DownPacketPtr;
|
||||
using PortType = vanetza::btp::port_type;
|
||||
using PromiscuousHook = vanetza::btp::PortDispatcher::PromiscuousHook;
|
||||
using UpPacketPtr = vanetza::geonet::Router::UpPacketPtr;
|
||||
|
||||
Application() = default;
|
||||
Application(const Application &) = delete;
|
||||
Application &operator=(const Application &) = delete;
|
||||
virtual ~Application() = default;
|
||||
|
||||
virtual PortType port() = 0;
|
||||
virtual PromiscuousHook *promiscuous_hook();
|
||||
|
||||
protected:
|
||||
DataConfirm request(const DataRequest &, DownPacketPtr, rclcpp::Node*);
|
||||
|
||||
private:
|
||||
friend class RouterContext;
|
||||
vanetza::geonet::GbcDataRequest request_gbc(const DataRequest &);
|
||||
vanetza::geonet::ShbDataRequest request_shb(const DataRequest &);
|
||||
vanetza::geonet::Router *router_;
|
||||
};
|
||||
|
||||
#endif /* APPLICATION_HPP_PSIGPUTG */
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef CPM_APPLICATION_HPP_EUIC2VFR
|
||||
#define CPM_APPLICATION_HPP_EUIC2VFR
|
||||
|
||||
#include "autoware_v2x/application.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include "autoware_perception_msgs/msg/dynamic_object_array.hpp"
|
||||
#include "autoware_v2x/positioning.hpp"
|
||||
|
||||
class CpmApplication : public Application
|
||||
{
|
||||
public:
|
||||
CpmApplication(rclcpp::Node *node);
|
||||
PortType port() override;
|
||||
void indicate(const DataIndication &, UpPacketPtr) override;
|
||||
void send(const autoware_perception_msgs::msg::DynamicObjectArray::ConstSharedPtr, rclcpp::Node *, double, double);
|
||||
|
||||
private:
|
||||
rclcpp::Node* node_;
|
||||
};
|
||||
|
||||
#endif /* CPM_APPLICATION_HPP_EUIC2VFR */
|
|
@ -0,0 +1,48 @@
|
|||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "std_msgs/msg/string.hpp"
|
||||
#include "autoware_perception_msgs/msg/dynamic_object_array.hpp"
|
||||
#include "tf2_msgs/msg/tf_message.hpp"
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include "autoware_v2x/cpm_application.hpp"
|
||||
#include "autoware_v2x/time_trigger.hpp"
|
||||
#include "autoware_v2x/link_layer.hpp"
|
||||
#include "autoware_v2x/ethernet_device.hpp"
|
||||
#include "autoware_v2x/positioning.hpp"
|
||||
#include "autoware_v2x/security.hpp"
|
||||
#include "autoware_v2x/router_context.hpp"
|
||||
|
||||
namespace v2x
|
||||
{
|
||||
class V2XNode : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
explicit V2XNode(const rclcpp::NodeOptions &node_options);
|
||||
|
||||
private:
|
||||
void objectsCallback(
|
||||
const autoware_perception_msgs::msg::DynamicObjectArray::ConstSharedPtr msg);
|
||||
void tfCallback(const tf2_msgs::msg::TFMessage::ConstSharedPtr msg);
|
||||
|
||||
friend class CpmApplication;
|
||||
friend class Application;
|
||||
rclcpp::Subscription<autoware_perception_msgs::msg::DynamicObjectArray>::SharedPtr subscription_;
|
||||
rclcpp::Subscription<tf2_msgs::msg::TFMessage>::SharedPtr subscription_pos_;
|
||||
|
||||
std::unique_ptr<CpmApplication> cp_;
|
||||
std::unique_ptr<Application> app_;
|
||||
boost::asio::io_service io_service_;
|
||||
TimeTrigger trigger_;
|
||||
const char *device_name_;
|
||||
EthernetDevice device_;
|
||||
vanetza::MacAddress mac_address_;
|
||||
std::unique_ptr<LinkLayer> link_layer_;
|
||||
vanetza::geonet::MIB mib_;
|
||||
std::unique_ptr<vanetza::PositionProvider> positioning_;
|
||||
std::unique_ptr<vanetza::security::SecurityEntity> security_;
|
||||
RouterContext context_;
|
||||
|
||||
double pos_lat_;
|
||||
double pos_lon_;
|
||||
|
||||
};
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef DCC_PASSTHROUGH_HPP_GSDFESAE
|
||||
#define DCC_PASSTHROUGH_HPP_GSDFESAE
|
||||
|
||||
#include "autoware_v2x/time_trigger.hpp"
|
||||
#include <vanetza/access/interface.hpp>
|
||||
#include <vanetza/dcc/data_request.hpp>
|
||||
#include <vanetza/dcc/interface.hpp>
|
||||
#include <vanetza/net/cohesive_packet.hpp>
|
||||
|
||||
class DccPassthrough : public vanetza::dcc::RequestInterface
|
||||
{
|
||||
public:
|
||||
DccPassthrough(vanetza::access::Interface&, TimeTrigger& trigger);
|
||||
|
||||
void request(const vanetza::dcc::DataRequest& request, std::unique_ptr<vanetza::ChunkPacket> packet) override;
|
||||
|
||||
void allow_packet_flow(bool allow);
|
||||
bool allow_packet_flow();
|
||||
|
||||
private:
|
||||
vanetza::access::Interface& access_;
|
||||
TimeTrigger& trigger_;
|
||||
bool allow_packet_flow_ = true;
|
||||
};
|
||||
|
||||
#endif /* DCC_PASSTHROUGH_HPP_GSDFESAE */
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef ETHERNET_DEVICE_HPP_NEVC5DAY
|
||||
#define ETHERNET_DEVICE_HPP_NEVC5DAY
|
||||
|
||||
#include <vanetza/net/mac_address.hpp>
|
||||
#include <boost/asio/generic/raw_protocol.hpp>
|
||||
#include <string>
|
||||
|
||||
class EthernetDevice
|
||||
{
|
||||
public:
|
||||
using protocol = boost::asio::generic::raw_protocol;
|
||||
|
||||
EthernetDevice(const char* devname);
|
||||
EthernetDevice(const EthernetDevice&) = delete;
|
||||
EthernetDevice& operator=(const EthernetDevice&) = delete;
|
||||
~EthernetDevice();
|
||||
|
||||
protocol::endpoint endpoint(int family) const;
|
||||
vanetza::MacAddress address() const;
|
||||
|
||||
private:
|
||||
int index() const;
|
||||
|
||||
int local_socket_;
|
||||
std::string interface_name_;
|
||||
};
|
||||
|
||||
#endif /* ETHERNET_DEVICE_HPP_NEVC5DAY */
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef LINK_LAYER_HPP_FGEK0QTH
|
||||
#define LINK_LAYER_HPP_FGEK0QTH
|
||||
|
||||
#include "autoware_v2x/ethernet_device.hpp"
|
||||
#include <vanetza/access/interface.hpp>
|
||||
#include <vanetza/net/cohesive_packet.hpp>
|
||||
#include <vanetza/net/ethernet_header.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class LinkLayerIndication
|
||||
{
|
||||
public:
|
||||
using IndicationCallback = std::function<void(vanetza::CohesivePacket&&, const vanetza::EthernetHeader&)>;
|
||||
|
||||
virtual void indicate(IndicationCallback) = 0;
|
||||
virtual ~LinkLayerIndication() = default;
|
||||
};
|
||||
|
||||
class LinkLayer : public vanetza::access::Interface, public LinkLayerIndication
|
||||
{
|
||||
};
|
||||
|
||||
std::unique_ptr<LinkLayer>
|
||||
create_link_layer(boost::asio::io_service&, const EthernetDevice&, const std::string& name);
|
||||
|
||||
#endif /* LINK_LAYER_HPP_FGEK0QTH */
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef POSITIONING_HPP_VZRIW7PB
|
||||
#define POSITIONING_HPP_VZRIW7PB
|
||||
|
||||
#include <vanetza/common/position_provider.hpp>
|
||||
#include <vanetza/common/runtime.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
class PositioningException : public std::runtime_error
|
||||
{
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
std::unique_ptr<vanetza::PositionProvider>
|
||||
create_position_provider(boost::asio::io_service &, const vanetza::Runtime &);
|
||||
|
||||
#endif /* POSITIONING_HPP_VZRIW7PB */
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef RAW_SOCKET_LINK_HPP_VUXH507U
|
||||
#define RAW_SOCKET_LINK_HPP_VUXH507U
|
||||
|
||||
#include "autoware_v2x/link_layer.hpp"
|
||||
#include <vanetza/access/interface.hpp>
|
||||
#include <vanetza/net/ethernet_header.hpp>
|
||||
#include <boost/asio/generic/raw_protocol.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
class RawSocketLink : public LinkLayer
|
||||
{
|
||||
public:
|
||||
RawSocketLink(boost::asio::generic::raw_protocol::socket&&);
|
||||
void request(const vanetza::access::DataRequest&, std::unique_ptr<vanetza::ChunkPacket>) override;
|
||||
void indicate(IndicationCallback) override;
|
||||
|
||||
protected:
|
||||
std::size_t transmit(std::unique_ptr<vanetza::ChunkPacket>);
|
||||
virtual boost::optional<vanetza::EthernetHeader> parse_ethernet_header(vanetza::CohesivePacket&) const;
|
||||
|
||||
private:
|
||||
void do_receive();
|
||||
void on_read(const boost::system::error_code&, std::size_t);
|
||||
void pass_up(vanetza::CohesivePacket&&);
|
||||
|
||||
static constexpr std::size_t layers_ = num_osi_layers(vanetza::OsiLayer::Physical, vanetza::OsiLayer::Application);
|
||||
|
||||
boost::asio::generic::raw_protocol::socket socket_;
|
||||
std::array<vanetza::ByteBuffer, layers_> buffers_;
|
||||
IndicationCallback callback_;
|
||||
vanetza::ByteBuffer receive_buffer_;
|
||||
boost::asio::generic::raw_protocol::endpoint receive_endpoint_;
|
||||
};
|
||||
|
||||
#endif /* RAW_SOCKET_LINK_HPP_VUXH507U */
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef ROUTER_CONTEXT_HPP_KIPUYBY2
|
||||
#define ROUTER_CONTEXT_HPP_KIPUYBY2
|
||||
|
||||
#include "autoware_v2x/dcc_passthrough.hpp"
|
||||
#include "autoware_v2x/link_layer.hpp"
|
||||
#include <vanetza/btp/port_dispatcher.hpp>
|
||||
#include <vanetza/common/position_provider.hpp>
|
||||
#include <vanetza/geonet/mib.hpp>
|
||||
#include <vanetza/geonet/router.hpp>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
class Application;
|
||||
class TimeTrigger;
|
||||
|
||||
class RouterContext
|
||||
{
|
||||
public:
|
||||
RouterContext(const vanetza::geonet::MIB&, TimeTrigger&, vanetza::PositionProvider&, vanetza::security::SecurityEntity*);
|
||||
~RouterContext();
|
||||
void enable(Application*);
|
||||
void disable(Application*);
|
||||
|
||||
/**
|
||||
* Allow/disallow transmissions without GNSS position fix
|
||||
*
|
||||
* \param flag true if transmissions shall be dropped when no GNSS position fix is available
|
||||
*/
|
||||
void require_position_fix(bool flag);
|
||||
|
||||
void set_link_layer(LinkLayer*);
|
||||
void updateMIB(const vanetza::geonet::MIB&);
|
||||
|
||||
private:
|
||||
void indicate(vanetza::CohesivePacket&& packet, const vanetza::EthernetHeader& hdr);
|
||||
void log_packet_drop(vanetza::geonet::Router::PacketDropReason);
|
||||
void update_position_vector();
|
||||
void update_packet_flow(const vanetza::geonet::LongPositionVector&);
|
||||
|
||||
vanetza::geonet::MIB mib_;
|
||||
vanetza::geonet::Router router_;
|
||||
TimeTrigger& trigger_;
|
||||
vanetza::PositionProvider& positioning_;
|
||||
vanetza::btp::PortDispatcher dispatcher_;
|
||||
std::unique_ptr<DccPassthrough> request_interface_;
|
||||
std::list<Application*> applications_;
|
||||
bool require_position_fix_ = false;
|
||||
};
|
||||
|
||||
#endif /* ROUTER_CONTEXT_HPP_KIPUYBY2 */
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef SECURITY_HPP_FV13ZIYA
|
||||
#define SECURITY_HPP_FV13ZIYA
|
||||
|
||||
#include <vanetza/common/position_provider.hpp>
|
||||
#include <vanetza/common/runtime.hpp>
|
||||
#include <vanetza/security/security_entity.hpp>
|
||||
#include <boost/program_options/options_description.hpp>
|
||||
#include <boost/program_options/variables_map.hpp>
|
||||
#include <memory>
|
||||
|
||||
std::unique_ptr<vanetza::security::SecurityEntity>
|
||||
create_security_entity(const vanetza::Runtime&, vanetza::PositionProvider&);
|
||||
|
||||
#endif /* SECURITY_HPP_FV13ZIYA */
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#ifndef TIME_TRIGGER_HPP_XRPGDYXO
|
||||
#define TIME_TRIGGER_HPP_XRPGDYXO
|
||||
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include <vanetza/common/manual_runtime.hpp>
|
||||
|
||||
class TimeTrigger
|
||||
{
|
||||
public:
|
||||
TimeTrigger(boost::asio::io_service &);
|
||||
vanetza::Runtime & runtime() { return runtime_; }
|
||||
void schedule();
|
||||
|
||||
private:
|
||||
boost::posix_time::ptime now() const;
|
||||
void on_timeout(const boost::system::error_code &);
|
||||
void update_runtime();
|
||||
|
||||
boost::asio::io_service & io_service_;
|
||||
boost::asio::deadline_timer timer_;
|
||||
vanetza::ManualRuntime runtime_;
|
||||
};
|
||||
|
||||
#endif /* TIME_TRIGGER_HPP_XRPGDYXO */
|
|
@ -0,0 +1,3 @@
|
|||
<launch>
|
||||
<node pkg="autoware_v2x" exec="autoware_v2x_node" namespace="v2x" output="screen" emulate_tty="true" />
|
||||
</launch>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0"?>
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>autoware_v2x</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="yuasabe@g.ecc.u-tokyo.ac.jp">yuasabe</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<buildtool_depend>ament_cmake_auto</buildtool_depend>
|
||||
|
||||
<depend>autoware_perception_msgs</depend>
|
||||
<depend>tf2_msgs</depend>
|
||||
<depend>geometry_msgs</depend>
|
||||
<depend>rclcpp</depend>
|
||||
<depend>std_msgs</depend>
|
||||
<depend>rclcpp_components</depend>
|
||||
<depend>Vanetza</depend>
|
||||
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
</export>
|
||||
</package>
|
|
@ -0,0 +1,76 @@
|
|||
#include "autoware_v2x/application.hpp"
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include <vanetza/btp/header.hpp>
|
||||
#include <vanetza/btp/header_conversion.hpp>
|
||||
#include <cassert>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
Application::DataConfirm Application::request(const DataRequest &request, DownPacketPtr packet, rclcpp::Node* node)
|
||||
{
|
||||
// RCLCPP_INFO(node->get_logger(), "Inside Application::request 0");
|
||||
DataConfirm confirm(DataConfirm::ResultCode::Rejected_Unspecified);
|
||||
// RCLCPP_INFO(node->get_logger(), "Inside Application::request 1");
|
||||
if (packet) {
|
||||
// RCLCPP_INFO(node->get_logger(), "Inside Application::request 2");
|
||||
}
|
||||
if (router_ && packet)
|
||||
{
|
||||
// RCLCPP_INFO(node->get_logger(), "Inside Application::request 3");
|
||||
btp::HeaderB btp_header;
|
||||
btp_header.destination_port = this->port();
|
||||
btp_header.destination_port_info = host_cast<uint16_t>(0);
|
||||
packet->layer(OsiLayer::Transport) = btp_header;
|
||||
|
||||
switch (request.transport_type)
|
||||
{
|
||||
case geonet::TransportType::SHB:
|
||||
// RCLCPP_INFO(node->get_logger(), "Inside Application::request 4");
|
||||
confirm = router_->request(request_shb(request), std::move(packet));
|
||||
break;
|
||||
case geonet::TransportType::GBC:
|
||||
confirm = router_->request(request_gbc(request), std::move(packet));
|
||||
break;
|
||||
default:
|
||||
// TODO remaining transport types are not implemented
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return confirm;
|
||||
}
|
||||
|
||||
void initialize_request(const Application::DataRequest &generic, geonet::DataRequest &geonet)
|
||||
{
|
||||
geonet.upper_protocol = geonet::UpperProtocol::BTP_B;
|
||||
geonet.communication_profile = generic.communication_profile;
|
||||
geonet.its_aid = generic.its_aid;
|
||||
if (generic.maximum_lifetime)
|
||||
{
|
||||
geonet.maximum_lifetime = generic.maximum_lifetime.get();
|
||||
}
|
||||
geonet.repetition = generic.repetition;
|
||||
geonet.traffic_class = generic.traffic_class;
|
||||
}
|
||||
|
||||
geonet::GbcDataRequest Application::request_gbc(const DataRequest &generic)
|
||||
{
|
||||
assert(router_);
|
||||
geonet::GbcDataRequest gbc(router_->get_mib());
|
||||
initialize_request(generic, gbc);
|
||||
gbc.destination = boost::get<geonet::Area>(generic.destination);
|
||||
return gbc;
|
||||
}
|
||||
|
||||
geonet::ShbDataRequest Application::request_shb(const DataRequest &generic)
|
||||
{
|
||||
assert(router_);
|
||||
geonet::ShbDataRequest shb(router_->get_mib());
|
||||
initialize_request(generic, shb);
|
||||
return shb;
|
||||
}
|
||||
|
||||
Application::PromiscuousHook *Application::promiscuous_hook()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
#include "autoware_v2x/cpm_application.hpp"
|
||||
#include "autoware_v2x/positioning.hpp"
|
||||
#include "autoware_v2x/security.hpp"
|
||||
#include "autoware_v2x/link_layer.hpp"
|
||||
|
||||
#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>
|
||||
|
||||
// This is a very simple application that sends BTP-B messages with the content 0xc0ffee.
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::facilities;
|
||||
using namespace std::chrono;
|
||||
|
||||
CpmApplication::CpmApplication(rclcpp::Node *node) : node_(node)
|
||||
{
|
||||
RCLCPP_INFO(node_->get_logger(), "CpmApplication started...");
|
||||
}
|
||||
|
||||
CpmApplication::PortType CpmApplication::port()
|
||||
{
|
||||
return btp::ports::CPM;
|
||||
}
|
||||
|
||||
void CpmApplication::indicate(const DataIndication &indication, UpPacketPtr packet)
|
||||
{
|
||||
asn1::PacketVisitor<asn1::Cpm> visitor;
|
||||
std::shared_ptr<const asn1::Cpm> cpm = boost::apply_visitor(visitor, *packet);
|
||||
if (cpm) {
|
||||
RCLCPP_INFO(node_->get_logger(), "Received decodable CPM content");
|
||||
} else {
|
||||
RCLCPP_INFO(node_->get_logger(), "Received broken content");
|
||||
}
|
||||
asn1::Cpm message = *cpm;
|
||||
ItsPduHeader_t &header = message->header;
|
||||
RCLCPP_INFO(node_->get_logger(), "cpm.ItsPduHeader.messageId = %d", header.messageID);
|
||||
RCLCPP_INFO(node_->get_logger(), "cpm.ItsPduHeader.stationId = %d", header.stationID);
|
||||
|
||||
CpmManagementContainer_t &management = message->cpm.cpmParameters.managementContainer;
|
||||
double lat = management.referencePosition.latitude;
|
||||
double lon = management.referencePosition.longitude;
|
||||
RCLCPP_INFO(node_->get_logger(), "cpm.(reference position) = %f, %f", lat, lon);
|
||||
}
|
||||
|
||||
void CpmApplication::send(const autoware_perception_msgs::msg::DynamicObjectArray::ConstSharedPtr msg, rclcpp::Node *node, double pos_lat, double pos_lon)
|
||||
{
|
||||
RCLCPP_INFO(node->get_logger(), "Sending CPM...");
|
||||
// Send all objects in 1 CPM message
|
||||
vanetza::asn1::Cpm message;
|
||||
|
||||
// ITS PDU Header
|
||||
ItsPduHeader_t &header = message->header;
|
||||
header.protocolVersion = 1;
|
||||
header.messageID = 14;
|
||||
header.stationID = 1;
|
||||
|
||||
const auto time_now = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
|
||||
uint16_t gen_delta_time = time_now.count();
|
||||
|
||||
CollectivePerceptionMessage_t &cpm = message->cpm;
|
||||
cpm.generationDeltaTime = gen_delta_time * GenerationDeltaTime_oneMilliSec;
|
||||
|
||||
// auto position = positioning->position_specify(pos_lat, pos_lon);
|
||||
|
||||
CpmManagementContainer_t& management = cpm.cpmParameters.managementContainer;
|
||||
management.stationType = StationType_passengerCar;
|
||||
// management.referencePosition.latitude = pos_lat;
|
||||
// management.referencePosition.longitude = pos_lon;
|
||||
// management.referencePosition.positionConfidenceEllipse.semiMajorConfidence = 1.0;
|
||||
// management.referencePosition.positionConfidenceEllipse.semiMinorConfidence = 1.0;
|
||||
PositionFix fix;
|
||||
// fix.timestamp = time_now;
|
||||
fix.latitude = pos_lat * units::degree;
|
||||
fix.longitude = pos_lon * units::degree;
|
||||
fix.confidence.semi_major = 1.0 * units::si::meter;
|
||||
fix.confidence.semi_minor = fix.confidence.semi_major;
|
||||
copy(fix, management.referencePosition);
|
||||
|
||||
// cpm.cpmParameters.stationDataContainer = NULL;
|
||||
// cpm.cpmParameters.perceivedObjectContainer = NULL;
|
||||
cpm.cpmParameters.numberOfPerceivedObjects = msg->objects.size();
|
||||
|
||||
StationDataContainer_t*& sdc = cpm.cpmParameters.stationDataContainer;
|
||||
sdc = vanetza::asn1::allocate<StationDataContainer_t>();
|
||||
// RCLCPP_INFO(node->get_logger(), "Allocated sdc");
|
||||
sdc->present = StationDataContainer_PR_originatingVehicleContainer;
|
||||
OriginatingVehicleContainer_t& ovc = sdc->choice.originatingVehicleContainer;
|
||||
ovc.speed.speedValue = 0;
|
||||
ovc.speed.speedConfidence = 1;
|
||||
ovc.heading.headingValue = 0;
|
||||
ovc.heading.headingConfidence = 1;
|
||||
|
||||
PerceivedObjectContainer_t *&poc = cpm.cpmParameters.perceivedObjectContainer;
|
||||
poc = vanetza::asn1::allocate<PerceivedObjectContainer_t>();
|
||||
// cpm.cpmParameters.perceivedObjectContainer = poc;
|
||||
// PerceivedObjectContainer_t pocc = *poc;
|
||||
// RCLCPP_INFO(node->get_logger(), "Allocated poc");
|
||||
|
||||
for (auto object : msg->objects) {
|
||||
PerceivedObject *pObj = vanetza::asn1::allocate<PerceivedObject>();
|
||||
pObj->objectID = 1;
|
||||
pObj->timeOfMeasurement = 10;
|
||||
pObj->xDistance.value = 100;
|
||||
pObj->xDistance.confidence = 1;
|
||||
pObj->yDistance.value = 200;
|
||||
pObj->yDistance.confidence = 1;
|
||||
pObj->xSpeed.value = 5;
|
||||
pObj->xSpeed.confidence = 1;
|
||||
pObj->ySpeed.value = 0;
|
||||
pObj->ySpeed.confidence = 1;
|
||||
|
||||
ASN_SEQUENCE_ADD(poc, pObj);
|
||||
// RCLCPP_INFO(node->get_logger(), "Added one object to poc->list");
|
||||
}
|
||||
|
||||
|
||||
Application::DownPacketPtr packet{new DownPacket()};
|
||||
std::unique_ptr<geonet::DownPacket> payload { new geonet::DownPacket() };
|
||||
// std::shared_ptr<asn1::Cpm> message_p = std::make_shared<asn1::Cpm>(message);
|
||||
// std::unique_ptr<convertible::byte_buffer> buffer { new convertible::byte_buffer_impl<asn1::Cpm>(&message)};
|
||||
|
||||
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;
|
||||
|
||||
// RCLCPP_INFO(node->get_logger(), "Packet Size: %d", payload->size());
|
||||
|
||||
// RCLCPP_INFO(node->get_logger(), "Going to Application::request...");
|
||||
Application::DataConfirm confirm = Application::request(request, std::move(payload), node);
|
||||
if (!confirm.accepted())
|
||||
{
|
||||
throw std::runtime_error("CPM application data request failed");
|
||||
}
|
||||
// RCLCPP_INFO(node->get_logger(), "Application::request END");
|
||||
}
|
||||
|
||||
// void HelloApplication::schedule_timer()
|
||||
// {
|
||||
// timer_.expires_from_now(interval_);
|
||||
// timer_.async_wait(std::bind(&HelloApplication::on_timer, this, std::placeholders::_1));
|
||||
// }
|
||||
|
||||
// void HelloApplication::on_timer(const boost::system::error_code& ec)
|
||||
// {
|
||||
// if (ec != boost::asio::error::operation_aborted) {
|
||||
// DownPacketPtr packet { new DownPacket() };
|
||||
// packet->layer(OsiLayer::Application) = ByteBuffer { 0xC0, 0xFF, 0xEE };
|
||||
// DataRequest request;
|
||||
// request.transport_type = geonet::TransportType::SHB;
|
||||
// request.communication_profile = geonet::CommunicationProfile::ITS_G5;
|
||||
// request.its_aid = aid::CA;
|
||||
// auto confirm = Application::request(request, std::move(packet));
|
||||
// if (!confirm.accepted()) {
|
||||
// throw std::runtime_error("Hello application data request failed");
|
||||
// }
|
||||
|
||||
// schedule_timer();
|
||||
// }
|
||||
// }
|
|
@ -0,0 +1,123 @@
|
|||
#include "autoware_v2x/cpm_sender.hpp"
|
||||
#include "autoware_v2x/time_trigger.hpp"
|
||||
#include "autoware_v2x/router_context.hpp"
|
||||
#include "autoware_v2x/positioning.hpp"
|
||||
#include "autoware_v2x/security.hpp"
|
||||
#include "autoware_v2x/link_layer.hpp"
|
||||
#include "autoware_v2x/cpm_application.hpp"
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "std_msgs/msg/string.hpp"
|
||||
|
||||
#include <vanetza/asn1/cpm.hpp>
|
||||
#include <vanetza/facilities/cpm_functions.hpp>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <GeographicLib/UTMUPS.hpp>
|
||||
#include <GeographicLib/MGRS.hpp>
|
||||
|
||||
namespace gn = vanetza::geonet;
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::facilities;
|
||||
using namespace std::chrono;
|
||||
|
||||
namespace v2x
|
||||
{
|
||||
V2XNode::V2XNode(const rclcpp::NodeOptions &node_options) :
|
||||
rclcpp::Node("autoware_v2x_node", node_options),
|
||||
io_service_(),
|
||||
trigger_(io_service_),
|
||||
device_name_("wlp4s0"),
|
||||
device_(device_name_),
|
||||
mac_address_(device_.address()),
|
||||
link_layer_(create_link_layer(io_service_, device_, "ethernet")),
|
||||
positioning_(create_position_provider(io_service_, trigger_.runtime())),
|
||||
security_(create_security_entity(trigger_.runtime(), *positioning_)),
|
||||
mib_(),
|
||||
context_(mib_, trigger_, *positioning_, security_.get()),
|
||||
cp_(new CpmApplication(this)),
|
||||
app_()
|
||||
{
|
||||
using std::placeholders::_1;
|
||||
subscription_ = this->create_subscription<autoware_perception_msgs::msg::DynamicObjectArray>("/perception/object_recognition/detection/objects", 10, std::bind(&V2XNode::objectsCallback, this, _1));
|
||||
|
||||
subscription_pos_ = this->create_subscription<tf2_msgs::msg::TFMessage>("/tf", 10, std::bind(&V2XNode::tfCallback, this, _1));
|
||||
RCLCPP_INFO(get_logger(), "V2X Node Launched");
|
||||
|
||||
// device_name_ = "wlp4s0";
|
||||
// device_(device_name_);
|
||||
// mac_address_ = device_.address();
|
||||
|
||||
std::stringstream sout;
|
||||
sout << mac_address_;
|
||||
RCLCPP_INFO(get_logger(), "MAC Address: '%s'", sout.str().c_str());
|
||||
|
||||
// trigger_(io_service_);
|
||||
|
||||
// link_layer_ = create_link_layer(io_service_, device_, "ethernet");
|
||||
mib_.itsGnLocalGnAddr.mid(mac_address_);
|
||||
mib_.itsGnLocalGnAddr.is_manually_configured(true);
|
||||
mib_.itsGnLocalAddrConfMethod = geonet::AddrConfMethod::Managed;
|
||||
mib_.itsGnSecurity = false;
|
||||
mib_.itsGnProtocolVersion = 1;
|
||||
|
||||
// context_.router_.set_address(mib_.itsGnLocalGnAddr);
|
||||
context_.updateMIB(mib_);
|
||||
|
||||
// positioning_ = create_position_provider(io_service_, trigger_.runtime());
|
||||
// security_ = create_security_entity(trigger_.runtime(), *positioning_);
|
||||
|
||||
// RouterContext context(mib_, trigger_, *positioning_, security_.get());
|
||||
// RouterContext context_(mib_, trigger_, *positioning_, security_.get());
|
||||
context_.set_link_layer(link_layer_.get());
|
||||
|
||||
// std::unique_ptr<CpmApplication> cp_ { new CpmApplication(this) };
|
||||
// app_ = std::move(cp_);
|
||||
|
||||
context_.enable(cp_.get());
|
||||
|
||||
|
||||
// io_service_.run();
|
||||
|
||||
// // Print MAC Address to logger
|
||||
// std::stringstream sout;
|
||||
// sout << mac_address;
|
||||
// RCLCPP_INFO(get_logger(), "MAC Address: '%s'", sout.str().c_str());
|
||||
}
|
||||
|
||||
void V2XNode::objectsCallback(const autoware_perception_msgs::msg::DynamicObjectArray::ConstSharedPtr msg)
|
||||
{
|
||||
// RCLCPP_INFO(get_logger(), "I heard: '%s'", msg->data.c_str());
|
||||
RCLCPP_INFO(get_logger(), "V2X: %d objects detected!", msg->objects.size());
|
||||
// Send CPM
|
||||
cp_->send(msg, this, pos_lat_, pos_lon_);
|
||||
}
|
||||
|
||||
void V2XNode::tfCallback(const tf2_msgs::msg::TFMessage::ConstSharedPtr msg) {
|
||||
// RCLCPP_INFO(get_logger(), "Ego Position: (%f, %f, %f)", msg->transforms[0].transform.translation.x, msg->transforms[0].transform.translation.y, msg->transforms[0].transform.translation.z);
|
||||
|
||||
float x = msg->transforms[0].transform.translation.x;
|
||||
float y = msg->transforms[0].transform.translation.y;
|
||||
float z = msg->transforms[0].transform.translation.z;
|
||||
|
||||
char mgrs[20];
|
||||
int zone, prec;
|
||||
bool northp;
|
||||
double x_mgrs, y_mgrs;
|
||||
double lat, lon;
|
||||
sprintf(mgrs, "54SVE%.5d%.5d", (int)x, (int)y);
|
||||
RCLCPP_INFO(get_logger(), "MGRS: %s", mgrs);
|
||||
|
||||
GeographicLib::MGRS::Reverse(mgrs, zone, northp, x_mgrs, y_mgrs, prec);
|
||||
GeographicLib::UTMUPS::Reverse(zone, northp, x_mgrs, y_mgrs, lat, lon);
|
||||
|
||||
pos_lat_ = lat;
|
||||
pos_lon_ = lon;
|
||||
|
||||
RCLCPP_INFO(get_logger(), "Ego Position Lat/Lon: %f, %f", lat, lon);
|
||||
}
|
||||
}
|
||||
|
||||
#include "rclcpp_components/register_node_macro.hpp"
|
||||
RCLCPP_COMPONENTS_REGISTER_NODE(v2x::V2XNode)
|
|
@ -0,0 +1,126 @@
|
|||
#include "autoware_v2x/cpm_sender.hpp"
|
||||
#include "autoware_v2x/time_trigger.hpp"
|
||||
#include "autoware_v2x/router_context.hpp"
|
||||
#include "autoware_v2x/positioning.hpp"
|
||||
#include "autoware_v2x/security.hpp"
|
||||
#include "autoware_v2x/link_layer.hpp"
|
||||
#include "autoware_v2x/cpm_application.hpp"
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "std_msgs/msg/string.hpp"
|
||||
|
||||
#include <vanetza/asn1/cpm.hpp>
|
||||
#include <vanetza/facilities/cpm_functions.hpp>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <GeographicLib/UTMUPS.hpp>
|
||||
#include <GeographicLib/MGRS.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
namespace gn = vanetza::geonet;
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::facilities;
|
||||
using namespace std::chrono;
|
||||
|
||||
namespace v2x
|
||||
{
|
||||
V2XNode::V2XNode(const rclcpp::NodeOptions &node_options) :
|
||||
rclcpp::Node("autoware_v2x_node", node_options),
|
||||
io_service_(),
|
||||
trigger_(io_service_),
|
||||
device_name_("wlp4s0"),
|
||||
device_(device_name_),
|
||||
mac_address_(device_.address()),
|
||||
link_layer_(create_link_layer(io_service_, device_, "ethernet")),
|
||||
positioning_(create_position_provider(io_service_, trigger_.runtime())),
|
||||
security_(create_security_entity(trigger_.runtime(), *positioning_)),
|
||||
mib_(),
|
||||
cp_(new CpmApplication(this)),
|
||||
context_(mib_, trigger_, *positioning_, security_.get()),
|
||||
app_()
|
||||
{
|
||||
using std::placeholders::_1;
|
||||
subscription_ = this->create_subscription<autoware_perception_msgs::msg::DynamicObjectArray>("/perception/object_recognition/detection/objects", 10, std::bind(&V2XNode::objectsCallback, this, _1));
|
||||
|
||||
subscription_pos_ = this->create_subscription<tf2_msgs::msg::TFMessage>("/tf", 10, std::bind(&V2XNode::tfCallback, this, _1));
|
||||
RCLCPP_INFO(get_logger(), "V2X Node Launched");
|
||||
|
||||
// device_name_ = "wlp4s0";
|
||||
// device_(device_name_);
|
||||
// mac_address_ = device_.address();
|
||||
|
||||
std::stringstream sout;
|
||||
sout << mac_address_;
|
||||
RCLCPP_INFO(get_logger(), "MAC Address: '%s'", sout.str().c_str());
|
||||
|
||||
// trigger_(io_service_);
|
||||
|
||||
// link_layer_ = create_link_layer(io_service_, device_, "ethernet");
|
||||
mib_.itsGnLocalGnAddr.mid(mac_address_);
|
||||
mib_.itsGnLocalGnAddr.is_manually_configured(true);
|
||||
mib_.itsGnLocalAddrConfMethod = geonet::AddrConfMethod::Managed;
|
||||
mib_.itsGnSecurity = false;
|
||||
mib_.itsGnProtocolVersion = 1;
|
||||
|
||||
// context_(mib_, trigger_, *positioning_, security_.get()),
|
||||
// context_.router_.set_address(mib_.itsGnLocalGnAddr);
|
||||
context_.updateMIB(mib_);
|
||||
|
||||
// positioning_ = create_position_provider(io_service_, trigger_.runtime());
|
||||
// security_ = create_security_entity(trigger_.runtime(), *positioning_);
|
||||
|
||||
// RouterContext context_(mib_, trigger_, *positioning_, security_.get());
|
||||
// RouterContext context_(mib_, trigger_, *positioning_, security_.get());
|
||||
context_.set_link_layer(link_layer_.get());
|
||||
|
||||
// std::unique_ptr<CpmApplication> cp_ { new CpmApplication(this) };
|
||||
// app_ = std::move(cp_);
|
||||
|
||||
context_.enable(cp_.get());
|
||||
|
||||
|
||||
// io_service_.run();
|
||||
boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
|
||||
|
||||
// // Print MAC Address to logger
|
||||
// std::stringstream sout;
|
||||
// sout << mac_address;
|
||||
// RCLCPP_INFO(get_logger(), "MAC Address: '%s'", sout.str().c_str());
|
||||
}
|
||||
|
||||
void V2XNode::objectsCallback(const autoware_perception_msgs::msg::DynamicObjectArray::ConstSharedPtr msg)
|
||||
{
|
||||
// RCLCPP_INFO(get_logger(), "I heard: '%s'", msg->data.c_str());
|
||||
RCLCPP_INFO(get_logger(), "V2X: %d objects detected!", msg->objects.size());
|
||||
// Send CPM
|
||||
cp_->send(msg, this, pos_lat_, pos_lon_);
|
||||
}
|
||||
|
||||
void V2XNode::tfCallback(const tf2_msgs::msg::TFMessage::ConstSharedPtr msg) {
|
||||
// RCLCPP_INFO(get_logger(), "Ego Position: (%f, %f, %f)", msg->transforms[0].transform.translation.x, msg->transforms[0].transform.translation.y, msg->transforms[0].transform.translation.z);
|
||||
|
||||
float x = msg->transforms[0].transform.translation.x;
|
||||
float y = msg->transforms[0].transform.translation.y;
|
||||
float z = msg->transforms[0].transform.translation.z;
|
||||
|
||||
char mgrs[20];
|
||||
int zone, prec;
|
||||
bool northp;
|
||||
double x_mgrs, y_mgrs;
|
||||
double lat, lon;
|
||||
sprintf(mgrs, "54SVE%.5d%.5d", (int)x, (int)y);
|
||||
RCLCPP_INFO(get_logger(), "MGRS: %s", mgrs);
|
||||
|
||||
GeographicLib::MGRS::Reverse(mgrs, zone, northp, x_mgrs, y_mgrs, prec);
|
||||
GeographicLib::UTMUPS::Reverse(zone, northp, x_mgrs, y_mgrs, lat, lon);
|
||||
|
||||
pos_lat_ = lat;
|
||||
pos_lon_ = lon;
|
||||
|
||||
RCLCPP_INFO(get_logger(), "Ego Position Lat/Lon: %f, %f", lat, lon);
|
||||
}
|
||||
}
|
||||
|
||||
#include "rclcpp_components/register_node_macro.hpp"
|
||||
RCLCPP_COMPONENTS_REGISTER_NODE(v2x::V2XNode)
|
|
@ -0,0 +1,36 @@
|
|||
#include "autoware_v2x/dcc_passthrough.hpp"
|
||||
#include <iostream>
|
||||
#include <vanetza/access/data_request.hpp>
|
||||
#include <vanetza/dcc/data_request.hpp>
|
||||
#include <vanetza/dcc/interface.hpp>
|
||||
#include <vanetza/dcc/mapping.hpp>
|
||||
#include <vanetza/net/chunk_packet.hpp>
|
||||
#include "autoware_v2x/time_trigger.hpp"
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
DccPassthrough::DccPassthrough(access::Interface & access, TimeTrigger & trigger)
|
||||
: access_(access), trigger_(trigger)
|
||||
{
|
||||
}
|
||||
|
||||
void DccPassthrough::request(const dcc::DataRequest & request, std::unique_ptr<ChunkPacket> packet)
|
||||
{
|
||||
if (!allow_packet_flow_) {
|
||||
std::cout << "ignored request because packet flow is suppressed\n";
|
||||
return;
|
||||
}
|
||||
|
||||
trigger_.schedule();
|
||||
|
||||
access::DataRequest acc_req;
|
||||
acc_req.ether_type = request.ether_type;
|
||||
acc_req.source_addr = request.source;
|
||||
acc_req.destination_addr = request.destination;
|
||||
acc_req.access_category = dcc::map_profile_onto_ac(request.dcc_profile);
|
||||
access_.request(acc_req, std::move(packet));
|
||||
}
|
||||
|
||||
void DccPassthrough::allow_packet_flow(bool allow) { allow_packet_flow_ = allow; }
|
||||
|
||||
bool DccPassthrough::allow_packet_flow() { return allow_packet_flow_; }
|
|
@ -0,0 +1,58 @@
|
|||
#include "autoware_v2x/ethernet_device.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <system_error>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static void initialize(ifreq& request, const char* interface_name)
|
||||
{
|
||||
std::memset(&request, 0, sizeof(ifreq));
|
||||
std::strncpy(request.ifr_name, interface_name, IF_NAMESIZE);
|
||||
request.ifr_name[IF_NAMESIZE - 1] = '\0';
|
||||
}
|
||||
|
||||
EthernetDevice::EthernetDevice(const char* devname) :
|
||||
local_socket_(::socket(AF_LOCAL, SOCK_DGRAM, 0)),
|
||||
interface_name_(devname)
|
||||
{
|
||||
if (!local_socket_) {
|
||||
throw std::system_error(errno, std::system_category());
|
||||
}
|
||||
}
|
||||
|
||||
EthernetDevice::~EthernetDevice()
|
||||
{
|
||||
if (local_socket_ >= 0)
|
||||
::close(local_socket_);
|
||||
}
|
||||
|
||||
EthernetDevice::protocol::endpoint EthernetDevice::endpoint(int family) const
|
||||
{
|
||||
sockaddr_ll socket_address = {0};
|
||||
socket_address.sll_family = family;
|
||||
socket_address.sll_protocol = htons(ETH_P_ALL);
|
||||
socket_address.sll_ifindex = index();
|
||||
return protocol::endpoint(&socket_address, sizeof(sockaddr_ll));
|
||||
}
|
||||
|
||||
int EthernetDevice::index() const
|
||||
{
|
||||
ifreq data;
|
||||
initialize(data, interface_name_.c_str());
|
||||
::ioctl(local_socket_, SIOCGIFINDEX, &data);
|
||||
return data.ifr_ifindex;
|
||||
}
|
||||
|
||||
vanetza::MacAddress EthernetDevice::address() const
|
||||
{
|
||||
ifreq data;
|
||||
initialize(data, interface_name_.c_str());
|
||||
::ioctl(local_socket_, SIOCGIFHWADDR, &data);
|
||||
|
||||
vanetza::MacAddress addr;
|
||||
std::copy_n(data.ifr_hwaddr.sa_data, addr.octets.size(), addr.octets.data());
|
||||
return addr;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#include "autoware_v2x/link_layer.hpp"
|
||||
#include <boost/asio/generic/raw_protocol.hpp>
|
||||
#include <vanetza/access/ethertype.hpp>
|
||||
#include "autoware_v2x/raw_socket_link.hpp"
|
||||
|
||||
std::unique_ptr<LinkLayer> create_link_layer(
|
||||
boost::asio::io_service & io_service, const EthernetDevice & device, const std::string & name)
|
||||
{
|
||||
std::unique_ptr<LinkLayer> link_layer;
|
||||
|
||||
if (name == "ethernet") {
|
||||
boost::asio::generic::raw_protocol raw_protocol(
|
||||
AF_PACKET, vanetza::access::ethertype::GeoNetworking.net());
|
||||
boost::asio::generic::raw_protocol::socket raw_socket(io_service, raw_protocol);
|
||||
raw_socket.bind(device.endpoint(AF_PACKET));
|
||||
link_layer.reset(new RawSocketLink{std::move(raw_socket)});
|
||||
}
|
||||
|
||||
// Removed Cohda and UDP Support
|
||||
|
||||
return link_layer;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#include "autoware_v2x/positioning.hpp"
|
||||
#include <vanetza/common/stored_position_provider.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
std::unique_ptr<vanetza::PositionProvider> create_position_provider(boost::asio::io_service &io_service, const Runtime &runtime)
|
||||
{
|
||||
std::unique_ptr<vanetza::PositionProvider> positioning;
|
||||
|
||||
std::unique_ptr<StoredPositionProvider> stored{new StoredPositionProvider()};
|
||||
PositionFix fix;
|
||||
fix.timestamp = runtime.now();
|
||||
fix.latitude = 10.0 * units::degree;
|
||||
fix.longitude = 10.0 * units::degree;
|
||||
fix.confidence.semi_major = 1.0 * units::si::meter;
|
||||
fix.confidence.semi_minor = fix.confidence.semi_major;
|
||||
stored->position_fix(fix);
|
||||
positioning = std::move(stored);
|
||||
|
||||
return positioning;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
#include "autoware_v2x/raw_socket_link.hpp"
|
||||
#include <iostream>
|
||||
#include <vanetza/access/data_request.hpp>
|
||||
#include <vanetza/net/ethernet_header.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
RawSocketLink::RawSocketLink(boost::asio::generic::raw_protocol::socket && socket)
|
||||
: socket_(std::move(socket)),
|
||||
receive_buffer_(2048, 0x00),
|
||||
receive_endpoint_(socket_.local_endpoint())
|
||||
{
|
||||
do_receive();
|
||||
}
|
||||
|
||||
void RawSocketLink::request(
|
||||
const access::DataRequest & request, std::unique_ptr<ChunkPacket> packet)
|
||||
{
|
||||
packet->layer(OsiLayer::Link) =
|
||||
create_ethernet_header(request.destination_addr, request.source_addr, request.ether_type);
|
||||
transmit(std::move(packet));
|
||||
}
|
||||
|
||||
std::size_t RawSocketLink::transmit(std::unique_ptr<ChunkPacket> packet)
|
||||
{
|
||||
std::array<boost::asio::const_buffer, layers_> const_buffers;
|
||||
for (auto & layer : osi_layer_range<OsiLayer::Physical, OsiLayer::Application>()) {
|
||||
const auto index = distance(OsiLayer::Physical, layer);
|
||||
packet->layer(layer).convert(buffers_[index]);
|
||||
const_buffers[index] = boost::asio::buffer(buffers_[index]);
|
||||
}
|
||||
|
||||
return socket_.send(const_buffers);
|
||||
}
|
||||
|
||||
void RawSocketLink::indicate(IndicationCallback callback) { callback_ = callback; }
|
||||
|
||||
void RawSocketLink::do_receive()
|
||||
{
|
||||
namespace sph = std::placeholders;
|
||||
socket_.async_receive_from(
|
||||
boost::asio::buffer(receive_buffer_), receive_endpoint_,
|
||||
std::bind(&RawSocketLink::on_read, this, sph::_1, sph::_2));
|
||||
}
|
||||
|
||||
void RawSocketLink::on_read(const boost::system::error_code & ec, std::size_t read_bytes)
|
||||
{
|
||||
if (!ec) {
|
||||
ByteBuffer buffer(receive_buffer_.begin(), receive_buffer_.begin() + read_bytes);
|
||||
CohesivePacket packet(std::move(buffer), OsiLayer::Physical);
|
||||
boost::optional<EthernetHeader> eth = parse_ethernet_header(packet);
|
||||
if (callback_ && eth) {
|
||||
callback_(std::move(packet), *eth);
|
||||
}
|
||||
do_receive();
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<EthernetHeader> RawSocketLink::parse_ethernet_header(
|
||||
vanetza::CohesivePacket & packet) const
|
||||
{
|
||||
packet.set_boundary(OsiLayer::Physical, 0);
|
||||
if (packet.size(OsiLayer::Link) < EthernetHeader::length_bytes) {
|
||||
std::cerr << "Router dropped invalid packet (too short for Ethernet header)\n";
|
||||
} else {
|
||||
packet.set_boundary(OsiLayer::Link, EthernetHeader::length_bytes);
|
||||
auto link_range = packet[OsiLayer::Link];
|
||||
return decode_ethernet_header(link_range.begin(), link_range.end());
|
||||
}
|
||||
|
||||
return boost::none;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
#include "autoware_v2x/application.hpp"
|
||||
#include "autoware_v2x/dcc_passthrough.hpp"
|
||||
#include "autoware_v2x/ethernet_device.hpp"
|
||||
#include "autoware_v2x/router_context.hpp"
|
||||
#include "autoware_v2x/time_trigger.hpp"
|
||||
#include <vanetza/access/ethertype.hpp>
|
||||
#include <vanetza/dcc/data_request.hpp>
|
||||
#include <vanetza/dcc/interface.hpp>
|
||||
#include <iostream>
|
||||
#include <vanetza/common/byte_order.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
|
||||
RouterContext::RouterContext(const geonet::MIB &mib, TimeTrigger &trigger, vanetza::PositionProvider &positioning, vanetza::security::SecurityEntity *security_entity) : mib_(mib), router_(trigger.runtime(), mib_), trigger_(trigger), positioning_(positioning)
|
||||
{
|
||||
router_.packet_dropped = std::bind(&RouterContext::log_packet_drop, this, std::placeholders::_1);
|
||||
router_.set_address(mib_.itsGnLocalGnAddr);
|
||||
router_.set_transport_handler(geonet::UpperProtocol::BTP_B, &dispatcher_);
|
||||
router_.set_security_entity(security_entity);
|
||||
update_position_vector();
|
||||
|
||||
trigger_.schedule();
|
||||
}
|
||||
|
||||
RouterContext::~RouterContext()
|
||||
{
|
||||
for (auto *app : applications_)
|
||||
{
|
||||
disable(app);
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::updateMIB(const geonet::MIB &mib) {
|
||||
mib_ = mib;
|
||||
router_.set_address(mib_.itsGnLocalGnAddr);
|
||||
}
|
||||
|
||||
void RouterContext::log_packet_drop(geonet::Router::PacketDropReason reason)
|
||||
{
|
||||
auto reason_string = stringify(reason);
|
||||
std::cout << "Router dropped packet because of " << reason_string << " (" << static_cast<int>(reason) << ")\n";
|
||||
}
|
||||
|
||||
void RouterContext::set_link_layer(LinkLayer *link_layer)
|
||||
{
|
||||
namespace dummy = std::placeholders;
|
||||
|
||||
if (link_layer)
|
||||
{
|
||||
request_interface_.reset(new DccPassthrough{*link_layer, trigger_});
|
||||
router_.set_access_interface(request_interface_.get());
|
||||
link_layer->indicate(std::bind(&RouterContext::indicate, this, dummy::_1, dummy::_2));
|
||||
update_packet_flow(router_.get_local_position_vector());
|
||||
}
|
||||
else
|
||||
{
|
||||
router_.set_access_interface(nullptr);
|
||||
request_interface_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::indicate(CohesivePacket &&packet, const EthernetHeader &hdr)
|
||||
{
|
||||
if (hdr.source != mib_.itsGnLocalGnAddr.mid() && hdr.type == access::ethertype::GeoNetworking)
|
||||
{
|
||||
std::cout << "received packet from " << hdr.source << " (" << packet.size() << " bytes)\n";
|
||||
std::unique_ptr<PacketVariant> up{new PacketVariant(std::move(packet))};
|
||||
trigger_.schedule(); // ensure the clock is up-to-date for the security entity
|
||||
router_.indicate(std::move(up), hdr.source, hdr.destination);
|
||||
trigger_.schedule(); // schedule packet forwarding
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::enable(Application *app)
|
||||
{
|
||||
app->router_ = &router_;
|
||||
|
||||
dispatcher_.add_promiscuous_hook(app->promiscuous_hook());
|
||||
if (app->port() != btp::port_type(0))
|
||||
{
|
||||
dispatcher_.set_non_interactive_handler(app->port(), app);
|
||||
}
|
||||
}
|
||||
|
||||
void RouterContext::disable(Application *app)
|
||||
{
|
||||
if (app->port() != btp::port_type(0))
|
||||
{
|
||||
dispatcher_.set_non_interactive_handler(app->port(), nullptr);
|
||||
}
|
||||
dispatcher_.remove_promiscuous_hook(app->promiscuous_hook());
|
||||
|
||||
app->router_ = nullptr;
|
||||
}
|
||||
|
||||
void RouterContext::require_position_fix(bool flag)
|
||||
{
|
||||
require_position_fix_ = flag;
|
||||
update_packet_flow(router_.get_local_position_vector());
|
||||
}
|
||||
|
||||
void RouterContext::update_position_vector()
|
||||
{
|
||||
router_.update_position(positioning_.position_fix());
|
||||
vanetza::Runtime::Callback callback = [this](vanetza::Clock::time_point)
|
||||
{ this->update_position_vector(); };
|
||||
vanetza::Clock::duration next = std::chrono::seconds(1);
|
||||
trigger_.runtime().schedule(next, callback);
|
||||
trigger_.schedule();
|
||||
|
||||
update_packet_flow(router_.get_local_position_vector());
|
||||
}
|
||||
|
||||
void RouterContext::update_packet_flow(const geonet::LongPositionVector &lpv)
|
||||
{
|
||||
if (request_interface_)
|
||||
{
|
||||
if (require_position_fix_)
|
||||
{
|
||||
// Skip all requests until a valid GPS position is available
|
||||
request_interface_->allow_packet_flow(lpv.position_accuracy_indicator);
|
||||
}
|
||||
else
|
||||
{
|
||||
request_interface_->allow_packet_flow(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
#include "autoware_v2x/security.hpp"
|
||||
#include <vanetza/security/certificate_cache.hpp>
|
||||
#include <vanetza/security/default_certificate_validator.hpp>
|
||||
#include <vanetza/security/delegating_security_entity.hpp>
|
||||
#include <vanetza/security/naive_certificate_provider.hpp>
|
||||
#include <vanetza/security/null_certificate_validator.hpp>
|
||||
#include <vanetza/security/persistence.hpp>
|
||||
#include <vanetza/security/sign_header_policy.hpp>
|
||||
#include <vanetza/security/static_certificate_provider.hpp>
|
||||
#include <vanetza/security/trust_store.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace vanetza;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
class SecurityContext : public security::SecurityEntity
|
||||
{
|
||||
public:
|
||||
SecurityContext(const Runtime &runtime, PositionProvider &positioning) : runtime(runtime), positioning(positioning),
|
||||
backend(security::create_backend("default")),
|
||||
sign_header_policy(runtime, positioning),
|
||||
cert_cache(runtime),
|
||||
cert_validator(*backend, cert_cache, trust_store)
|
||||
{
|
||||
}
|
||||
|
||||
security::EncapConfirm encapsulate_packet(security::EncapRequest &&request) override
|
||||
{
|
||||
if (!entity)
|
||||
{
|
||||
throw std::runtime_error("security entity is not ready");
|
||||
}
|
||||
return entity->encapsulate_packet(std::move(request));
|
||||
}
|
||||
|
||||
security::DecapConfirm decapsulate_packet(security::DecapRequest &&request) override
|
||||
{
|
||||
if (!entity)
|
||||
{
|
||||
throw std::runtime_error("security entity is not ready");
|
||||
}
|
||||
return entity->decapsulate_packet(std::move(request));
|
||||
}
|
||||
|
||||
void build_entity()
|
||||
{
|
||||
if (!cert_provider)
|
||||
{
|
||||
throw std::runtime_error("certificate provider is missing");
|
||||
}
|
||||
security::SignService sign_service = straight_sign_service(*cert_provider, *backend, sign_header_policy);
|
||||
security::VerifyService verify_service = straight_verify_service(runtime, *cert_provider, cert_validator,
|
||||
*backend, cert_cache, sign_header_policy, positioning);
|
||||
entity.reset(new security::DelegatingSecurityEntity{sign_service, verify_service});
|
||||
}
|
||||
|
||||
const Runtime &runtime;
|
||||
PositionProvider &positioning;
|
||||
std::unique_ptr<security::Backend> backend;
|
||||
std::unique_ptr<security::SecurityEntity> entity;
|
||||
std::unique_ptr<security::CertificateProvider> cert_provider;
|
||||
security::DefaultSignHeaderPolicy sign_header_policy;
|
||||
security::TrustStore trust_store;
|
||||
security::CertificateCache cert_cache;
|
||||
security::DefaultCertificateValidator cert_validator;
|
||||
};
|
||||
|
||||
std::unique_ptr<security::SecurityEntity>
|
||||
create_security_entity(const Runtime &runtime, PositionProvider &positioning)
|
||||
{
|
||||
std::unique_ptr<security::SecurityEntity> security;
|
||||
|
||||
return security;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#include "autoware_v2x/time_trigger.hpp"
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
|
||||
namespace asio = boost::asio;
|
||||
namespace posix_time = boost::posix_time;
|
||||
using namespace vanetza;
|
||||
|
||||
TimeTrigger::TimeTrigger(asio::io_service & io_service)
|
||||
: io_service_(io_service), timer_(io_service), runtime_(Clock::at(now()))
|
||||
{
|
||||
std::cout << "Starting runtime at " << now() << "\n";
|
||||
schedule();
|
||||
}
|
||||
|
||||
posix_time::ptime TimeTrigger::now() const { return posix_time::microsec_clock::universal_time(); }
|
||||
|
||||
void TimeTrigger::schedule()
|
||||
{
|
||||
update_runtime();
|
||||
auto next = runtime_.next();
|
||||
if (next < Clock::time_point::max()) {
|
||||
timer_.expires_at(Clock::at(next));
|
||||
timer_.async_wait(std::bind(&TimeTrigger::on_timeout, this, std::placeholders::_1));
|
||||
} else {
|
||||
timer_.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
void TimeTrigger::on_timeout(const boost::system::error_code & ec)
|
||||
{
|
||||
if (asio::error::operation_aborted != ec) {
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
|
||||
void TimeTrigger::update_runtime()
|
||||
{
|
||||
auto current_time = now();
|
||||
runtime_.trigger(Clock::at(current_time));
|
||||
}
|
Loading…
Reference in New Issue