lots of work on tools
This commit is contained in:
		
							parent
							
								
									c9e872c355
								
							
						
					
					
						commit
						b3e9dd75ca
					
				| @ -25,6 +25,7 @@ class UGVComms(E32): | |||||||
|         self.ack_cv = threading.Condition() |         self.ack_cv = threading.Condition() | ||||||
|         self.next_command_id = 1 |         self.next_command_id = 1 | ||||||
|         self.last_status = None |         self.last_status = None | ||||||
|  |         self.last_status_time = None | ||||||
|         self.rx_thread = None |         self.rx_thread = None | ||||||
|         self.is_running = False |         self.is_running = False | ||||||
| 
 | 
 | ||||||
| @ -89,11 +90,15 @@ class UGVComms(E32): | |||||||
|                 self.ack_cv.notify() |                 self.ack_cv.notify() | ||||||
|         elif msg.HasField("status"): |         elif msg.HasField("status"): | ||||||
|             self.last_status = msg.status |             self.last_status = msg.status | ||||||
|  |             self.last_status_time = time.time() | ||||||
|  |         else: | ||||||
|  |             log.warn("unknown UGV message: %s", msg) | ||||||
| 
 | 
 | ||||||
|     def start(self): |     def start(self): | ||||||
|         if self.is_running: |         if self.is_running: | ||||||
|             log.warning("RX thread already running") |             log.warning("RX thread already running") | ||||||
|             return False |             return False | ||||||
|  |         self.is_running = True | ||||||
|         self.rx_thread = Thread(target=self.__rx_thread_entry, daemon=True) |         self.rx_thread = Thread(target=self.__rx_thread_entry, daemon=True) | ||||||
|         self.rx_thread.start() |         self.rx_thread.start() | ||||||
|         log.debug("started RX thread") |         log.debug("started RX thread") | ||||||
|  | |||||||
| @ -5,12 +5,23 @@ import serial | |||||||
| import time | import time | ||||||
| import logging | import logging | ||||||
| import readline | import readline | ||||||
|  | import yaml | ||||||
| 
 | 
 | ||||||
| from ugv import UGVComms | from ugv import UGVComms | ||||||
| import messages_pb2 as messages | import messages_pb2 as messages | ||||||
|  | import config_pb2 | ||||||
| 
 | 
 | ||||||
| log = logging.getLogger("ugv_cmd") | log = logging.getLogger("ugv_cmd") | ||||||
| 
 | 
 | ||||||
|  | def dict2pb(d, pb): | ||||||
|  |     for key in d: | ||||||
|  |         val = d[key] | ||||||
|  |         if isinstance(val, dict): | ||||||
|  |             dict2pb(val, getattr(pb, key)) | ||||||
|  |         else: | ||||||
|  |             setattr(pb, key, val) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class UGV_CLI: | class UGV_CLI: | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         self.is_running = False |         self.is_running = False | ||||||
| @ -20,7 +31,16 @@ class UGV_CLI: | |||||||
|             'h': self.help_msg, |             'h': self.help_msg, | ||||||
|             '?': self.help_msg, |             '?': self.help_msg, | ||||||
|             'exit': self.exit, |             'exit': self.exit, | ||||||
|             'q': self.exit |             'q': self.exit, | ||||||
|  |             'disable': self.disable, | ||||||
|  |             'd': self.disable, | ||||||
|  |             'target': self.set_target, | ||||||
|  |             'config': self.set_config, | ||||||
|  |             'c': self.set_config, | ||||||
|  |             'drive_heading': self.drive_heading, | ||||||
|  |             'drive_to_target': self.drive_to_target, | ||||||
|  |             'get_status': self.get_status, | ||||||
|  |             's': self.get_status, | ||||||
|         } |         } | ||||||
|         pass |         pass | ||||||
| 
 | 
 | ||||||
| @ -37,45 +57,58 @@ exit, q, C-c, C-d:  Quit the program | |||||||
|     def disable(self): |     def disable(self): | ||||||
|         self.ugv.write_command(messages.CMD_DISABLE) |         self.ugv.write_command(messages.CMD_DISABLE) | ||||||
| 
 | 
 | ||||||
|     def set_target(self): |     def set_target(self, lat=34.068415, long=-118.443217): | ||||||
|         # TODO: parse arguments somehow |  | ||||||
|         cmd = messages.GroundCommand() |         cmd = messages.GroundCommand() | ||||||
|         cmd.type = messages.CMD_SET_TARGET |         cmd.type = messages.CMD_SET_TARGET | ||||||
|         cmd.target_location.latitude = 34.068415 |         cmd.target_location.latitude = lat | ||||||
|         cmd.target_location.longitude = -118.443217 |         cmd.target_location.longitude = long | ||||||
|         self.ugv.write_command(cmd) |         self.ugv.write_command(cmd) | ||||||
|  |         log.info("set target to (%d, %d)", lat, long) | ||||||
| 
 | 
 | ||||||
|     def set_config(self): |     def set_config(self): | ||||||
|         # TODO: read from config.yml |         with open('./tools/config.yml', 'r') as configfile: | ||||||
|  |             config = yaml.load(configfile) | ||||||
|  | 
 | ||||||
