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

Kart commander #46

Open
wants to merge 34 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
3e3ace6
Initial Commit
berliernj Apr 12, 2023
2c75908
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 12, 2023
36bf7ad
Fixed bug due to name change
berliernj Apr 14, 2023
c6505db
kart_commander node initial
Reschivon Apr 16, 2023
da0bac3
kChange twist setup to single mux
Reschivon Apr 16, 2023
56f99e9
Add constants for TrackState and KartState response
Reschivon Apr 16, 2023
6e6184a
Changed trackstate srv package to match the new name
Reschivon Apr 16, 2023
7f74120
bug fixes during testing
Reschivon Apr 16, 2023
afd5286
Add test cases
Reschivon Apr 16, 2023
4511e3d
amp_commander: Add new mux node and docs
Reschivon May 10, 2023
59f684b
amp_commander: remove debug log
Reschivon May 10, 2023
7438da3
amp_lint install scripts breaking ci
Reschivon May 10, 2023
abddec2
amp_lint: appease ci
Reschivon May 11, 2023
3d7dcb7
Merge branch 'main' into kart_commander
Reschivon May 11, 2023
341b0fa
amp_ci: remove tests
Reschivon May 11, 2023
fbca70a
Initial Commit
berliernj Apr 12, 2023
eb4ca84
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 12, 2023
1512010
kart_commander node initial
Reschivon Apr 16, 2023
b0134cb
kChange twist setup to single mux
Reschivon Apr 16, 2023
a6a320b
Add constants for TrackState and KartState response
Reschivon Apr 16, 2023
88283cc
Changed trackstate srv package to match the new name
Reschivon Apr 16, 2023
0114b40
bug fixes during testing
Reschivon Apr 16, 2023
a012786
Add test cases
Reschivon Apr 16, 2023
2ef9007
amp_commander: Add new mux node and docs
Reschivon May 10, 2023
b917104
amp_commander: remove debug log
Reschivon May 10, 2023
e1796b8
amp_lint install scripts breaking ci
Reschivon May 10, 2023
bc110ad
amp_lint: appease ci
Reschivon May 11, 2023
2db155a
amp_ci: remove tests
Reschivon May 11, 2023
1f3757f
amp_rcs_client: fix
alanssitis May 11, 2023
5e134cc
amp_commander: Change trackstate server name to trackstatereciever
Reschivon May 12, 2023
a2b4793
amp_commander: added metadat to package.xml
Reschivon May 12, 2023
80c6780
Merge branch 'kart_commander' of github.com:Autonomous-Motorsports-Pu…
Reschivon May 12, 2023
8c3d313
amp_ci: add license to package.xml
Reschivon May 12, 2023
d1b4b96
amp_commander: change from service to client since someone
Reschivon May 12, 2023
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
46 changes: 17 additions & 29 deletions src/amp_kart_bringup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,25 @@ Contains files needed to start the kart.

## Mux structure

