Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Mock global path implementation #61

Merged
merged 56 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
ba7ef54
Created mock global path node
SPDonaghy Nov 4, 2023
32304c5
added some validation
SPDonaghy Nov 4, 2023
9c6d4be
used numpy for even spacing of waypoints
SPDonaghy Nov 11, 2023
de1107f
small change to check something git related
SPDonaghy Nov 11, 2023
8574c81
Launch mgp node
patrick-5546 Nov 15, 2023
24735e8
Only launch mgp if in development mode
patrick-5546 Nov 15, 2023
5997d2f
Merge branch 'main' into user/SPDonaghy/mock-global-path-49
patrick-5546 Nov 15, 2023
e57d368
Remove duplicate launch argument
patrick-5546 Nov 15, 2023
b195393
mgp node runs now, as expected
SPDonaghy Nov 16, 2023
31186a3
added method to convert to string array
SPDonaghy Nov 25, 2023
f97e19f
Implemented async Service between navigate and mgp
SPDonaghy Nov 29, 2023
fd48495
comit
SPDonaghy Nov 30, 2023
d3e7d06
some changes
SPDonaghy Nov 30, 2023
a6755e8
fixed issue with csv reader
SPDonaghy Nov 30, 2023
7675125
latest changes
SPDonaghy Dec 5, 2023
acd21a1
Gpath is topic again, made test for generate path
SPDonaghy Dec 7, 2023
8449560
Fix file diff
patrick-5546 Dec 7, 2023
28eacd2
Formatting
patrick-5546 Dec 7, 2023
07514fc
adjusted based on PR feedback
SPDonaghy Dec 8, 2023
ec539d2
Merge branch 'user/SPDonaghy/mock-global-path-49' of https://github.c…
SPDonaghy Dec 8, 2023
a984ffd
Further flatten
patrick-5546 Dec 8, 2023
f710f21
added a visualizer, doesn't read csv yet
SPDonaghy Dec 8, 2023
f1856f6
Merge branch 'user/SPDonaghy/mock-global-path-49' of https://github.c…
SPDonaghy Dec 8, 2023
8fb815b
Fix log levels
patrick-5546 Dec 8, 2023
7c349d5
Remove global path instance variable
patrick-5546 Dec 8, 2023
7befb7e
Use coord_systems
patrick-5546 Dec 8, 2023
84fc1e7
Print global path nicer
patrick-5546 Dec 8, 2023
96a58ee
Fix argument name
patrick-5546 Dec 8, 2023
ea09f81
Formatting
patrick-5546 Dec 8, 2023
82e8511
changed to check for filepath change first
SPDonaghy Dec 8, 2023
df38dc4
generate path overwrites file
SPDonaghy Dec 8, 2023
ad0fe99
updated test
SPDonaghy Dec 8, 2023
31816fb
Move to global_paths directory
patrick-5546 Dec 8, 2023
04b03f0
Cleanup plotting script
patrick-5546 Dec 8, 2023
f77ed42
modified generate path to accept new args
SPDonaghy Dec 9, 2023
c1b3c7c
added parameters and CLI args for
SPDonaghy Dec 9, 2023
ac32d34
added new features to generate_path
SPDonaghy Dec 10, 2023
64b6b17
new interpolate path func
SPDonaghy Dec 13, 2023
b9bc17b
interpolater is tested and works
SPDonaghy Dec 14, 2023
d74109f
added purge script
SPDonaghy Dec 14, 2023
23241bd
implemented force param to make callback run
SPDonaghy Dec 14, 2023
63a839a
implemented a path builder GUI
SPDonaghy Dec 14, 2023
d518254
some restructuring to clean things up
SPDonaghy Dec 18, 2023
142e3da
map refresh and some other
SPDonaghy Dec 18, 2023
eee0a7e
visual improvements
SPDonaghy Dec 20, 2023
da18a87
Formatting
patrick-5546 Dec 20, 2023
ef44874
Merge remote-tracking branch 'origin/main' into user/SPDonaghy/mock-g…
patrick-5546 Jan 1, 2024
5aa5348
removed argument option from generate path
SPDonaghy Jan 8, 2024
f699d57
combined files into path_builder
SPDonaghy Jan 8, 2024
2df7e24
moving some functions to global scope
SPDonaghy Jan 8, 2024
628b275
readme for path_builder
SPDonaghy Jan 8, 2024
1ff51a2
refactoring, added delete CLA
SPDonaghy Jan 9, 2024
c0dcffb
small changes
SPDonaghy Jan 9, 2024
9e1b88b
formatted readme
SPDonaghy Jan 9, 2024
eb6cc52
conversation resolves
SPDonaghy Jan 9, 2024
e3685a0
updated log msg for gps_thresh
SPDonaghy Jan 9, 2024
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
34 changes: 33 additions & 1 deletion launch/main_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,11 @@ def setup_launch(context: LaunchContext) -> List[Node]:
Returns:
List[Node]: Nodes to launch.
"""
launch_description_entities = list()
mode = LaunchConfiguration("mode").perform(context)
SPDonaghy marked this conversation as resolved.
Show resolved Hide resolved
launch_description_entities = []
launch_description_entities.append(get_navigate_node_description(context))
if mode == "development":
patrick-5546 marked this conversation as resolved.
Show resolved Hide resolved
launch_description_entities.append(get_mock_global_path_node_description(context))
return launch_description_entities


Expand Down Expand Up @@ -97,3 +100,32 @@ def get_navigate_node_description(context: LaunchContext) -> Node:
)

return node


def get_mock_global_path_node_description(context: LaunchContext) -> Node:
"""Gets the launch description for the mgp_main node.

Args:
context (LaunchContext): The current launch context.

