Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: publisher and server for calibration with external application #722

Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3e25bc5
ci: add sync-upstream.yaml (#4)
kenji-miyake Jan 29, 2022
bfb6ec8
ci(sync-upstream): update settings (#19)
kenji-miyake Mar 3, 2022
41a9d49
(editting) add node for creating calibration data
TakumiKozaka-T4 Apr 1, 2022
2cf8528
(editting) modify server node
TakumiKozaka-T4 Apr 4, 2022
b222a9c
(editting) add server and client
TakumiKozaka-T4 Apr 12, 2022
791ddb9
(editting) add client and server
TakumiKozaka-T4 Apr 12, 2022
f30d3dd
modify server and client
TakumiKozaka-T4 Apr 13, 2022
ee4a6fe
modify client and server
TakumiKozaka-T4 Apr 15, 2022
df9a1d9
modify server node
TakumiKozaka-T4 Apr 15, 2022
13a705b
delete debug codes
TakumiKozaka-T4 Apr 15, 2022
775b6a7
run pre-commit
TakumiKozaka-T4 Apr 18, 2022
ad6a811
rebase to autowarefoundation/autoware/main
TakumiKozaka-T4 Apr 21, 2022
1b0ad75
Delete sync-upstream.yaml
TakumiKozaka-T4 Apr 25, 2022
3ac3d96
Merge branch 'main' of github.com:autowarefoundation/autoware.univers…
TakumiKozaka-T4 May 11, 2022
f25352d
merge the latest version of universe main
TakumiKozaka-T4 May 12, 2022
dcf3f5d
return empty data when error occurs
TakumiKozaka-T4 May 17, 2022
004ef8a
modify plot_csv_server for adding it to launcher
TakumiKozaka-T4 May 20, 2022
ad588ba
Merge branch 'main' of github.com:autowarefoundation/autoware.univers…
TakumiKozaka-T4 May 20, 2022
e096cb9
pull the latest universe main
TakumiKozaka-T4 May 20, 2022
f6d9560
modify test script
TakumiKozaka-T4 May 26, 2022
3196d1f
ci(pre-commit): autofix
pre-commit-ci[bot] May 26, 2022
43aebec
Merge branch 'main' of github.com:autowarefoundation/autoware.univers…
TakumiKozaka-T4 May 26, 2022
7fbea7d
rename server file, add test script for calibration status change
TakumiKozaka-T4 May 30, 2022
28a87c6
ci(pre-commit): autofix
pre-commit-ci[bot] May 30, 2022
bc5d09e
change node name
TakumiKozaka-T4 May 30, 2022
3d0c22a
Merge branch 'feature/add-calibrator-api' of github.com:TakumiKozaka-…
TakumiKozaka-T4 May 30, 2022
aa0500a
Fix status when default accel/brake map is not found
TakumiKozaka-T4 Jun 3, 2022
cb8fbaf
run pre-commit
TakumiKozaka-T4 Jun 3, 2022
8f765f3
return blank data if default map is not found.
TakumiKozaka-T4 Jun 6, 2022
d59d2b6
ci(pre-commit): autofix
pre-commit-ci[bot] Jun 6, 2022
4fd525f
change calibration status definition
TakumiKozaka-T4 Jun 6, 2022
ddfa2c1
Merge branch 'feature/add-calibrator-api' of github.com:TakumiKozaka-…
TakumiKozaka-T4 Jun 6, 2022
694a6fc
Change print to get_logger(). Delete unnecessary comment.
TakumiKozaka-T4 Jun 8, 2022
2f547b3
Merge branch 'main' of github.com:autowarefoundation/autoware.univers…
TakumiKozaka-T4 Jun 8, 2022
7ff3f34
pull the latest foundation main
TakumiKozaka-T4 Jun 8, 2022
86cb2da
modified as comment in PR
TakumiKozaka-T4 Jun 13, 2022
2403555
Delete unnecessary sentences.
TakumiKozaka-T4 Jun 14, 2022
eb514fd
ci(pre-commit): autofix
pre-commit-ci[bot] Jun 14, 2022
5da0247
Merge branch 'main' of github.com:autowarefoundation/autoware.univers…
TakumiKozaka-T4 Jun 15, 2022
40b59df
pull the latest foundation/main
TakumiKozaka-T4 Jun 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ install(
scripts/csv_reader.py
scripts/log_analyzer.py
scripts/view_plot.py
scripts/new_accel_brake_map_server.py
test/plot_csv_client_node.py
test/sim_actuation_status_publisher.py
DESTINATION lib/${PROJECT_NAME}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
#include "std_msgs/msg/string.hpp"
#include "tier4_debug_msgs/msg/float32_multi_array_stamped.hpp"
#include "tier4_debug_msgs/msg/float32_stamped.hpp"
#include "tier4_external_api_msgs/msg/calibration_status.hpp"
#include "tier4_external_api_msgs/msg/calibration_status_array.hpp"
#include "tier4_external_api_msgs/srv/get_accel_brake_map_calibration_data.hpp"
#include "tier4_vehicle_msgs/msg/actuation_status_stamped.hpp"
#include "tier4_vehicle_msgs/srv/update_accel_brake_map.hpp"

Expand Down Expand Up @@ -84,6 +87,8 @@ class AccelBrakeMapCalibrator : public rclcpp::Node
rclcpp::Publisher<tier4_debug_msgs::msg::Float32Stamped>::SharedPtr current_map_error_pub_;
rclcpp::Publisher<tier4_debug_msgs::msg::Float32Stamped>::SharedPtr updated_map_error_pub_;
rclcpp::Publisher<tier4_debug_msgs::msg::Float32Stamped>::SharedPtr map_error_ratio_pub_;
rclcpp::Publisher<tier4_external_api_msgs::msg::CalibrationStatus>::SharedPtr
calibration_status_pub_;

rclcpp::Subscription<autoware_auto_vehicle_msgs::msg::VelocityReport>::SharedPtr velocity_sub_;
rclcpp::Subscription<autoware_auto_vehicle_msgs::msg::SteeringReport>::SharedPtr steer_sub_;
Expand All @@ -110,6 +115,7 @@ class AccelBrakeMapCalibrator : public rclcpp::Node

// Diagnostic Updater
std::shared_ptr<diagnostic_updater::Updater> updater_ptr_;
bool is_default_map_ = true;

int get_pitch_method_;
int update_method_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
<param name="use_sim_time" value="$(var use_sim_time)"/>
</node>

<!-- calibration plot and map server node -->
<node pkg="accel_brake_map_calibrator" exec="new_accel_brake_map_server.py" name="new_accel_brake_map_server" output="screen"/>
<!-- Rviz -->
<node pkg="rviz2" exec="rviz2" name="rviz2" output="screen" args="-d $(find-pkg-share accel_brake_map_calibrator)/rviz/occupancy.rviz" if="$(var rviz)"/>
</launch>
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<depend>tf2_ros</depend>
<depend>tier4_autoware_utils</depend>
<depend>tier4_debug_msgs</depend>
<depend>tier4_external_api_msgs</depend>
<depend>tier4_vehicle_msgs</depend>
<depend>visualization_msgs</depend>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,339 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
kenji-miyake marked this conversation as resolved.
Show resolved Hide resolved

# Copyright 2021 Tier IV, Inc. All rights reserved.
kenji-miyake marked this conversation as resolved.
Show resolved Hide resolved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import math
from pathlib import Path

from ament_index_python.packages import get_package_share_directory
from calc_utils import CalcUtils
import config as CF
from csv_reader import CSVReader
import matplotlib.pyplot as plt
import numpy as np
from plotter import Plotter
import rclpy
from rclpy.node import Node
from tier4_external_api_msgs.srv import GetAccelBrakeMapCalibrationData as CalibData
import yaml


class DrawGraph(Node):
calibrated_map_dir = ""

def __init__(self):
super().__init__("plot_server")
self.srv = self.create_service(
CalibData, "/accel_brake_map_calibrator/get_data_service", self.get_data_callback
)

package_path = get_package_share_directory("accel_brake_map_calibrator")
default_map_path = get_package_share_directory("raw_vehicle_cmd_converter")

self.default_map_dir = default_map_path + "/data/default/"
self.calibrated_map_dir = package_path + "/config/"
self.log_file = package_path + "/config/log.csv"

config_file = package_path + "/config/accel_brake_map_calibrator.param.yaml"
if Path(config_file).exists():
print("config file exists")
with open(config_file) as yml:
data = yaml.safe_load(yml)
self.min_vel_thr = data["/**"]["ros__parameters"]["velocity_min_threshold"]
self.vel_diff_thr = data["/**"]["ros__parameters"]["velocity_diff_threshold"]
self.pedal_diff_thr = data["/**"]["ros__parameters"]["pedal_diff_threshold"]
self.max_steer_thr = data["/**"]["ros__parameters"]["max_steer_threshold"]
self.max_pitch_thr = data["/**"]["ros__parameters"]["max_pitch_threshold"]
self.max_jerk_thr = data["/**"]["ros__parameters"]["max_jerk_threshold"]
else:
print("config file is not found")
self.min_vel_thr = 0.1
self.vel_diff_thr = 0.556
self.pedal_diff_thr = 0.03
self.max_steer_thr = 0.2
self.max_pitch_thr = 0.02
self.max_jerk_thr = 0.7

self.max_pedal_vel_thr = 0.7

# debug
print("default map dir: {}".format(self.default_map_dir))
print("calibrated map dir: {}".format(self.calibrated_map_dir))
print("log file :", self.log_file)
print("min_vel_thr : ", self.min_vel_thr)
print("vel_diff_thr : ", self.vel_diff_thr)
print("pedal_diff_thr : ", self.pedal_diff_thr)
print("max_steer_thr : ", self.max_steer_thr)
print("max_pitch_thr : ", self.max_pitch_thr)
print("max_jerk_thr : ", self.max_jerk_thr)
print("max_pedal_vel_thr : ", self.max_pedal_vel_thr)

def get_data_callback(self, request, response):
# read csv
# If log file doesn't exsist, return empty data
if not Path(self.log_file).exists():
response.graph_image = []
print("svg data is empty")

response.accel_map = ""
print("accel map is empty")

response.brake_map = ""
print("brake map is empty")

return response

self.cr = CSVReader(self.log_file, csv_type="file")

# remove unused_data
self.csv_data = self.cr.removeUnusedData(
self.min_vel_thr,
self.max_steer_thr,
self.max_pitch_thr,
self.max_pedal_vel_thr,
self.max_jerk_thr,
)

# get statistics array
vel_data = self.cr.getVelData()
pedal_data = self.cr.getPedalData()
acc_data = self.cr.getAccData()

# get color factor (pitch) array for plotting
color_data = self.cr.getPitchData()

data, full_data = CalcUtils.create_2d_map(
vel_data,
pedal_data,
acc_data,
color_data,
CF.VEL_LIST / 3.6,
self.vel_diff_thr,
CF.PEDAL_LIST,
self.pedal_diff_thr,
)

count_map, average_map, stddev_map = CalcUtils.create_stat_map(data)
velocity_map_list = []
for i in range(len(CF.VEL_LIST)):
velocity_map_list.append(CalcUtils.extract_x_index_map(full_data, i))

default_pedal_list, default_acc_list = self.load_map(self.default_map_dir)
if len(default_pedal_list) == 0 or len(default_acc_list) == 0:
self.get_logger().warning(
"No default map file was found in {}".format(self.default_map_dir)
)

response.graph_image = []
print("svg data is empty")

response.accel_map = ""
print("accel map is empty")

response.brake_map = ""
print("brake map is empty")

return response

calibrated_pedal_list, calibrated_acc_list = self.load_map(self.calibrated_map_dir)
if len(calibrated_pedal_list) == 0 or len(calibrated_acc_list) == 0:
self.get_logger().warning(
"No calibrated map file was found in {}".format(self.calibrated_map_dir)
)

# visualize point from data
plot_width = 3
plot_height = int(math.ceil(len(CF.VEL_LIST) / float(plot_width)))
plotter = Plotter(plot_height, plot_width)
for i in range(len(CF.VEL_LIST)):
self.view_pedal_accel_graph(
plotter,
i,
velocity_map_list,
i,
count_map,
average_map,
stddev_map,
default_pedal_list,
default_acc_list,
calibrated_pedal_list,
calibrated_acc_list,
)
plt.savefig("plot.svg")
print("svg saved")

# pack response data
text = Path("plot.svg").read_text()
if text == "":
response.graph_image = []
print("svg data is empty")
else:
byte = text.encode()
for b in byte:
response.graph_image.append(b)
print("svg data is packed")
yabuta marked this conversation as resolved.
Show resolved Hide resolved

accel_map_name = Path(self.calibrated_map_dir + "accel_map.csv")
if accel_map_name.exists():
with open(self.calibrated_map_dir + "accel_map.csv", "r") as calibrated_accel_map:
for accel_data in calibrated_accel_map:
response.accel_map += accel_data
print("accel map is packed")
else:
response.accel_map = ""
print("accel map is empty")

brake_map_name = Path(self.calibrated_map_dir + "brake_map.csv")
if brake_map_name.exists():
with open(self.calibrated_map_dir + "brake_map.csv", "r") as calibrated_brake_map:
for brake_data in calibrated_brake_map:
response.brake_map += brake_data
print("brake map is packed")
else:
response.brake_map = ""
print("brake map is empty")

return response

def plotter_function(self):
return self.plotter

def view_pedal_accel_graph(
self,
plotter,
subplot_num,
velocity_map_list,
vel_list_idx,
count_map,
average_map,
stddev_map,
default_pedal_list,
default_acc_list,
calibrated_pedal_list,
calibrated_acc_list,
):

fig = plotter.subplot_more(subplot_num)

# calibrated map
if len(calibrated_pedal_list) != 0 and len(calibrated_acc_list) != 0:
plotter.plot(
calibrated_pedal_list[vel_list_idx],
calibrated_acc_list[vel_list_idx],
color="blue",
label="calibrated",
)

# default map
if len(default_pedal_list) != 0 and len(default_acc_list) != 0:
plotter.plot(
default_pedal_list[vel_list_idx],
default_acc_list[vel_list_idx],
color="orange",
label="default",
linestyle="dashed",
)

# plot all data
pedal_list = [0 for i in range(len(CF.PEDAL_LIST))]
if velocity_map_list[vel_list_idx] is not None:
plotter.scatter_color(
velocity_map_list[vel_list_idx][:, 1],
velocity_map_list[vel_list_idx][:, 2],
color=velocity_map_list[vel_list_idx][:, 3],
label="all",
)

for pedal in velocity_map_list[vel_list_idx][:, 1]:
min_pedal = 10
for pedal_idx, ref_pedal in enumerate(CF.PEDAL_LIST):
if min_pedal > abs(pedal - ref_pedal):
min_pedal = abs(pedal - ref_pedal)
min_pedal_idx = pedal_idx
pedal_list[min_pedal_idx] += 1

# plot average data
plotter.scatter(CF.PEDAL_LIST, average_map[:, vel_list_idx], "red", label="average")

# add label of standard deviation
plotter.scatter([], [], "black", label="std dev")

# plot average text
for i in range(len(CF.PEDAL_LIST)):
if count_map[i, vel_list_idx] == 0:
continue
x = CF.PEDAL_LIST[i]
y = average_map[i, vel_list_idx]
y2 = stddev_map[i, vel_list_idx]
# plot average
plotter.plot_text(x, y + 1, y, color="red")

# plot standard deviation
plotter.plot_text(x, y - 1, y2, color="black")

# plot the number of all data
plotter.plot_text(
x, y - 2, "{}\npts".format(pedal_list[i]), num_data_type="str", color="green"
)

pedal_lim = [CF.PEDAL_LIST[0] - 0.05, CF.PEDAL_LIST[-1] + 0.05]
accel_lim = [-5.0, 5.0]

plotter.set_lim(fig, pedal_lim, accel_lim)
plotter.add_label(
str(CF.VEL_LIST[vel_list_idx]) + "kmh; pedal-accel relation", "pedal", "accel"
)

def load_map(self, csv_dir):
try:
accel_pedal_list = []
accel_acc_list = []
with open(csv_dir + "accel_map.csv") as f:
for l_idx, l in enumerate(f.readlines()):
w = l.split(",")
w[-1] = w[-1][:-1]
if l_idx != 0:
accel_pedal_list.append([float(w[0]) for e in w[1:]])
accel_acc_list.append([float(e) for e in w[1:]])

brake_pedal_list = []
brake_acc_list = []
with open(csv_dir + "brake_map.csv") as f:
for l_idx, l in enumerate(f.readlines()):
w = l.split(",")
w[-1] = w[-1][:-1]
if l_idx != 0:
brake_pedal_list.append([-float(w[0]) for e in w[1:]])
brake_acc_list.append([float(e) for e in w[1:]])

return np.hstack(
[np.fliplr(np.array(accel_pedal_list).T), np.array(brake_pedal_list).T.tolist()]
), np.hstack([np.fliplr(np.array(accel_acc_list).T), np.array(brake_acc_list).T])
except OSError as e:
print(e)
return [], []


def main(args=None):
rclpy.init(args=None)
node = DrawGraph()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()


if __name__ == "__main__":
main()
Loading