algorithm.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import rospy
4 import sys
5 import numpy as np
6 import actionlib
7 
8 from geometry_msgs.msg import Vector3
9 
10 from pioneer_mrs.msg import * # include msg for action
11 from pioneer_mrs.srv import *
12 
13 class Algorithm:
14  def __init__(self):
15  # robot parameters
16  self._hostname = rospy.get_param('~hostname', 'robot1')
17  self._hostnum = int(self._hostname[-1]) - 1 # index 0 to 4
18  self._comm_state = [False, False, False, False, False]
19 
20  # algorithm parameters
21  self._gain_q = 0.2
22  self._moving_distance = 0.0
23  self._pose_offset = np.array([(-1,1), (1,1), (0,0), (1,-1), (-1,-1)], dtype=np.float32)
24  self._gradient = np.array([(-1,1), (1,1), (0,0), (1,-1), (-1,-1)], dtype=np.float32)
25  self._team_pose = np.array([(0,0), (0,0), (0,0), (0,0), (0,0)], dtype=np.float32)
26  self._my_pose = np.array((0,0), dtype=np.float32)
27 
28  # sub and pub init
29  rospy.Subscriber("comm_state", CommunicationState, self.communication_state_callback)
30  self.vel_hp_pub = rospy.Publisher("cmd_vel_hp", Vector3, queue_size=1)
31 
32  # service client init
33  for i in range(5):
34  rospy.wait_for_service("/robot" + str(i+1) + "/get_pose")
35  get_pose_1 = rospy.ServiceProxy("/robot1/get_pose", Pose2D, persistent=True)
36  get_pose_2 = rospy.ServiceProxy("/robot2/get_pose", Pose2D, persistent=True)
37  get_pose_3 = rospy.ServiceProxy("/robot3/get_pose", Pose2D, persistent=True)
38  get_pose_4 = rospy.ServiceProxy("/robot4/get_pose", Pose2D, persistent=True)
39  get_pose_5 = rospy.ServiceProxy("/robot5/get_pose", Pose2D, persistent=True)
40  self.get_pose = (get_pose_1, get_pose_2, get_pose_3, get_pose_4, get_pose_5)
41 
42  # action server init
43  self._feedback = pioneer_mrs.msg.FormationFeedback()
44  self._result = pioneer_mrs.msg.FormationResult()
45  self._action_name = "Formation"
46  self._as = actionlib.SimpleActionServer(self._action_name, pioneer_mrs.msg.FormationAction, \
47  execute_cb=self.action_callback, auto_start=False)
48  self._as.start()
49 
50  # done
51  rospy.loginfo(self._hostname + " algorithm_node launched.")
52  rospy.spin()
53 
54 
56  for i in range(5):
57  self._comm_state[i] = msg.state[i]
58 
59 
60  def action_callback(self, goal):
61  # action started
62  success = True
63  rospy.loginfo(self._hostname + " algorithm_node action started")
64 
65  # run action for goal.order steps
66  rate = rospy.Rate(10)
67  for step in range(1, goal.order):
68  # send feedback and check preempt every second
69  if step % 10 == 0:
70  self._feedback.name = self._hostname
71  self._feedback.x = self._my_pose[0]
72  self._feedback.y = self._my_pose[1]
73  self._as.publish_feedback(self._feedback)
74  if self._as.is_preempt_requested():
75  self._as.set_preempted()
76  success = False
77  rospy.logerr(self._hostname + " algorithm_node action preempted")
78  break
79  # run algorithm
80  self.run_algorithm()
81  rate.sleep()
82 
83  # action succeeded
84  if success:
85  self._result.name = self._hostname
86  self._result.x = self._my_pose[0]
87  self._result.y = self._my_pose[1]
88  self._as.set_succeeded(self._result)
89  rospy.loginfo(self._hostname + " algorithm_node action succeeded")
90 
91 
92  def update_team_pose(self):
93  for i in range(5):
94  # call get_pose service
95  srv = self.get_pose[i]()
96  # convert srv type to numpy type
97  self._team_pose[i][0] = srv.x
98  self._team_pose[i][1] = srv.y
99  # get my pose
100  self._my_pose = self._team_pose[self._hostnum]
101 
102 
103  def run_algorithm(self):
104  # make a log for communication time
105  rospy.loginfo(self._hostname + " algorithm_node: Updating team pose.")
106  self.update_team_pose()
107  rospy.loginfo(self._hostname + " algorithm_node: Updated team pose.")
108 
109  # prepare local variables (add offset to prevent robots from crashing into the same consensus point)
110  team_pose_with_offset = self._team_pose - self._pose_offset
111  my_pose_with_offset = self._my_pose - self._pose_offset[self._hostnum]
112  vel_sum = np.array((0,0), dtype=np.float32)
113  moving_distance = np.array((self._moving_distance ,0), dtype=np.float32)
114 
115  # consensus algorithm makes it keep formation
116  for i in range(5):
117  # check communication graph and the correctness of pose data
118  if self._comm_state[i] and self._team_pose[i].any() != 0:
119  vel = (team_pose_with_offset[i] - my_pose_with_offset) * self._gain_q
120  vel_sum = vel_sum + vel
121  rospy.loginfo(self._hostname + " algorithm_node: robot" + str(i+1) + \
122  " pose (% .4f,% .4f)", self._team_pose[i][0], self._team_pose[i][1])
123  rospy.loginfo(self._hostname + " algorithm_node: vel" + str(i+1) + \
124  " (% .4f,% .4f)", vel[0], vel[1])
125 
126  # gradient descent makes the consensus point stick to the optimal point
127  gradient = my_pose_with_offset - self._gradient[self._hostnum]
128  vel_sum = vel_sum - (gradient - moving_distance)
129  rospy.loginfo(self._hostname + " algorithm_node: gradient (% .4f,% .4f)", gradient[0], gradient[1])
130 
131  # publish velocity result (vel of hand point)
132  vel_hp = Vector3()
133  vel_hp.x = vel_sum[0]
134  vel_hp.y = vel_sum[1]
135  self.vel_hp_pub.publish(vel_hp)
136  rospy.loginfo(self._hostname + " algorithm_node: pub vel_hp (% .4f,% .4f)", vel_hp.x, vel_hp.y)
137 
138 
139 if __name__ == '__main__':
140  rospy.init_node('algorithm_node')
141  try:
142  algorithm = Algorithm()
143  except rospy.ROSInterruptException:
144  pass
def communication_state_callback(self, msg)
Definition: algorithm.py:55
def update_team_pose(self)
Definition: algorithm.py:92
def __init__(self)
Definition: algorithm.py:14
def run_algorithm(self)
Definition: algorithm.py:103
def action_callback(self, goal)
Definition: algorithm.py:60


pioneer_mrs
Author(s): Hanzhe Teng
autogenerated on Thu Mar 5 2020 03:17:35