The muxes used are [`twist_mux`](http://wiki.ros.org/twist_mux).
They are laid out as can be seen below.
There are two control sources that both produce `twist_mux` messages to `cmd_vel`: joy_vel (teleop controller) and nav_vel (autnomous navigation).
The RCS provides some track states (safe stop, estop, teleop, auto) that control which input we select. The kart_commander uses these states to determine which control source to let through, or neither.

The priorities are implemented with `switch_mux`, a node defined in `kart_commander`

```
/joy_disable /joy_enable
| |
| | /stop
____ | |
| | /mux1_vel ____
/joy_vel ____| |_____________| |
| | | |
|____| | |____ /cmd_vel
mux1 | |
/nav_vel ___| |
|____|
mux2
/topic_select
|
|
_|___
/joy_vel____| |
| |____ /cmd_vel
| |
switch_mux
| |
/nav_vel ___| |
|_____|
```

Priorities for the muxes are listed below, as well as the corresponding topic
and (expected) topic publishers:

- `mux1` → `/mux1_vel`
- `joy_disable` ~ `kart_commander`: 150
- `joy_vel` ~ `teleop_twist_joy_node`: 100
- `mux2` → `/cmd_vel`
- `stop` ~ `kart_commander`: 255
- `joy_enable` ~ `kart_commander`: 50
- `nav_vel` ~ `nav2`: 10
- `mux1_vel` ~ `mux1`: 100

## Directory Tree

- `config/`
Expand All @@ -48,7 +37,7 @@ and (expected) topic publishers:
- `rviz.launch.py` _Initialize RViz with Nav2 configuration_
- `slam.launch.py` _Initialize map_server and slam_toolbox_
- `teleop.launch.py` _Launch joy teleop nodes_
- `twist_mux.launch.py` _Launch both twist muxex_
- `kart_commander.launch.py` _Launch kart_commander and the twist muxes_
- `VLP16.launch.py` _Initialize Velodyne LIDAR VLP16 nodes_
- `zed.launch.py` _Zed camera launch file_
- `map/`
Expand All @@ -58,7 +47,6 @@ and (expected) topic publishers:
- `VLP16db.params.yaml` _VLP16 calibration parameters_
- `nav2.params.yaml` _Nav2 parameters_
- `patchworkpp.params.yaml` _Patchwork++ parameters_
- `twist_mux_1.params.yaml`
- `twist_mux_2.params.yaml`
- `switch_mux.params.yaml`
- `rviz/`
- `nav2_default_view.rviz.yaml` _RViz config for Nav2_
31 changes: 31 additions & 0 deletions src/amp_kart_bringup/launch/kart_commander.launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os

from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node


def generate_launch_description():

params_file = os.path.join(get_package_share_directory('amp_kart_bringup'),
'params', 'switch_mux.params.yaml')

switch_mux_action = Node(package='amp_kart_commander',
namespace='',
executable='switch_mux',
name='switch_mux',
parameters=[params_file])

kart_commander_action = Node(package='amp_kart_commander',
namespace='',
executable='kart_commander',
name='kart_commander')

ld = LaunchDescription()
ld.add_action(switch_mux_action)
ld.add_action(kart_commander_action)

return ld
44 changes: 0 additions & 44 deletions src/amp_kart_bringup/launch/twist_mux.launch.py

This file was deleted.

6 changes: 6 additions & 0 deletions src/amp_kart_bringup/params/switch_mux.params.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
switch_mux:
ros__parameters:
input_topics:
- joy_vel
- nav_vel
initial_topic: __none
12 changes: 0 additions & 12 deletions src/amp_kart_bringup/params/twist_mux_1.params.yaml

This file was deleted.

20 changes: 0 additions & 20 deletions src/amp_kart_bringup/params/twist_mux_2.params.yaml

This file was deleted.

24 changes: 24 additions & 0 deletions src/amp_kart_commander/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Kart Commander

Kart Commander hosts a Service Server that listens for TrackState changes from the RCS node and manipulates the switch_mux accordingly.

Might consider moving the mux diagram from `bringup/launch/twist_mux` here. There's more elaboration on this node in particular there. Somebody fix the rest,

Note that while you can reach `Stop` from any other state, returning to `Autonomous` from `Stop` is not allowed; switch to RC first.

## `switch_mux`

An one-in, one-out mux for `Twist` messages, since ROS2 does not support generic message types in Foxy.
Publishes to a `Twist` topic named "cmd_vel" and takes in a configurable list of `Twist` topics

- Parameters
- `initial_topic`: (optional) name of the initial `Twist` topic to pass through
- `input_topics`: list of `Twist` topics to listen for
- Subscribed Topics
- `select_topic`: `String` name of topic from `input_topics` to pass through, or `__none`, ehich explicitly turns off the mux
- Published Topics
- `cmd_vel`: Twist topic output chosen from the inputs, or nothing at all

## Tests

See the README in the test folder
Empty file.
62 changes: 62 additions & 0 deletions src/amp_kart_commander/amp_kart_commander/kart_commander.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'''Server that receives updates to TrackState from RCS and sets the kart cmd_vel mux accordingly'''

#usr/bin/env python3
from amp_msgs.srv import TrackState
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

from rclpy.qos import QoSProfile, HistoryPolicy, DurabilityPolicy, ReliabilityPolicy

# Create high-reliability QoS for mux toggling
qos_profile = QoSProfile(
history=HistoryPolicy.KEEP_LAST,
depth=1, # Last always has priority anyways
reliability=ReliabilityPolicy.RELIABLE, # Guaranteed delivery
durability=DurabilityPolicy.
TRANSIENT_LOCAL # Re-send msg to late-joining subscribers
)


class ServiceServer(Node):

def __init__(self):
super().__init__('service_server')
self.server = self.create_service(TrackState, 'track_state',
Reschivon marked this conversation as resolved.
Show resolved Hide resolved
self.track_state_callback)
self.mux_publisher = self.create_publisher(String,
'select_topic',
qos_profile=qos_profile)

def track_state_callback(self, request, response):
response.state = request.state

self.get_logger().info('Recieved: %s Response: %s' %
(request.state, response.state))

# self.get_logger().info('eeee' + str(dir(TrackState.Request)))

# TODO More complex states in TrackState.srv have transition rules not yet implemented

if response.state == TrackState.Request.EMERGENCY or response.state == TrackState.Request.SAFESTOP:
self.mux_publisher.publish(String(data='__none'))
self.get_logger().info('STOP: nav2 and teleop disabled')
if response.state == TrackState.Request.RC or response.state == TrackState.Request.RACEDONE:
self.mux_publisher.publish(String(data='joy_vel'))
self.get_logger().info('RC: joy only')
if response.state == TrackState.Request.AUTONOMOUS_SLOW or response.state == TrackState.Request.AUTONOMOUS_OVERTAKE:
self.mux_publisher.publish(String(data='nav_vel'))
self.get_logger().info('AUTO: nav2 only')

return response


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


if __name__ == 'main':
main()
82 changes: 82 additions & 0 deletions src/amp_kart_commander/amp_kart_commander/switch_mux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
''' Mux the allows choosing a single topic to let through '''
#usr/bin/env python3
import rclpy
import functools

from rclpy.node import Node
from std_msgs.msg import String
from geometry_msgs.msg import Twist
from rclpy.exceptions import ParameterNotDeclaredException

from rclpy.qos import QoSProfile, HistoryPolicy, DurabilityPolicy, ReliabilityPolicy
# Create lossy QoS that is compatible with any publisher
subscriber_any = QoSProfile(history=HistoryPolicy.KEEP_LAST,
depth=5,
reliability=ReliabilityPolicy.BEST_EFFORT,
durability=DurabilityPolicy.VOLATILE)

# Create high-reliability QoS for topic selection
reliable = QoSProfile(
history=HistoryPolicy.KEEP_LAST,
depth=1, # Last always has priority anyways
reliability=ReliabilityPolicy.RELIABLE, # Guaranteed delivery
durability=DurabilityPolicy.TRANSIENT_LOCAL # Re-send msg to late-joiners
)

EMPTY_TOPIC = "__none"


class SwitchMux(Node):

def __init__(self):
super().__init__('switch_mux', allow_undeclared_parameters=True)

self.declare_parameter('initial_topic', String)
self.declare_parameter('input_topics')

# `initial_topic` is optionally defined at initialization
try:
self.current_topic = self.get_parameter('initial_topic').value
except ParameterNotDeclaredException:
self.current_topic = EMPTY_TOPIC

# `input_topics` must be defined at initialization
self.input_topics = self._parameters['input_topics'].value
if self.input_topics is None:
raise ParameterNotDeclaredException('input_topics')

for topic_name in self.input_topics:
# This specific name is disallowed to guarantee that it disables the mux
if topic_name == EMPTY_TOPIC:
continue
# All input topics share the same base callback (input_topic_callback), but we
# bind a third `topic_name` parameter that changes with the topic
named_callback = functools.partial(self.input_topic_callback,
topic_name)
self.create_subscription(Twist, topic_name, named_callback,
subscriber_any)

# Topic name
self.subscription = self.create_subscription(String, 'select_topic',
self.set_topic_callback,
reliable)
self.publisher = self.create_publisher(Twist, 'cmd_vel', reliable)

def set_topic_callback(self, topic_name_msg):
self.current_topic = str(topic_name_msg.data)

def input_topic_callback(self, topic_name, twist_msg):
''' Upon receiving a message to any registered input of the mux'''
if topic_name == self.current_topic:
self.publisher.publish(twist_msg)


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


if __name__ == 'main':
main()
13 changes: 13 additions & 0 deletions src/amp_kart_commander/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" ?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>amp_kart_commander</name>
<version>0.0.0</version>
<description>Updates cmd_vel max based on TrackState changes</description>
<maintainer email="[email protected]">lucy</maintainer>
<license>TODO: License declaration</license>

<export>
<build_type>ament_python</build_type>
</export>
</package>
Empty file.
4 changes: 4 additions & 0 deletions src/amp_kart_commander/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[develop]
script_dir=$base/lib/amp_kart_commander
[install]
install_scripts=$base/lib/amp_kart_commander
Loading