1 | #!/usr/bin/python |
---|
2 | """ |
---|
3 | This module has the utility functions required by both leader and follower. |
---|
4 | These include common functionality like obtaining a mode from heartbeat message. |
---|
5 | """ |
---|
6 | import re, sys, os, socket, select, time |
---|
7 | |
---|
8 | import mavlink_apm |
---|
9 | |
---|
10 | class FTL_util: |
---|
11 | dict_mode_names = {} |
---|
12 | # mode names for APM |
---|
13 | # We can save this in the following way: x1,x2,x3 = A,B,C. But for |
---|
14 | # readability sake, we stick to this format |
---|
15 | stabilize_mode = 'STABILIZE' |
---|
16 | auto_mode = 'AUTO' |
---|
17 | guided_mode = 'GUIDED' |
---|
18 | rtl_mode = 'RTL' |
---|
19 | land_mode = 'LAND' |
---|
20 | of_loiter_mode = 'OF_LOITER' |
---|
21 | alt_hold_mode = 'ALT_HOLD' |
---|
22 | loiter_mode = 'LOITER' |
---|
23 | position_mode = 'POSITION' |
---|
24 | circle_mode = 'CIRCLE' |
---|
25 | approach_mode = 'APPROACH' |
---|
26 | acro_mode = 'ACRO' |
---|
27 | MAX_SIZE = 1024 |
---|
28 | """Constructor for the class. Takes nothing as argument and initializes |
---|
29 | the dictionary mapping for <custom_mode>->mode name""" |
---|
30 | def __init__(self): |
---|
31 | self.dict_mode_names[0] = self.stabilize_mode |
---|
32 | self.dict_mode_names[1] = self.acro_mode |
---|
33 | self.dict_mode_names[2] = self.alt_hold_mode |
---|
34 | self.dict_mode_names[3] = self.auto_mode |
---|
35 | self.dict_mode_names[4] = self.guided_mode |
---|
36 | self.dict_mode_names[5] = self.loiter_mode |
---|
37 | self.dict_mode_names[6] = self.rtl_mode |
---|
38 | self.dict_mode_names[7] = self.circle_mode |
---|
39 | self.dict_mode_names[8] = self.position_mode |
---|
40 | self.dict_mode_names[9] = self.land_mode |
---|
41 | self.dict_mode_names[10] = self.of_loiter_mode |
---|
42 | self.dict_mode_names[11] = self.approach_mode |
---|
43 | |
---|
44 | """Destructor for the class, we do nothing here """ |
---|
45 | def __del__(self): |
---|
46 | pass |
---|
47 | |
---|
48 | """Internal function: Given the base mode and custom mode, this |
---|
49 | function function returns the string for relevant mode. We are doing |
---|
50 | this as a different function as we may need to add some functionality |
---|
51 | here later. |
---|
52 | UPDATE: We are currently using only the custom_mode. We may update |
---|
53 | this part if the custom_mode is found to be insufficient""" |
---|
54 | def __return_mav_mode__(self, base_mode, custom_mode): |
---|
55 | if (custom_mode) in self.dict_mode_names: |
---|
56 | return self.dict_mode_names[custom_mode] |
---|
57 | else: |
---|
58 | return "" |
---|
59 | |
---|
60 | """ Internal function to get the custom_mode corresponding to a string. |
---|
61 | If mode is not found, returns -1 """ |
---|
62 | def __return_custom_mode__(self, mode_str): |
---|
63 | # Get the value of custom_mode corresponding to the string passed |
---|
64 | for key,value in self.dict_mode_names.items(): |
---|
65 | if value == mode_str: |
---|
66 | return key |
---|
67 | return -1 |
---|
68 | |
---|
69 | """ Function that receives the mode as a string and sets the mode. |
---|
70 | Returns 0 on success, -1 on failure""" |
---|
71 | def set_mav_mode(self,mode_str,mav_obj,mavproxy_sock,address_of_mavproxy): |
---|
72 | custom_mode = self.__return_custom_mode__(mode_str) |
---|
73 | |
---|
74 | # Basic error checking |
---|
75 | if custom_mode == -1 or not mav_obj or not mavproxy_sock or not address_of_mavproxy: |
---|
76 | return -1 |
---|
77 | msg = mav_obj.set_mode_encode(1, 1, custom_mode) |
---|
78 | list_read_sockets = [mavproxy_sock] |
---|
79 | list_write_sockets = list_error_sockets = [] |
---|
80 | # Do not proceed until the MAV is set to the given mode |
---|
81 | while 1: |
---|
82 | try: |
---|
83 | mavproxy_sock.sendto(msg.get_msgbuf(),(address_of_mavproxy)) |
---|
84 | data_from_mavproxy,address_of_mavproxy = mavproxy_sock.recvfrom (self.MAX_SIZE) |
---|
85 | except socket.error as v: |
---|
86 | print "Exception when trying to set AUTO mode:" |
---|
87 | print os.strerror(v.errno) |
---|
88 | time.sleep(1) |
---|
89 | continue |
---|
90 | |
---|
91 | decoded_message = mav_obj.decode(data_from_mavproxy) |
---|
92 | msg_id = decoded_message.get_msgId() |
---|
93 | # we are interested only if this is the heartbeat |
---|
94 | if msg_id == mavlink_apm.MAVLINK_MSG_ID_HEARTBEAT: |
---|
95 | # Get the mode from the message |
---|
96 | mode = self.get_mav_mode(str(decoded_message)) |
---|
97 | if mode.lower() == mode_str.lower(): |
---|
98 | print "Mode set as expected" |
---|
99 | return 0 |
---|
100 | else: |
---|
101 | continue |
---|
102 | |
---|
103 | |
---|
104 | """ Function that receives the heartbeat message as a string |
---|
105 | and extracts base_mode and custom_mode.""" |
---|
106 | def get_mav_mode (self, heartbeat_message): |
---|
107 | print "heartbeat message is %s" % heartbeat_message |
---|
108 | # Get base_mode |
---|
109 | match_for_base_mode = re.search(r'base_mode : (.+?),',heartbeat_message) |
---|
110 | if not match_for_base_mode: |
---|
111 | print "Error - no base_mode found, return!" |
---|
112 | return "" |
---|
113 | else: |
---|
114 | base_mode = match_for_base_mode.group(1) |
---|
115 | |
---|
116 | # Get custom_mode |
---|
117 | match_for_custom_mode = re.search(r'custom_mode : (.+?),',heartbeat_message) |
---|
118 | if not match_for_custom_mode: |
---|
119 | print "Error - no custom_mode found, return!" |
---|
120 | return "" |
---|
121 | else: |
---|
122 | custom_mode = match_for_custom_mode.group(1) |
---|
123 | return self.__return_mav_mode__(int(base_mode),int(custom_mode)) |
---|