Skip to content

Commit caf26c3

Browse files
committed
draft
Signed-off-by: Berkay Karaman <brkay54@gmail.com>
1 parent 9a63f6f commit caf26c3

File tree

3 files changed

+105
-18
lines changed

3 files changed

+105
-18
lines changed

tools/reaction_analyzer/include/reaction_analyzer_node.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ struct NodeParams
121121
{
122122
std::string running_mode;
123123
double timer_period;
124+
std::string output_file_path;
125+
size_t test_iteration;
124126
double object_search_radius_offset;
125127
double spawn_time_after_init;
126128
double spawn_distance_threshold;
@@ -211,6 +213,8 @@ class ReactionAnalyzerNode : public rclcpp::Node
211213

212214
void reset();
213215

216+
void writeResultsToFile();
217+
214218
// Callbacks
215219
void vehiclePoseCallback(Odometry::ConstSharedPtr msg_ptr);
216220

@@ -239,6 +243,7 @@ class ReactionAnalyzerNode : public rclcpp::Node
239243
// Variables
240244
std::vector<rclcpp::SubscriptionBase::SharedPtr> subscribers_;
241245
std::unordered_map<std::string, BufferVariant> message_buffers_;
246+
std::unordered_map<std::string, std::vector<double>> test_results_;
242247
std::optional<rclcpp::Time> last_test_environment_init_request_time_;
243248
std::optional<rclcpp::Time> test_environment_init_time_;
244249
std::optional<rclcpp::Time> spawn_cmd_time_;
@@ -247,6 +252,8 @@ class ReactionAnalyzerNode : public rclcpp::Node
247252
bool is_output_printed_{false};
248253
bool is_vehicle_initialized_{false};
249254
bool is_route_set_{false};
255+
size_t test_iteration_count_{0};
256+
250257
// Timer
251258
rclcpp::TimerBase::SharedPtr timer_;
252259
rclcpp::TimerBase::SharedPtr dummy_perception_timer_;
@@ -258,7 +265,6 @@ class ReactionAnalyzerNode : public rclcpp::Node
258265

259266
// Pointers
260267
std::shared_ptr<topic_publisher::TopicPublisher> topic_publisher_ptr_;
261-
262268
PointCloud2::SharedPtr entity_pointcloud_ptr_;
263269
PredictedObjects::SharedPtr predicted_objects_ptr_;
264270
Odometry::ConstSharedPtr odometry_;

tools/reaction_analyzer/param/reaction_analyzer.param.yaml

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/**:
22
ros__parameters:
33
timer_period: 0.1 # s
4+
test_iteration: 5
5+
output_file_path: /home/berkay/projects/reaction_analyzer_results/
46
object_search_radius_offset: 0.1 # m
57
spawn_time_after_init: 20.0 # s
68
spawn_distance_threshold: 25.0 # m
@@ -10,13 +12,20 @@
1012
control_cmd_buffer_time_interval: 1.0 # s
1113
min_number_descending_order_control_cmd: 8
1214
min_jerk_for_brake_cmd: 0.3 # m/s^3
15+
# initialization_pose:
16+
# x: 1.5
17+
# y: 200.0
18+
# z: 101.25
19+
# roll: 0.0
20+
# pitch: 0.0
21+
# yaw: 90.0
1322
initialization_pose:
14-
x: 1.5
15-
y: 200.0
16-
z: 101.25
23+
x: 81247.9609375
24+
y: 49828.87890625
25+
z: 0.0
1726
roll: 0.0
1827
pitch: 0.0
19-
yaw: 90.0
28+
yaw: 35.5
2029
# entity_params:
2130
# x: 1.5
2231
# y: 345.0

tools/reaction_analyzer/src/reaction_analyzer_node.cpp

+85-13
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,8 @@ ReactionAnalyzerNode::ReactionAnalyzerNode(rclcpp::NodeOptions options)
258258
}
259259

260260
node_params_.timer_period = get_parameter("timer_period").as_double();
261+
node_params_.test_iteration = get_parameter("test_iteration").as_int();
262+
node_params_.output_file_path = get_parameter("output_file_path").as_string();
261263
node_params_.object_search_radius_offset =
262264
get_parameter("object_search_radius_offset").as_double();
263265
node_params_.spawn_time_after_init = get_parameter("spawn_time_after_init").as_double();
@@ -507,20 +509,12 @@ void ReactionAnalyzerNode::printResults(
507509
const std::pair<std::string, rclcpp::Time> & a,
508510
const std::pair<std::string, rclcpp::Time> & b) { return a.second < b.second; });
509511

510-
// first print spawn_cmd_time to first reaction
511-
// std::cout << "spawn_cmd_time to " << reaction_times.begin()->first << ": "
512-
// << createDurationMs(spawn_cmd_time_.value(), reaction_times.begin()->second)
513-
// << std::endl;
514-
515-
// if (reaction_times.size() < 2) return;
516-
517-
for (size_t i = 0; i < reaction_times.size(); i++) {
518-
const auto & first_reaction = reaction_times.at(i);
519-
// const auto & second_reaction = reaction_times.at(i + 1);
520-
521-
std::cout << "spawn_cmd_time to " << first_reaction.first << ": "
522-
<< createDurationMs(spawn_cmd_time_.value(), first_reaction.second) << std::endl;
512+
for (const auto & reaction_time : reaction_times) {
513+
const double duration = createDurationMs(spawn_cmd_time_.value(), reaction_time.second);
514+
test_results_[reaction_time.first].emplace_back(duration);
515+
std::cout << "spawn_cmd_time to " << reaction_time.first << ": " << duration << std::endl;
523516
}
517+
test_iteration_count_++;
524518
is_output_printed_ = true;
525519
}
526520

@@ -988,6 +982,11 @@ bool ReactionAnalyzerNode::searchDetectedObjectsNearEntity(const DetectedObjects
988982

989983
void ReactionAnalyzerNode::reset()
990984
{
985+
if (test_iteration_count_ >= node_params_.test_iteration) {
986+
writeResultsToFile();
987+
RCLCPP_INFO(get_logger(), "Test finished. Node shutting down.");
988+
rclcpp::shutdown();
989+
}
991990
is_vehicle_initialized_ = false;
992991
is_route_set_ = false;
993992
test_environment_init_time_ = std::nullopt;
@@ -1004,6 +1003,79 @@ void ReactionAnalyzerNode::reset()
10041003
mutex_.unlock();
10051004
}
10061005

1006+
void ReactionAnalyzerNode::writeResultsToFile()
1007+
{
1008+
// create csv file
1009+
auto now = std::chrono::system_clock::now();
1010+
auto in_time_t = std::chrono::system_clock::to_time_t(now);
1011+
1012+
std::stringstream ss;
1013+
ss << node_params_.output_file_path;
1014+
if (!node_params_.output_file_path.empty() && node_params_.output_file_path.back() != '/') {
1015+
ss << "/"; // Ensure the path ends with a slash
1016+
}
1017+
if (node_running_mode_ == RunningMode::PlanningControl) {
1018+
ss << "planning_control-";
1019+
} else {
1020+
ss << "perception_planning-";
1021+
}
1022+
1023+
ss << std::put_time(std::localtime(&in_time_t), "%Y-%m-%d-%H-%M-%S");
1024+
ss << "-reaction-results.csv";
1025+
1026+
// parse the results
1027+
std::ofstream file(ss.str());
1028+
// Check if the file was opened successfully
1029+
if (!file.is_open()) {
1030+
std::cerr << "Failed to open file: " << ss.str() << std::endl;
1031+
return;
1032+
}
1033+
1034+
bool is_header_written = false;
1035+
1036+
for (const auto & [node, durations] : test_results_) {
1037+
if (!is_header_written) {
1038+
file << "Node,";
1039+
const size_t num_durations = durations.size();
1040+
for (size_t i = 0; i < num_durations; ++i) {
1041+
file << "Test - " << i + 1 << ",";
1042+
}
1043+
file << "Min,Max,Mean,Median,StdDev\n ";
1044+
is_header_written = true;
1045+
}
1046+
1047+
// parse test results
1048+
file << node << ",";
1049+
for (double i : durations) {
1050+
file << i << ",";
1051+
}
1052+
1053+
// calculate stats
1054+
const double min = *std::min_element(durations.begin(), durations.end());
1055+
const double max = *std::max_element(durations.begin(), durations.end());
1056+
1057+
std::vector<double> sorted_data = durations;
1058+
std::sort(sorted_data.begin(), sorted_data.end());
1059+
const double median =
1060+
sorted_data.size() % 2 == 0
1061+
? (sorted_data[sorted_data.size() / 2 - 1] + sorted_data[sorted_data.size() / 2]) / 2
1062+
: sorted_data[sorted_data.size() / 2];
1063+
1064+
const double mean =
1065+
std::accumulate(sorted_data.begin(), sorted_data.end(), 0.0) / sorted_data.size();
1066+
const double sq_sum = std::inner_product(
1067+
sorted_data.begin(), sorted_data.end(), sorted_data.begin(), 0.0, std::plus<>(),
1068+
[&](double a, double b) { return (a - mean) * (b - mean); });
1069+
double std_dev = std::sqrt(sq_sum / sorted_data.size());
1070+
1071+
// parse stats
1072+
file << min << "," << max << "," << mean << "," << median << "," << std_dev << "\n";
1073+
1074+
}
1075+
file.close();
1076+
std::cout << "Results written to: " << ss.str() << std::endl;
1077+
}
1078+
10071079
} // namespace reaction_analyzer
10081080

10091081
#include <rclcpp_components/register_node_macro.hpp>

0 commit comments

Comments
 (0)