Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
#encoding=utf-8
'''
project overview:
Subscribe:
1.slam pose(global/local pose) *
2.octomap_server/global map
3.local pointcloud/local octomap
4.target input(semantic target/visual pose target/gps target)
Publish:
1.Mavros(amo) Command
2.Navigator status
Algorithms:
1.D*
2.state transfer
3.position->position PID controller
4.global/semantic/visual target to local pose
'''
import threading
import time
from path_optimization.path_pruning import PathPruning
# for ros
import rospy
from geometry_msgs.msg import PoseStamped, Twist
from std_msgs.msg import Float32, String
from sensor_msgs.msg import Imu, NavSatFix, PointCloud, PointCloud2
import sensor_msgs.point_cloud2 as pc2
from visualization_msgs.msg import Marker,MarkerArray
# for mavros
from mavros_msgs.msg import GlobalPositionTarget, State, PositionTarget#, Command
from mavros_msgs.srv import CommandBool, SetMode
# for octomap
from octomap_msgs.msg import Octomap, OctomapWithPose, octomap_msgs
# other useful utilities
#from pyquaternion import Quaternion
import pyquaternion
import astar.astar
import astar.driver
import time
import math
from enum import Enum
import thread
#from queue import Queue
#from Pos2PosController import Pos2PosController as Controller # TODO:re-implement this.
from SimController import Controller as Controller
import DiscreteGridUtils
import numpy as np
# define system status
class status(Enum):
INITIALIZED = 1
LOOKING_FOR_PATH = 2
LOOKING_FOR_PATH_SUCCEED = 3
LOOKING_FOR_PATH_FAILED = 4
GOING_TO_TARGET = 5
GOING_TO_VISION_TARGET = 6
def dist(pos1,pos2):
if not pos1 or not pos2:
return False, 0
else:
return True, reduce(lambda x,y:x+y,map(lambda i:(pos1[i]-pos2[i])**2,[0,1,2]))
class Navigator:
def __init__(self,config_file_path = None):
if config_file_path:
pass
rospy.init_node("gi_navigator_node")
self.dg = DiscreteGridUtils.DiscreteGridUtils(grid_size=0.2)#0.2)
self.rate = rospy.Rate(50)
self.driver = astar.driver.Driver()
self.controller = Controller()
self.mavros_state = "OFFBOARD"
self.set_status(status.INITIALIZED)
self.cur_command_id = 0
self.prev_command_id = 0
self.cur_target_position=None
self.task_id = -1
self.obstacle_set_mutex = threading.Lock() # mutex.acquire(timeout);mutex.release()
self.nav_command_mutex = threading.Lock() # for nav command in dstar and ros high level command.
self.local_pose = None
t1 = threading.Thread(target=self.ros_thread)
t1.start()
self.navigator_status_pub = rospy.Publisher('/gi/navigator_status', String, queue_size=10)
self.path_plan_pub = rospy.Publisher('/gi/navi_path_plan',MarkerArray,queue_size=10)
#t2 = thread.start_new_thread(self.Dstar_thread, ())
#self.keep_navigating()
self.path = []
self.path_prune = PathPruning(obstacle_distance=8)
'''
Navigating thread
'''
def keep_navigating(self):
# for debug:
#self.algo = astar.astar.A_star((1,0,0))
while self.mavros_state == "OFFBOARD" and not(rospy.is_shutdown()):
# print ('Inside outer loop!')
#print ("Navigator state: ", self.STATUS.data, "Mavros state: ", self.mavros_state)
relative_pos = (0, 0, 0)
end_pos = self.get_latest_target()
current_pos = self.get_current_pose() # TODO:fix this.
if current_pos is None:
#print ('current pose not valid!')
continue
while current_pos != end_pos and not self.navi_task_terminated() and not(rospy.is_shutdown()): # Till task is finished:
# print ('Inside inner loop!')
current_pos = self.get_current_pose()
self.algo = astar.astar.A_star(end_pos)
print ('Move 1 step')
obstacle_map = self.driver.get_obstacles_around() # TODO:加入障碍记忆.
print ('From ', current_pos)
t1 = time.time()
self.driver.algo = astar.astar.A_star(end_pos)
self.path = self.algo.find_path(current_pos, self.driver.get_obstacles_around())
t2 = time.time()
print('A* time cost:', (t2 - t1))
if not self.path:
#TODO set status
print ('No path found!')
self.do_hover() # TODO
time.sleep(0.05) # TODO
else:
# Path found. keep state machine and do task step by step.
self.collear_check_path = self.path_prune.remove_collinear_points(self.path)
self.bresenham_check_path = self.path_prune.path_pruning_bresenham3d(self.collear_check_path, obstacle_map)
#publish raw path plan.
m_arr = MarkerArray()
marr_index = 0
for next_move in self.path:
point = self.dg.discrete_to_continuous_target((next_move[0],next_move[1],next_move[2]))
mk = Marker()
mk.header.frame_id="map"
mk.action=mk.ADD
mk.id=marr_index
marr_index+=1
mk.color.r = 1.0
mk.color.a = 1.0
mk.type=mk.CUBE
mk.scale.x = 0.3
mk.scale.y = 0.3
mk.scale.z = 0.3
mk.pose.position.x = point[0]
mk.pose.position.y = point[1]
mk.pose.position.z = point[2]
m_arr.markers.append(mk)
self.path_plan_pub.publish(m_arr)
for next_move in self.bresenham_check_path:
self.path_plan_pub.publish(m_arr)
if self.navi_task_terminated():
break
print ('current_pos:', current_pos)
next_pos = next_move
relative_pos = (next_pos[0] - current_pos[0], next_pos[1] - current_pos[1],
next_pos[2] - current_pos[2])
print ('next_move : ', next_move)
print ("relative_move : ", relative_pos)
if not self.driver.algo.is_valid(next_pos, self.driver.get_obstacles_around()):
print ('Path not valid!')
break
self.current_pos = next_pos
#axis transform
relative_pos_new = (-relative_pos[0], -relative_pos[1], relative_pos[2])
#self.controller.mav_move(*relative_pos_new,abs_mode=False) # TODO:fix this.
print ('mav_move() input: relative pos=',next_pos)
self.controller.mav_move(*self.dg.discrete_to_continuous_target((next_pos[0],next_pos[1],next_pos[2])), abs_mode=True) # TODO:fix this.
current_pos = self.get_current_pose()
time.sleep(2)
predict_move = (self.current_pos[0] + relative_pos[0], self.current_pos[1] + relative_pos[1],
self.current_pos[2] + relative_pos[2])
print ("predict_move : ", predict_move)
if not self.algo.path_is_valid(self.bresenham_check_path, self.driver.get_obstacles_around()):
print ('Path conflict detected!')
break
time.sleep(0.05) # wait for new nav task.
'''
if self.found_path:
print("Found path!")
target_position = self.cur_target_position
result = False
while result is False:
result = self.mav_move(target_position[0], target_position[1], target_position[2])
print("Reached Position: ", target_position[0], target_position[1], target_position[2])
print("Finished Current Path")
time.sleep(0.2)
'''
print("Mavros not in OFFBOARD mode, Disconnected!")
'''
move quad in body frame
'''
def distance(self, p1, p2):
x_distance = (p2[0] - p1[0])**2
y_distance = (p2[1] - p1[1])**2
z_distance = (p2[2] - p1[2])**2
return np.sqrt(x_distance + y_distance + z_distance)
def remove_collinear_points(self, original_path):
new_path = []
print ("original_path length: ", len(original_path))
length = len(original_path) - 2
new_path.append(original_path[0])
# new_path.append(original_path[-1])
print(original_path)
for i in range(length):
distance13 = self.distance(original_path[i+2], original_path[i])
distance12 = self.distance(original_path[i+1], original_path[i])
distance23 = self.distance(original_path[i+2], original_path[i+1])
print("distance13 - distance12 - distance23 :", distance13 - distance12 - distance23 )
if abs(distance13 - distance12 - distance23) < 0.001:
# print ("points collinear")
continue
else:
print(original_path[i+1])
print("not found collinear point")
new_path.append(original_path[i+1])
print("new path length: ", len(new_path))
print(new_path)
return new_path
def terminate_navigating(self):
#TODO
pass
def resume_navigating(self):
#TODO
pass
def set_target_postion(self, target_position):
self.found_path = True
self.cur_target_position = target_position
#print("Set Current Position to: ", target_position[0], target_position[1], target_position[2])
def get_latest_target(self):
return self.cur_target_position
def set_vision_target(self):
self.set_status(status.GOING_TO_VISION_TARGET)
self.set_target_position(xxxxx) #TODO
pass
def navi_task_terminated(self):
if dist(self.local_pose,self.cur_target_position) <0.25: #TODO: or stop flag is set.
return True
else:
return False
'''
Dstar Thread
def Dstar_thread(self):
while not rospy.is_shutdown():
while status!= xxx:# TODO
next_move = xxx
return next_move'''
'''##For test:
target = [0.5, 0.5, 0.5]
self.set_target_postion(target)
pass'''
'''
ROS thread
responsible for subscribers and publishers
'''
def ros_thread(self):
print('ros_thread spawn!!!!')
self.octomap_msg = None
# subscribers
self.slam_sub = rospy.Subscriber("/gi/slam_output/pose", PoseStamped, self.slam_pose_callback)
self.vision_target_sub = rospy.Subscriber("/gi/visual_target/pose", PoseStamped, self.vision_target_callback)
self.point_cloud_sub = rospy.Subscriber("/camera/left/point_cloud", PointCloud, self.point_cloud_callback)
self.octomap_cells_vis = rospy.Subscriber("/octomap_point_cloud_centers", PointCloud2, self.octomap_update_callback)
self.local_pose_sub = rospy.Subscriber("/mavros/local_position/pose", PoseStamped, self.local_pose_callback)
self.mavros_sub = rospy.Subscriber("/mavros/state", State, self.mavros_state_callback)
# publishers
#self.mavros_control_pub = rospy.Publisher('mavros/Command', Command, queue_size=10)
self.set_status(status.INITIALIZED)
rospy.spin()
'''
ROS callbacks
'''
def slam_pose_callback(self, msg):
self.slam_pose = msg
def vision_target_callback(self, msg):
self.vision_target = msg
#print("Received New Vision Target!")
def mavros_state_callback(self, msg):
self.mavros_state = msg.mode
#print(msg.mode, type(msg.mode))
self.navigator_status_pub.publish(self.STATUS)
def point_cloud_callback(self, msg):
self.current_point_cloud = msg
def octomap_update_callback(self, msg): # as pointcloud2.
obs_set = set()
for p in pc2.read_points(msg, field_names=("x", "y", "z"), skip_nans=True):
#print " x : %f y: %f z: %f" % (p[0], p[1], p[2])
point = self.dg.continuous_to_discrete((p[0],p[1],p[2]))
#print ('point:',point)
obs_set.add(point)
acquired = self.obstacle_set_mutex.acquire(True) # blocking.
if acquired:
#print('octomap updated!')
self.driver.set_obstacle_set(obs_set)
self.obstacle_set_mutex.release()
return
else:
print ('Lock not acquired!')
def local_pose_callback(self, msg):
pose_ = msg.pose.position #TODO:do fusion with visual slam.
self.local_pose = self.dg.continuous_to_discrete((pose_.x,pose_.y,pose_.z))
#print ('local_pose set!!!')
def get_local_pose(self): # in mavros axis.for command.
#print ('self.local_pose',self.local_pose)
return self.local_pose
def get_current_pose(self): # current pose:slam pose(in world axis)
return self.get_local_pose() # TODO:do transform T1 ^-1 * T2.
'''
helper functions
'''
def set_status(self, status):
self.STATUS = String(status.name)
'''
def reachTargetPosition(self, target, threshold = 0.1):
delta_x = math.fabs(self.local_pose.pose.position.x - target.pos_sp[0])
delta_y = math.fabs(self.local_pose.pose.position.y - target.pos_sp[1])
delta_z = math.fabs(self.local_pose.pose.position.z - target.pos_sp[2])
distance = (delta_x + delta_y + delta_z)
print("distance: ", distance, "threshold: ", threshold)
if distance < threshold:
return True
else:
return False
'''
def setMavMode(self, msg):
pass
if __name__ == '__main__':
nav = Navigator()
nav.set_target_postion((80, 0, 2))
nav.keep_navigating()
c7b2c4605This file is pinned to the selected release. Download the original to open it in your design tool.