Skip to content

Commit f7da10f

Browse files
authored
feat(route_client): add route_client (autowarefoundation#67)
Signed-off-by: Fumiya Watanabe <rej55.g@gmail.com>
1 parent ad0b811 commit f7da10f

File tree

4 files changed

+195
-0
lines changed

4 files changed

+195
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
cmake_minimum_required(VERSION 3.5)
2+
project(autoware_route_client)
3+
4+
find_package(autoware_cmake REQUIRED)
5+
autoware_package()
6+
7+
find_package(std_msgs REQUIRED)
8+
9+
ament_auto_package()
10+
11+
install(PROGRAMS
12+
scripts/route_client.py
13+
DESTINATION lib/${PROJECT_NAME}
14+
)
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Route Client
2+
3+
This package contains a tool to send request to set route.
4+
5+
## Usage
6+
7+
### Prepare a route file
8+
9+
Prepare a YAML file containing route information.
10+
The file format is like following:
11+
12+
```yaml
13+
goal:
14+
position:
15+
x: 0.0
16+
y: 0.0
17+
z: 0.0
18+
orientation:
19+
x: 0.0
20+
y: 0.0
21+
z: 0.0
22+
w: 0.0
23+
segments:
24+
- preferred:
25+
id: 0
26+
type: lane
27+
alternatives:
28+
- id: 1
29+
type: lane
30+
- preferred:
31+
id: 2
32+
type: lane
33+
alternatives: []
34+
- preferred:
35+
id: 3
36+
type: lane
37+
alternatives:
38+
- id: 4
39+
type: lane
40+
```
41+
42+
### Send request to set route
43+
44+
Execute following command.
45+
46+
```bash
47+
ros2 run autoware_route_client route_client.py <path_to_yaml_file>
48+
```
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0"?>
2+
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
3+
<package format="3">
4+
<name>autoware_route_client</name>
5+
<version>0.1.0</version>
6+
<description>The autoware_route_client package</description>
7+
<maintainer email="fumiya.watanabe@tier4.jp">Fumiya Watanabe</maintainer>
8+
<license>Apache License 2.0</license>
9+
10+
<author email="fumiya.watanabe@tier4.jp">Fumiya Watanabe</author>
11+
12+
<buildtool_depend>ament_cmake_auto</buildtool_depend>
13+
<buildtool_depend>autoware_cmake</buildtool_depend>
14+
15+
<depend>autoware_adapi_v1_msgs</depend>
16+
<depend>geometry_msgs</depend>
17+
<depend>rclpy</depend>
18+
<depend>std_msgs</depend>
19+
20+
<test_depend>ament_lint_auto</test_depend>
21+
<test_depend>autoware_lint_common</test_depend>
22+
23+
<export>
24+
<build_type>ament_cmake</build_type>
25+
</export>
26+
</package>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#! /usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
# Copyright 2024 TIER IV, Inc. All rights reserved.
5+
#
6+
# Licensed under the Apache License, Version 2.0 (the "License");
7+
# you may not use this file except in compliance with the License.
8+
# You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing, software
13+
# distributed under the License is distributed on an "AS IS" BASIS,
14+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
# See the License for the specific language governing permissions and
16+
# limitations under the License.
17+
18+
import argparse
19+
20+
from autoware_adapi_v1_msgs.msg import RouteOption
21+
from autoware_adapi_v1_msgs.msg import RoutePrimitive
22+
from autoware_adapi_v1_msgs.msg import RouteSegment
23+
from autoware_adapi_v1_msgs.srv import SetRoute
24+
from geometry_msgs.msg import Pose
25+
import rclpy
26+
from rclpy.node import Node
27+
from std_msgs.msg import Header
28+
import yaml
29+
30+
31+
class route_client(Node):
32+
def __init__(self):
33+
super().__init__("route_client")
34+
self.cli = self.create_client(SetRoute, "/api/routing/change_route")
35+
36+
while not self.cli.wait_for_service(timeout_sec=1.0):
37+
self.get_logger().info("service not available...")
38+
39+
self.req = SetRoute.Request()
40+
41+
def send_request(self, filepath):
42+
self.req.header = Header()
43+
self.req.header.frame_id = "map"
44+
self.req.header.stamp = self.get_clock().now().to_msg()
45+
self.req.option = RouteOption()
46+
self.req.option.allow_goal_modification = True
47+
48+
with open(filepath) as file:
49+
data = yaml.safe_load(file)
50+
self.req.goal = self.set_goal(data["goal"])
51+
self.req.segments = self.set_segments(data["segments"])
52+
self.future = self.cli.call_async(self.req)
53+
54+
def set_goal(self, goal):
55+
out = Pose()
56+
out.position.x = goal["position"]["x"]
57+
out.position.y = goal["position"]["y"]
58+
out.position.z = goal["position"]["z"]
59+
out.orientation.x = goal["orientation"]["x"]
60+
out.orientation.y = goal["orientation"]["y"]
61+
out.orientation.z = goal["orientation"]["z"]
62+
out.orientation.w = goal["orientation"]["w"]
63+
64+
return out
65+
66+
def set_segments(self, segments):
67+
out = []
68+
for segment in segments:
69+
out_segment = RouteSegment()
70+
out_segment.preferred.id = segment["preferred"]["id"]
71+
out_segment.preferred.type = segment["preferred"]["type"]
72+
for alt in segment["alternatives"]:
73+
out_alt = RoutePrimitive()
74+
out_alt.id = alt["id"]
75+
out_alt.type = alt["type"]
76+
out_segment.alternatives.append(out_alt)
77+
78+
out.append(out_segment)
79+
return out
80+
81+
82+
def main(args=None):
83+
rclpy.init(args=args)
84+
85+
parser = argparse.ArgumentParser(description="Send set route request.")
86+
parser.add_argument("filepath", type=str, help="path to yaml file containing route information")
87+
args = parser.parse_args()
88+
89+
client = route_client()
90+
client.send_request(args.filepath)
91+
92+
while rclpy.ok():
93+
rclpy.spin_once(client)
94+
if client.future.done():
95+
try:
96+
client.get_logger().info("Service requested.")
97+
except Exception as e:
98+
client.get_logger().info("Error: %r" % (e,))
99+
break
100+
101+
client.destroy_node()
102+
103+
rclpy.shutdown()
104+
105+
106+
if __name__ == "__main__":
107+
main()

0 commit comments

Comments
 (0)