Skip to content

Commit cfc4aa4

Browse files
committed
added lost_connection behavior (pain and suffering)
1 parent 52f592c commit cfc4aa4

File tree

2 files changed

+71
-39
lines changed

2 files changed

+71
-39
lines changed

src/rove_navigation/rove_navigation/lost_connection.py

Lines changed: 70 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,118 @@
22
import rclpy
33
from rclpy.node import Node
44
from rclpy.action import ActionClient
5-
from sensor_msgs.msg import PointCloud2
6-
import sensor_msgs_py.point_cloud2 as pc2
5+
from geometry_msgs.msg import PoseArray
76
from geometry_msgs.msg import Point, PoseStamped
87
from nav2_msgs.action import NavigateToPose
98
import numpy as np
109
from std_msgs.msg import Header
1110
from nav_msgs.msg import Odometry
12-
import constants
1311

1412
# Node to handle when the robot loses connection with internet, stores waypoints to fall back to to try to get back connection
1513
class LostNetworkFallback(Node):
1614

17-
def __init__(self):
18-
self.NB_FALLBACKS=100
19-
self.DISTANCE_BETWEEN_FALLBACKS = 2 # meters
15+
def __init__(self):
16+
self.DISTANCE_BETWEEN_FALLBACKS = 0.1 # meters
2017
self.NB_MAX_FAILED_CONNS = 3
2118
self.nbFailedConns = 0
2219
self.fallbackIndex = 0
2320
self.PING_RATE = 1 # seconds
2421

2522
self.ONLINE = 'ONLINE'
2623
self.OFFLINE = 'OFFLINE'
24+
self.WAITING = 'WAITING'
25+
26+
self.state = "ONLINE"
27+
self.traveling_to_fallback = False
2728

28-
self.state = constants.OFFLINE
2929
self.goal_handle = None
3030

3131
super().__init__('lost_network_fallback')
32+
self.get_logger().info('Initiating LostNetworkFallback node')
3233
self.create_timer(self.PING_RATE, self.check_connection)
3334
self.odometry_subscription = self.create_subscription(
3435
Odometry, '/odometry/local', self.odometry_callback, 10)
35-
self.action_client = ActionClient(self, LostNetworkFallback, 'lost_network_fallback')
36+
self.action_client = ActionClient(self, NavigateToPose, 'navigate_to_pose')
3637

37-
#list of potential fallback positions, always will be of size self.NB_FALLBACKS, ascending order
38-
self.fallback_position = [Point(x=0.0, y=0.0, z=0.0) for _ in range(self.NB_FALLBACKS)]
39-
self.current_position = Point(x=0.0, y=0.0, z=0.0)
38+
#list of potential fallback positions, ascending order
39+
self.fallback_positions = [Point(x=0.0,y=0.0,z=0.0)]
40+
self.fallback_positions.pop()
41+
self.current_position: Point
42+
4043

4144
# Check connection to google.com TODO: check connection to UI user instead
4245
def check_connection(self):
4346
try:
4447
socket.setdefaulttimeout(1) # in seconds
4548
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(("8.8.8.8", 53))
46-
self.nbFailedConns = -1
47-
if self.goal_handle != None:
48-
self.action_client._cancel_goal_async(self.goal_handle)
49-
self.goal_handle = None
50-
except:
49+
# if this following code runs, the connection was established
50+
self.nbFailedConns = 0
51+
if self.state != self.ONLINE:
52+
self.get_logger().info('Connection re-established to server! terminating fallback state')
53+
self.fallback_positions[self.fallbackIndex:]
54+
if self.goal_handle != None:
55+
self.action_client._cancel_goal_async(self.goal_handle)
56+
self.goal_handle = None
57+
self.state = self.ONLINE
58+
except socket.error:
5159
self.nbFailedConns += 1
52-
if self.nbFailedConns == self.NB_MAX_FAILED_CONNS:
53-
# TODO: cancel current state
54-
self.navigate_to_fallback(self.fallbackIndex)
55-
56-
def odometry_callback(self, msg : Odometry):
57-
# If robot at self.DISTANCE_BETWEEN_FALLBACKS distance or more from last fallback, add new fallback, delete the last one from the list
58-
self.current_position = Point(msg.pose.pose.position.x, msg.pose.pose.position.y, msg.pose.pose.position.z, )
59-
if(np.linalg.norm(self.current_position-self.fallback_position[0]) >= self.DISTANCE_BETWEEN_FALLBACKS):
60-
self.fallback_position.insert(0, self.current_position)
61-
self.fallback_position.pop()
60+
if self.state != self.WAITING and self.nbFailedConns >= self.NB_MAX_FAILED_CONNS:
61+
self.state = self.OFFLINE
62+
if self.nbFailedConns == self.NB_MAX_FAILED_CONNS:
63+
self.get_logger().warn(f'Connection Error!!! ping to server failed {self.nbFailedConns} '+
64+
'times in a row, activating fallback state, the robot will try to retrace its steps.')
65+
# TODO: cancel current state of general state_handler
66+
if not self.traveling_to_fallback and self.fallbackIndex < len(self.fallback_positions):
67+
self.traveling_to_fallback = True
68+
self.navigate_to_fallback()
6269

