| 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)) |
|---|