Skip to content

Commit

Permalink
more remapping tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ottojo committed Aug 25, 2023
1 parent 53777f5 commit d49b2e8
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 23 deletions.
31 changes: 29 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Unit Tests
name: Tests

on:
push:
Expand All @@ -8,7 +8,7 @@ on:
- develop

jobs:
test:
unit-test:
runs-on: ubuntu-22.04
container: ros:iron
steps:
Expand All @@ -32,3 +32,30 @@ jobs:
cd $GITHUB_WORKSPACE
. ./install/setup.sh
pytest-3 --color=yes ros2/orchestrator
pyright:
runs-on: ubuntu-22.04
container: ros:iron
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Install dependencies
run: |
. /opt/ros/$ROS_DISTRO/setup.sh
cd $GITHUB_WORKSPACE
apt update
rosdep update
rosdep install --from-paths ros2 --ignore-packages-from-source --verbose --default-yes --skip-keys="aduulm_cmake_tools aduulm_messages"
pip install --upgrade pyright
- name: Build orchestrator dependencies
run: |
. /opt/ros/$ROS_DISTRO/setup.sh
cd $GITHUB_WORKSPACE
colcon build --packages-up-to orchestrator --packages-skip orchestrator
- name: Run pyright
run: |
. /opt/ros/$ROS_DISTRO/setup.sh
cd $GITHUB_WORKSPACE
. ./install/setup.sh
cd ros2/orchestrator
pyright
43 changes: 23 additions & 20 deletions ros2/orchestrator/orchestrator/orchestrator_lib/orchestrator.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import datetime
from dataclasses import dataclass
from collections import defaultdict
from typing import Any, Generator, Tuple, cast, Union, Optional, List, Dict, Set
from typing import Any, Generator, Tuple, cast, Union, Optional, List, Dict, Set, Iterable
from typing_extensions import TypeAlias

from std_srvs.srv import Trigger
Expand All @@ -21,7 +21,7 @@
from orchestrator_interfaces.srv import ReconfigurationAnnouncement, ReconfigurationRequest

