diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e4442ff..ec4b66f 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,36 +1,21 @@ -# Create executables for each example -add_executable(example_mcap_writer example_mcap_writer.cpp) -add_executable(example_native_binary_reader example_native_binary_reader.cpp) -add_executable(example_txth_reader example_txth_reader.cpp) -add_executable(example_txth_writer example_txth_writer.cpp) -add_executable(convert_osi2mcap convert_osi2mcap.cpp) +function(configure_example TARGET_NAME SOURCE_FILE) + add_executable(${TARGET_NAME} ${SOURCE_FILE}) -# Link against OSI made available by parent CMakeLists.txt -if(LINK_WITH_SHARED_OSI) - target_link_libraries(example_mcap_writer PRIVATE open_simulation_interface) - target_link_libraries(example_native_binary_reader PRIVATE open_simulation_interface) - target_link_libraries(example_txth_reader PRIVATE open_simulation_interface) - target_link_libraries(example_txth_writer PRIVATE open_simulation_interface) - target_link_libraries(convert_osi2mcap PRIVATE open_simulation_interface) -else() - target_link_libraries(example_mcap_writer PRIVATE open_simulation_interface_pic) - target_link_libraries(example_native_binary_reader PRIVATE open_simulation_interface_pic) - target_link_libraries(example_txth_reader PRIVATE open_simulation_interface_pic) - target_link_libraries(example_txth_writer PRIVATE open_simulation_interface_pic) - target_link_libraries(convert_osi2mcap PRIVATE open_simulation_interface_pic) - include_directories(${OSI_INCLUDE_DIR}) -endif() + if(LINK_WITH_SHARED_OSI) + target_link_libraries(${TARGET_NAME} PRIVATE open_simulation_interface) + else() + target_link_libraries(${TARGET_NAME} PRIVATE open_simulation_interface_pic) + include_directories(${OSI_INCLUDE_DIR}) + endif() -# Link each example against the library -target_link_libraries(example_mcap_writer PRIVATE OSIUtilities) -target_link_libraries(example_native_binary_reader PRIVATE OSIUtilities) -target_link_libraries(example_txth_reader PRIVATE OSIUtilities) -target_link_libraries(example_txth_writer PRIVATE OSIUtilities) -target_link_libraries(convert_osi2mcap PRIVATE OSIUtilities) + target_link_libraries(${TARGET_NAME} PRIVATE OSIUtilities) + target_include_directories(${TARGET_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include) +endfunction() -# Specify the public headers for the library for clean access -target_include_directories(example_mcap_writer PUBLIC ${PROJECT_SOURCE_DIR}/include) -target_include_directories(example_native_binary_reader PUBLIC ${PROJECT_SOURCE_DIR}/include) -target_include_directories(example_txth_reader PUBLIC ${PROJECT_SOURCE_DIR}/include) -target_include_directories(example_txth_writer PUBLIC ${PROJECT_SOURCE_DIR}/include) -target_include_directories(convert_osi2mcap PUBLIC ${PROJECT_SOURCE_DIR}/include) \ No newline at end of file +# Add examples using the function above +configure_example(example_mcap_writer example_mcap_writer.cpp) +configure_example(example_native_binary_reader example_native_binary_reader.cpp) +configure_example(example_native_binary_writer example_native_binary_writer.cpp) +configure_example(example_txth_reader example_txth_reader.cpp) +configure_example(example_txth_writer example_txth_writer.cpp) +configure_example(convert_osi2mcap convert_osi2mcap.cpp) \ No newline at end of file diff --git a/examples/example_native_binary_writer.cpp b/examples/example_native_binary_writer.cpp new file mode 100644 index 0000000..dd3dd94 --- /dev/null +++ b/examples/example_native_binary_writer.cpp @@ -0,0 +1,67 @@ +// +// Copyright (c) 2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// SPDX-License-Identifier: MPL-2.0 +// + +#include + +#include + +#include "osi_sensordata.pb.h" +#include "osi_version.pb.h" + +std::string GenerateTempFilePath() { + const auto path = std::filesystem::temp_directory_path() / "example_native_binary_writer.osi"; + return path.string(); +} + +int main(int argc, const char** argv) { + std::cout << "Starting Native Binary Writer example:" << std::endl; + + // Create writer and open file + auto tracefile_writer = osi3::NativeBinaryTraceFileWriter(); + const auto tracefile_path = GenerateTempFilePath(); + std::cout << "Creating tracefile at " << tracefile_path << std::endl; + tracefile_writer.Open(tracefile_path); + + // create OSI data to store + const auto osi_version = osi3::InterfaceVersion::descriptor()->file()->options().GetExtension(osi3::current_interface_version); + + osi3::SensorView sensor_view; + sensor_view.mutable_version()->CopyFrom(osi_version); + sensor_view.mutable_sensor_id()->set_value(0); + + auto* const ground_truth = sensor_view.mutable_global_ground_truth(); + ground_truth->mutable_version()->CopyFrom(osi_version); + + auto* const host_vehicle = ground_truth->mutable_moving_object()->Add(); + host_vehicle->mutable_id()->set_value(12); + host_vehicle->mutable_vehicle_classification()->set_type(osi3::MovingObject_VehicleClassification_Type_TYPE_SMALL_CAR); + host_vehicle->mutable_base()->mutable_dimension()->set_length(5); + host_vehicle->mutable_base()->mutable_dimension()->set_width(2); + host_vehicle->mutable_base()->mutable_dimension()->set_height(1.5); + host_vehicle->mutable_base()->mutable_velocity()->set_x(10.0); + + // write the data continuously in a loop + constexpr double kTimeStepSizeS = 0.1; // NOLINT + for (int i = 0; i < 10; ++i) { + // manipulate the data so not every message is the same + auto timestamp = sensor_view.timestamp().seconds() * 1000000000 + sensor_view.timestamp().nanos(); + timestamp += 100000000; + sensor_view.mutable_timestamp()->set_nanos(timestamp % 1000000000); + sensor_view.mutable_timestamp()->set_seconds(timestamp / 1000000000); + ground_truth->mutable_timestamp()->set_nanos(timestamp % 1000000000); + ground_truth->mutable_timestamp()->set_seconds(timestamp / 1000000000); + const auto old_position = host_vehicle->base().position().x(); + const auto new_position = old_position + host_vehicle->base().velocity().x() * kTimeStepSizeS; + host_vehicle->mutable_base()->mutable_position()->set_x(new_position); + + // write the data + tracefile_writer.WriteMessage(sensor_view); + } + + tracefile_writer.Close(); + + std::cout << "Finished Native Binary Writer example" << std::endl; + return 0; +} \ No newline at end of file diff --git a/include/osi-utilities/tracefile/writer/NativeBinaryTraceFileWriter.h b/include/osi-utilities/tracefile/writer/NativeBinaryTraceFileWriter.h new file mode 100644 index 0000000..84b1f83 --- /dev/null +++ b/include/osi-utilities/tracefile/writer/NativeBinaryTraceFileWriter.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2024, Bayerische Motoren Werke Aktiengesellschaft (BMW AG) +// SPDX-License-Identifier: MPL-2.0 +// + + +#ifndef OSIUTILITIES_TRACEFILE_NATIVEBINARYTRACEFILEWRITER_H_ +#define OSIUTILITIES_TRACEFILE_NATIVEBINARYTRACEFILEWRITER_H_ + +#include "osi-utilities/tracefile/Writer.h" +#include + +namespace osi3 { + +class NativeBinaryTraceFileWriter : public TraceFileWriter { +public: + bool Open(const std::string& filename) override; + void Close() override; + bool SetMetadata(const std::string& /*name*/, const std::unordered_map& /*metadata_entries*/) override { return true; } + + template + bool WriteMessage(T top_level_message); + + template + bool WriteMessage(T /*top_level_message*/, const std::string& /*topic*/) { return false; } + +private: + std::ofstream trace_file_; + bool file_open_ = false; +}; + +} // namespace osi3 +#endif \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 07b68af..71d6db7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,14 +6,14 @@ option(BUILD_TESTING "Build the testing suite" ON) # specify library source files set(OSIUtilities_SRCS - tracefile/MCAPImplementation.cpp - tracefile/writer/Writer.cpp - tracefile/writer/MCAPTraceFileWriter.cpp - tracefile/writer/txthTraceFileWriter.cpp tracefile/reader/Reader.cpp + tracefile/writer/Writer.cpp + tracefile/MCAPImplementation.cpp tracefile/reader/NativeBinaryTraceFileReader.cpp + tracefile/writer/NativeBinaryTraceFileWriter.cpp tracefile/reader/txthTraceFileReader.cpp - + tracefile/writer/txthTraceFileWriter.cpp + tracefile/writer/MCAPTraceFileWriter.cpp ) # Create a library target for the entire library diff --git a/src/tracefile/writer/NativeBinaryTraceFileWriter.cpp b/src/tracefile/writer/NativeBinaryTraceFileWriter.cpp new file mode 100644 index 0000000..55f5b84 --- /dev/null +++ b/src/tracefile/writer/NativeBinaryTraceFileWriter.cpp @@ -0,0 +1,63 @@ +#include "osi-utilities/tracefile/writer/NativeBinaryTraceFileWriter.h" + +#include "osi_groundtruth.pb.h" +#include "osi_hostvehicledata.pb.h" +#include "osi_motionrequest.pb.h" +#include "osi_sensordata.pb.h" +#include "osi_sensorview.pb.h" +#include "osi_streamingupdate.pb.h" +#include "osi_trafficcommand.pb.h" +#include "osi_trafficcommandupdate.pb.h" +#include "osi_trafficupdate.pb.h" + +namespace osi3 { + +bool NativeBinaryTraceFileWriter::Open(const std::string& filename) { + if (filename.substr(filename.length() - 4) != ".osi") { + std::cerr << "Error: Filename must end with .osi extension\n"; + return false; + } + + trace_file_.open(filename, std::ios::binary); + if (trace_file_.is_open()) { + file_open_ = true; + return true; + } + return false; +} + +void NativeBinaryTraceFileWriter::Close() { + if (file_open_) { + trace_file_.close(); + file_open_ = false; + } +} + +template +bool NativeBinaryTraceFileWriter::WriteMessage(T top_level_message) { + if (!file_open_) { + std::cerr << "Error: Cannot write message, file is not open\n"; + return false; + } + + const std::string serialized_message = top_level_message.SerializeAsString(); + const uint32_t message_size = static_cast(serialized_message.size()); + + trace_file_.write(reinterpret_cast(&message_size), sizeof(message_size)); + trace_file_.write(serialized_message.data(), message_size); + + return trace_file_.good(); +} + +// Template instantiations for allowed OSI top-level messages +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::GroundTruth); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::SensorData); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::SensorView); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::HostVehicleData); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::TrafficCommand); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::TrafficCommandUpdate); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::TrafficUpdate); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::MotionRequest); +template bool NativeBinaryTraceFileWriter::WriteMessage(osi3::StreamingUpdate); + +} // namespace osi3 \ No newline at end of file