Returns:
Node: The node object that launches the mgp_main node.
"""
node_name = "mgp_main"
ros_parameters = [LaunchConfiguration("config").perform(context)]
ros_arguments: List[SomeSubstitutionsType] = [
"--log-level",
[f"{node_name}:=", LaunchConfiguration("log_level")],
]

node = Node(
package=PACKAGE_NAME,
executable="mock_global_path",
name=node_name,
output="screen",
emulate_tty=True,
parameters=ros_parameters,
ros_arguments=ros_arguments,
)

return node
141 changes: 141 additions & 0 deletions local_pathfinding/node_mock_global_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
"""The main node of the local_pathfinding package, represented by the `Sailbot` class."""

from typing import List

import numpy as np
import rclpy
from custom_interfaces.msg import GPS, HelperLatLon, Path
from rclpy.node import Node

# Destination is hardcoded temporarily as a single element list
DESTINATION = []
DESTINATION.append(HelperLatLon(lat=49.263, lon=-123.138))

NUM_INTERVALS = 100


def main(args=None):
rclpy.init(args=args)
global_path = GlobalPath()

rclpy.spin(node=global_path)

global_path.destroy_node()
rclpy.shutdown()


class GlobalPath(Node):
"""Stores, and publishes the global path.

Subscribers:
SPDonaghy marked this conversation as resolved.
Show resolved Hide resolved
gps_sub (Subscription): Subscribe to a `GPS` msg.

Publishers and their timers:
global_path_pub (Subscription): Subscribe to a `Path` msg.
global_path_timer (Timer): Call the global path callback function.

Attributes from subscribers:
gps (GPS): Data from the GPS sensor.
"""

def __init__(self):
super().__init__(node_name="mock_global_path")

self.declare_parameters(
namespace="",
parameters=[
("pub_period_sec", rclpy.Parameter.Type.DOUBLE),
("global_path_param", DESTINATION),
],
)

# subscribers
self.gps_sub = self.create_subscription(
msg_type=GPS, topic="gps", callback=self.gps_callback, qos_profile=10
)

# publishers and their timers
self.global_path_pub = self.create_publisher(
msg_type=Path, topic="global_path", qos_profile=10
)
pub_period_sec = self.get_parameter("pub_period_sec").get_parameter_value().double_value
self.get_logger().info(f"Got parameter: {pub_period_sec=}")
self.global_path_timer = self.create_timer(
timer_period_sec=pub_period_sec, callback=self.global_path_callback
)

# attributes from subscribers
self.gps = None

# subscriber callbacks

def gps_callback(self, msg: GPS):
self.get_logger().info(f"Received data from {self.gps_sub.topic}: {msg}")
self.gps = msg

# publisher callbacks

def global_path_callback(self):
"""Get and publish the global path."""
if self.gps is not None:
global_path = self.get_global_path()

if global_path is None or len(global_path) < NUM_INTERVALS + 1:
self.get_logger().warning("Global path is invalid")

msg = Path()
msg.waypoints = global_path

self.global_path_pub.publish(msg)
self.get_logger().info(f"Publishing to {self.global_path_pub.topic}: {msg}")

# get_global_path and its helper functions

def get_global_path(self) -> List[HelperLatLon]:
"""Get the global path.

Returns:
List[HelperLatLon]: The global path.
"""
if not self._all_subs_active():
self._log_inactive_subs_warning()
return []

current_location = self.gps.latlon

global_path = self.get_parameter("global_path_param").get_parameter_value

# Check if global path parameter is just a destination point
if len(global_path) < 2:
SPDonaghy marked this conversation as resolved.
Show resolved Hide resolved
if len(global_path) < 1:
self.get_logger().warning("Global path has 0 elements. Must have at least 1.")
# TODO do something here to handle this

# Create a simple global path from the single destination point
# There will be some distortion here, so the intermediate points wont be evenly spaced
latitudes = np.linspace(current_location.lat, global_path[0].lat, NUM_INTERVALS + 1)
longitudes = np.linspace(current_location.lon, global_path[0].lon, NUM_INTERVALS + 1)

global_path = []

for i in range(NUM_INTERVALS):
global_path.append(
HelperLatLon(
lat=latitudes[i],
lon=longitudes[i],
)
)
return global_path

return global_path

def _all_subs_active(self) -> bool:
return True # TODO: this line is a placeholder, delete when mocks can be run
SPDonaghy marked this conversation as resolved.
Show resolved Hide resolved

def _log_inactive_subs_warning(self):
# TODO: log which subscribers are inactive
self.get_logger().warning("There are inactive subscribers")
SPDonaghy marked this conversation as resolved.
Show resolved Hide resolved


if __name__ == "__main__":
main()
25 changes: 13 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,28 @@

from setuptools import setup

package_name = 'local_pathfinding'
package_name = "local_pathfinding"

setup(
name=package_name,
version='0.0.0',
version="0.0.0",
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages', ['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name), glob('launch/*_launch.py')),
("share/ament_index/resource_index/packages", ["resource/" + package_name]),
("share/" + package_name, ["package.xml"]),
(os.path.join("share", package_name), glob("launch/*_launch.py")),
],
install_requires=['setuptools'],
install_requires=["setuptools"],
zip_safe=True,
maintainer='Patrick Creighton',
maintainer_email='software@ubcsailbot.org',
maintainer="Patrick Creighton",
maintainer_email="software@ubcsailbot.org",
description="UBC Sailbot's local pathfinding ROS package",
license='MIT',
tests_require=['pytest'],
license="MIT",
tests_require=["pytest"],
entry_points={
'console_scripts': [
'navigate = local_pathfinding.node_navigate:main',
"console_scripts": [
"navigate = local_pathfinding.node_navigate:main",
"mock_global_path = local_pathfinding.node_mock_global_path:main",
],
},
)