import rclpy
from rclpy import Future
from rclpy.task import Future
from rclpy.node import Node as RosNode
from rclpy.subscription import Subscription
from rclpy.publisher import Publisher
Expand Down Expand Up @@ -608,7 +608,7 @@ def __request_next_input(self):
next = self.next_input
self.next_input = None
self.l.info(f"Requesting data on topic {next.topic} for current time {self.simulator_time}")
if self.timing_analysis:
if self.next_input_timestamp is not None:
delta = datetime.datetime.now() - self.next_input_timestamp
self.l.info(f"Topic input was delayed by {delta}")
assert self.simulator_time is not None
Expand All @@ -622,7 +622,7 @@ def __request_next_input(self):
next = self.next_input
self.next_input = None
self.l.info(f"Requesting clock input for time {next.time}")
if self.timing_analysis:
if self.next_input_timestamp is not None:
delta = datetime.datetime.now() - self.next_input_timestamp
self.l.info(f"Clock input was delayed by {delta}")
self.__add_pending_timers_until(next.time)
Expand Down Expand Up @@ -652,9 +652,9 @@ def __buffer_childs_of_parent(self, parent: GraphNodeId) -> Generator[
yield id, data

def __edges_between(self, u: GraphNodeId, v: GraphNodeId) -> Generator[Tuple[Any, Dict], None, None]:
for e_u, e_v, e_k, e_d in self.graph.edges(nbunch=[u, v], data=True, keys=True):
for e_u, e_v, e_k, e_d in self.graph.edges(nbunch=[u, v], data=True, keys=True): # type: ignore
if e_u == u and e_v == v:
yield e_k, e_d
yield e_k, cast(Dict, e_d)

def __causality_childs_of(self, buffer_id: GraphNodeId) -> Generator[GraphNodeId, None, None]:
for node in self.graph.predecessors(buffer_id):
Expand Down Expand Up @@ -815,7 +815,7 @@ def __remove_node(self, graph_node: GraphNodeId, recursive=False):
self.graph.remove_node(graph_node)
if self.__graph_is_empty() and self.dataprovider_pending_actions_future is not None:
self.l.info(" Graph is now empty, allowing data provider to continue.")
if self.timing_analysis:
if self.dataprovider_pending_actions_future_timestamp is not None:
delta = datetime.datetime.now() - self.dataprovider_pending_actions_future_timestamp
self.l.info(f" Data provider state update was delayed by {delta}")
self.dataprovider_pending_actions_future.set_result(())
Expand Down Expand Up @@ -897,7 +897,7 @@ def __process(self):
if self.dataprovider_state_update_future is not None:
if not self.__has_nodes_that_change_provider_state():
self.l.info(" No actions which change provider state anymore, allowing data provider state update.")
if self.timing_analysis:
if self.dataprovider_state_update_future_timestamp is not None:
delta = datetime.datetime.now() - self.dataprovider_state_update_future_timestamp
self.l.info(f" Data provider state update was delayed by {delta}")
self.dataprovider_state_update_future.set_result(())
Expand All @@ -916,7 +916,7 @@ def __process(self):

def __reconfiguration_done_callback(self, future: Future):
assert future.done()
response: ReconfigurationRequest.Response = future.result()
response = cast(ReconfigurationRequest.Response, future.result())
package_name = response.new_launch_config_package
file_name = response.new_launch_config_filename
lc(self.l, f"Received reconfiguration done callback! New config: {package_name} {file_name}")
Expand Down Expand Up @@ -975,6 +975,7 @@ def __ready_for_next_input(self) -> bool:
if isinstance(data.cause, TopicInput) and data.cause.input_topic == self.next_input.topic:
return False
return True
assert False

def __graph_is_empty(self) -> bool:
return self.graph.number_of_nodes() == 0
Expand All @@ -998,8 +999,8 @@ def __find_running_action(self, published_topic_name: TopicName) -> int:
else:
raise RuntimeError(f"Unknown action type: {d}")

node_list = '\n'.join(
["(" + str(nid) + ", " + str(nd["data"]) + ")" for nid, nd in self.graph.nodes(data=True)])
node_list = '\n'.join(["(" + str(nid) + ", " + str(nd["data"]) + ")" for nid, nd in
cast(Iterable[tuple[Any, dict]], self.graph.nodes(data=True))])
raise ActionNotFoundError(
f"There is no currently running action which should have published a message on topic \"{published_topic_name}\"! "
f"Current graph nodes: \n{node_list}")
Expand Down Expand Up @@ -1028,7 +1029,7 @@ def plot_graph(self):
"""

try:
import netgraph
import netgraph # pyright: ignore [reportMissingImports]
except ImportError:
netgraph = None

Expand Down Expand Up @@ -1099,7 +1100,8 @@ def __interception_subscription_callback(self, topic_name: TopicName, msg: Any):

if self.ignore_next_input_from_topic[topic_name]:
self.ignore_next_input_from_topic[topic_name] = False
self.l.debug(f"Ignoring input from topic {topic_name} since it was already given to us by dataprovider_publish()")
self.l.debug(
f"Ignoring input from topic {topic_name} since it was already given to us by dataprovider_publish()")
return

if topic_name == normalize_topic_name("clock"):
Expand Down Expand Up @@ -1178,17 +1180,18 @@ def __interception_subscription_callback(self, topic_name: TopicName, msg: Any):
def __in_degree_by_type(self, node: GraphNodeId, edge_type: EdgeType) -> int:
""" Returns the in-degree of an edge filtered by edge type """
degree = 0
# type: ignore
for u, v, edge_data in self.graph.in_edges(node, data=True):
type: EdgeType = edge_data["edge_type"] # type: ignore
edge_data: dict
for u, v, edge_data in self.graph.in_edges(node, data=True): # type: ignore
type: EdgeType = edge_data["edge_type"]
if type == edge_type:
degree += 1
return degree

def __parent_node(self, node: GraphNodeId) -> Optional[GraphNodeId]:
parent = None
# type: ignore
for u, v, edge_data in self.graph.out_edges(node, data=True):

edge_data: dict
for u, v, edge_data in self.graph.out_edges(node, data=True): # type: ignore
type: EdgeType = edge_data["edge_type"] # type: ignore
if type == EdgeType.CAUSALITY:
if parent is not None:
Expand Down Expand Up @@ -1233,8 +1236,8 @@ def __status_callback(self, msg: Status):
except ActionNotFoundError:
self.l.warn(" Topic output was not expected, ignoring...")
continue
causing_action = cast(Union[CallbackAction, DataProviderInputAction],
self.graph.nodes[cause_action_id]["data"])
causing_action = cast(CallbackAction, self.graph.nodes[cause_action_id]["data"])
assert isinstance(causing_action, CallbackAction)
assert causing_action.node == msg.node_name
for buffer_id, buffer_data in list(self.__buffer_childs_of_parent(cause_action_id)):
if buffer_data.cause.input_topic == omitted_output_topic_name:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Type, Optional

from rclpy import Future
from rclpy.task import Future
from rclpy.executors import Executor
from rclpy.node import Node
from rclpy.impl.rcutils_logger import RcutilsLogger
Expand Down
5 changes: 5 additions & 0 deletions ros2/orchestrator/pyrightconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"include": [
"orchestrator"
]
}

0 comments on commit d49b2e8

Please sign in to comment.