63-
def navigate_to_fallback(self, index):
64-
assert(index < self.DISTANCE_BETWEEN_FALLBACKS)
70+
71+
def navigate_to_fallback(self):
6572
# Prepare the goal message and send it
6673
goal_pose = PoseStamped()
6774
goal_pose.header = Header(frame_id='map')
6875

69-
goal_pose.pose.position = self.fallback_position[index]
76+
goal_pose.pose.position = self.fallback_positions[self.fallbackIndex]
7077
goal_pose.pose.orientation.w = 1.0 # Assuming no orientation preference
7178

72-
self.get_logger().info(f'Navigating to fallback at ({self.fallback_position.__str__()})')
79+
self.get_logger().warn(f'Navigating to fallback at ({self.fallback_positions[self.fallbackIndex].__str__()})')
7380
self.action_client.wait_for_server()
74-
self.send_goal(goal_pose)
75-
76-
def send_goal(self, goal_pose):
81+
7782
goal_msg = NavigateToPose.Goal()
7883
goal_msg.pose = goal_pose
79-
self.goal_handle = self.action_client.send_goal_async(goal_msg,self.fallback_point_reached).result()
80-
self.get_logger().info('Goal sent to navigation system.')
81-
82-
def fallback_point_reached(self):
83-
if self.state == self.OFFLINE:
84+
future = self.action_client.send_goal_async(goal_msg)
85+
self.goal_handle = future.result()
86+
future.add_done_callback(self.fallback_point_reached)
87+
88+
89+
def fallback_point_reached(self, _):
90+
self.traveling_to_fallback = False
91+
if self.state == self.OFFLINE and self.fallbackIndex < len(self.fallback_positions):
92+
self.get_logger().warn(f'Fallback {self.fallbackIndex} reached. Will attempt to reach next one if still offline.')
8493
self.fallbackIndex+=1
85-
self.navigate_to_fallback(self.fallbackIndex)
94+
if self.state == self.OFFLINE and self.fallbackIndex >= len(self.fallback_positions):
95+
self.state = self.WAITING
96+
self.get_logger().error(f'Last fallback reached, waiting and hoping for connection to come back :(')
97+
98+
def odometry_callback(self, msg : Odometry):
99+
current_position = Point(x=msg.pose.pose.position.x, y=msg.pose.pose.position.y, z=msg.pose.pose.position.z)
100+
# Sets the first position
101+
if len(self.fallback_positions) == 0:
102+
self.fallback_positions = [current_position]
103+
self.get_logger().info(f'First fallback position initiated: {self.fallback_positions[0]}')
104+
105+
# If robot at self.DISTANCE_BETWEEN_FALLBACKS distance or more from last fallback, add new fallback point
106+
if(self.state == self.ONLINE):
107+
if len(self.fallback_positions) == 0:
108+
self.fallback_positions.append(current_position)
109+
else:
110+
dist = [current_position.x-self.fallback_positions[0]._x,
111+
current_position.y-self.fallback_positions[0]._y,
112+
current_position.z-self.fallback_positions[0]._z]
113+
114+
if(np.linalg.norm(dist) >= self.DISTANCE_BETWEEN_FALLBACKS):
115+
self.fallback_positions.insert(0, current_position)
116+
self.get_logger().info(f'New fallback position added: {self.fallback_positions}')
86117

87118
def main(args=None):
88119
rclpy.init(args=args)

src/rove_navigation/setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
'person_following = rove_navigation.person_following:main',
3131
'frontier_publisher = rove_navigation.frontier_publisher:main',
3232
'exploration = rove_navigation.exploration:main',
33+
'lost_connection = rove_navigation.lost_connection:main',
3334
],
3435
},
3536
)

0 commit comments

Comments
 (0)