|  |         if 'REVISION' in config: | ||||||
|  |             config_rev = config['REVISION'] | ||||||
|  |             del config['REVISION'] | ||||||
|  |         else: | ||||||
|  |             config_rev = 1 | ||||||
|  | 
 | ||||||
|         cmd = messages.GroundCommand() |         cmd = messages.GroundCommand() | ||||||
|         cmd.type = messages.CMD_SET_CONFIG |         cmd.type = messages.CMD_SET_CONFIG | ||||||
|         cmd.config.angle_pid.kp = 0.10 |         dict2pb(config, cmd.config) | ||||||
|         cmd.config.angle_pid.ki = 0  # .00005 |  | ||||||
|         cmd.config.angle_pid.kd = 0.4 |  | ||||||
|         cmd.config.angle_pid.max_output = 0.5 |  | ||||||
|         cmd.config.angle_pid.max_i_error = 15.0 |  | ||||||
|         cmd.config.min_target_dist = 10.0 |  | ||||||
|         cmd.config.min_flip_pitch = 90.0 |  | ||||||
|         self.ugv.write_command(cmd) |         self.ugv.write_command(cmd) | ||||||
|  |         log.info("updated config") | ||||||
| 
 | 
 | ||||||
|     def drive_heading(self): |     def drive_heading(self, heading=65, power=0.0): | ||||||
|         # TODO: parse arguments somehow |  | ||||||
|         cmd = messages.GroundCommand() |         cmd = messages.GroundCommand() | ||||||
|         cmd.type = messages.CMD_DRIVE_HEADING |         cmd.type = messages.CMD_DRIVE_HEADING | ||||||
|         cmd.drive_heading.heading = -115.0 - 180 |         cmd.drive_heading.heading = float(heading) | ||||||
|         cmd.drive_heading.power = 0.3 |         cmd.drive_heading.power = float(power) | ||||||
|         self.ugv.write_command(cmd) |         self.ugv.write_command(cmd) | ||||||
|         time.sleep(2.0) |         log.info("driving heading %d at power %d", heading, power) | ||||||
|  | 
 | ||||||
|  |     def drive_to_target(self): | ||||||
|  |         cmd = messages.GroundCommand() | ||||||
|  |         cmd.type = messages.CMD_DRIVE_TO_TARGET | ||||||
|  |         self.ugv.write_command(cmd) | ||||||
|  |         log.info("driving to target") | ||||||
|  | 
 | ||||||
|  |     def get_status(self): | ||||||
|  |         if self.ugv.last_status_time is None: | ||||||
|  |             log.info("no status received") | ||||||
|  |         else: | ||||||
|  |             last_status_delay = time.time() - self.ugv.last_status_time | ||||||
|  |             log.info("last status (%.4f seconds ago): %s", last_status_delay, self.ugv.last_status) | ||||||
| 
 | 
 | ||||||
|     def start(self): |     def start(self): | ||||||
|         self.is_running = True |         self.is_running = True | ||||||
|         readline.parse_and_bind('tab: complete') |  | ||||||
|         #readline.parse_and_bind('set editing-mode vi') |  | ||||||
| 
 | 
 | ||||||
|         if len(sys.argv) >= 2: |         if len(sys.argv) >= 2: | ||||||
|             ser_url = sys.argv[1] |             ser_url = sys.argv[1] | ||||||
|         else: |         else: | ||||||
|             ser_url = "loop://" |             ser_url = "hwgrep://USB1" | ||||||
|         ser = serial.serial_for_url(ser_url, baudrate=9600, parity=serial.PARITY_NONE, |         ser = serial.serial_for_url(ser_url, baudrate=9600, parity=serial.PARITY_NONE, | ||||||
|                                     stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, |                                     stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, | ||||||
|                                     timeout=0.5) |                                     timeout=0.5) | ||||||
| @ -93,7 +126,10 @@ exit, q, C-c, C-d:  Quit the program | |||||||
|                 except KeyError: |                 except KeyError: | ||||||
|                     print("Unknown command: '%s'" % line_parts[0]) |                     print("Unknown command: '%s'" % line_parts[0]) | ||||||
|                     continue |                     continue | ||||||
|                 cmd() |                 try: | ||||||
|  |                     cmd(*line_parts[1:]) | ||||||
|  |                 except Exception as e: | ||||||
|  |                     print("Error executing command: ", e) | ||||||
|             # TODO: continuously write state |             # TODO: continuously write state | ||||||
|             # while True: |             # while True: | ||||||
|             #    if self.ugv.last_status is None or self.ugv.last_status.state is not messages.STATE_DRIVE_HEADING: |             #    if self.ugv.last_status is None or self.ugv.last_status.state is not messages.STATE_DRIVE_HEADING: | ||||||
| @ -111,5 +147,5 @@ exit, q, C-c, C-d:  Quit the program | |||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     logging.basicConfig(format='%(asctime)s [%(name)s] %(levelname)s: %(message)s', datefmt='%Y-%b-%d %H:%M:%S') |     logging.basicConfig(format='%(asctime)s [%(name)s] %(levelname)s: %(message)s', datefmt='%Y-%b-%d %H:%M:%S') | ||||||
|     logging.getLogger().setLevel(logging.DEBUG) |     logging.getLogger().setLevel(logging.INFO) | ||||||
|     UGV_CLI().start() |     UGV_CLI().start() | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user