2016-04-27 22:34:15 -03:00
#!/usr/bin/env python
# framework to start a simulated vehicle and connect it to MAVProxy
# Peter Barker, April 2016
# based on sim_vehicle.sh by Andrew Tridgell, October 2011
import optparse
import sys
import atexit
import os
2016-05-13 17:55:06 -03:00
import os . path
2016-04-27 22:34:15 -03:00
import subprocess
import tempfile
import getpass
import time
2016-04-28 23:16:53 -03:00
import signal
2016-04-27 22:34:15 -03:00
class CompatError ( Exception ) :
''' a custom exception class to hold state if we encounter the parse error we are looking for '''
def __init__ ( self , error , opts , rargs ) :
Exception . __init__ ( self , error )
self . opts = opts
self . rargs = rargs
class CompatOptionParser ( optparse . OptionParser ) :
''' An option parser which emulates the behaviour of the old sim_vehicle.sh; if passed -C, the first argument not understood starts a list of arguments that are passed straight to mavproxy '''
def __init__ ( self , * args , * * kwargs ) :
optparse . OptionParser . __init__ ( self , * args , * * kwargs )
def error ( self , error ) :
''' override default error handler called by optparse.OptionParser.parse_args when a parse error occurs; raise a detailed exception which can be caught '''
if error . find ( " no such option " ) != - 1 :
raise CompatError ( error , self . values , self . rargs )
optparse . OptionParser . error ( self , error )
def parse_args ( self ) :
''' wrap parse_args so we can catch the exception raised upon discovering the known parameter parsing error '''
mavproxy_args = [ ]
try :
opts , args = optparse . OptionParser . parse_args ( self )
except CompatError as e :
if not e . opts . sim_vehicle_sh_compatible :
print ( e )
2016-04-28 23:16:53 -03:00
print ( " Perhaps you want --sim_vehicle_sh_compatible (-C)? " )
2016-04-27 22:34:15 -03:00
sys . exit ( 1 )
if e . opts . mavproxy_args :
print ( " --mavproxy-args not permitted in compat mode " )
sys . exit ( 1 )
args = [ ]
opts = e . opts
mavproxy_args = [ ]
mavproxy_args . append ( str ( e ) [ 16 : ] ) # this trims "no such option" off
mavproxy_args . extend ( e . rargs )
opts . ensure_value ( " mavproxy_args " , " " . join ( mavproxy_args ) )
return opts , args
2016-04-28 23:16:53 -03:00
def cygwin_pidof ( procName ) :
''' Thanks to kata198 for this:
https : / / github . com / kata198 / cygwin - ps - misc / blob / master / pidof
'''
pipe = subprocess . Popen ( " ps -ea | grep " + procName , shell = True , stdout = subprocess . PIPE )
outputLines = pipe . stdout . read ( ) . replace ( " \r " , " " ) . split ( " \n " )
ret = pipe . wait ( )
pids = [ ]
if ret != 0 :
# No results
return [ ]
for line in outputLines :
if not line :
continue
lineSplit = [ item for item in line . split ( ' ' ) if item ]
cmd = lineSplit [ - 1 ] . split ( ' / ' ) [ - 1 ]
if cmd == procName :
try :
pid = int ( lineSplit [ 0 ] . strip ( ) )
except :
pid = int ( lineSplit [ 1 ] . strip ( ) )
pid = str ( pid )
if pid not in pids :
pids . append ( pid )
return pids
def under_cygwin ( ) :
return os . path . exists ( " /usr/bin/cygstart " )
def kill_tasks_cygwin ( victims ) :
2016-06-23 00:31:38 -03:00
''' shell out to ps -ea to find processes to kill '''
2016-04-28 23:16:53 -03:00
for victim in list ( victims ) :
pids = cygwin_pidof ( victim )
# progress("pids for (%s): %s" % (victim,",".join([ str(p) for p in pids])))
for apid in pids :
os . kill ( apid , signal . SIGKILL )
2016-06-23 00:31:38 -03:00
def kill_tasks_psutil ( victims ) :
''' use the psutil module to kill tasks by name. Sadly, this module is not available on Windows, but when it is we should be able to *just* use this routine '''
import psutil
for proc in psutil . process_iter ( ) :
if proc . status == psutil . STATUS_ZOMBIE :
continue
if proc . name in victims :
proc . kill ( )
def kill_tasks_pkill ( victims ) :
''' shell out to pkill(1) to kill processed by name '''
for victim in victims : # pkill takes a single pattern, so iterate
cmd = [ " pkill " ]
cmd . append ( victim )
run_cmd_blocking ( " pkill " , cmd , quiet = True )
class BobException ( Exception ) :
pass
2016-04-27 22:34:15 -03:00
def kill_tasks ( ) :
''' clean up stray processes by name. This is a somewhat shotgun approach '''
2016-06-23 00:33:52 -03:00
progress ( " Killing tasks " )
2016-06-23 00:31:38 -03:00
try :
2016-06-23 00:33:52 -03:00
victim_names = [
' JSBSim ' ,
' lt-JSBSim ' ,
' ArduPlane.elf ' ,
' ArduCopter.elf ' ,
' APMrover2.elf ' ,
' AntennaTracker.elf ' ,
' JSBSIm.exe ' ,
' MAVProxy.exe ' ,
' runsim.py ' ,
' AntennaTracker.elf ' ,
]
if under_cygwin ( ) :
return kill_tasks_cygwin ( victim_names )
try :
kill_tasks_psutil ( victim_names )
except ImportError as e :
kill_tasks_pkill ( victim_names )
except Exception as e :
progress ( " kill_tasks failed: {} " . format ( str ( e ) ) )
2016-04-27 22:34:15 -03:00
# clean up processes at exit:
atexit . register ( kill_tasks )
def check_jsbsim_version ( ) :
''' assert that the JSBSim we will run is the one we expect to run '''
2016-04-28 23:16:53 -03:00
jsbsim_cmd = [ " JSBSim " , " --version " ]
progress_cmd ( " Get JSBSim version " , jsbsim_cmd )
2016-05-15 22:58:53 -03:00
try :
jsbsim_version = subprocess . Popen ( jsbsim_cmd , stdout = subprocess . PIPE ) . communicate ( ) [ 0 ]
except OSError as e :
jsbsim_version = ' ' # this value will trigger the ".index"
# check below and produce a reasonable
# error message
2016-04-27 22:34:15 -03:00
try :
jsbsim_version . index ( " ArduPilot " )
except ValueError :
print ( '''
== == == == == == == == == == == == == == == == == == == == == == == == == == == == =
You need the latest ArduPilot version of JSBSim installed
and in your \$ PATH
Please get it from git : / / github . com / tridge / jsbsim . git
See
http : / / dev . ardupilot . org / wiki / simulation - 2 / sitl - simulator - software - in - the - loop / setting - up - sitl - on - linux /
for more details
== == == == == == == == == == == == == == == == == == == == == == == == == == == == =
''' )
sys . exit ( 1 )
def progress ( text ) :
''' display sim_vehicle progress text '''
print ( " SIM_VEHICLE: " + text )
def find_autotest_dir ( ) :
''' return path to autotest directory '''
return os . path . dirname ( os . path . realpath ( __file__ ) )
2016-05-12 00:32:36 -03:00
def find_root_dir ( ) :
''' return path to root directory '''
return os . path . realpath ( os . path . join ( find_autotest_dir ( ) , ' ../.. ' ) )
2016-04-27 22:34:15 -03:00
progress ( " Start " )
# define and run parser
parser = CompatOptionParser ( " sim_vehicle.py " , epilog = '''
eeprom . bin in the starting directory contains the parameters for your simulated vehicle . Always start from the same directory . It is recommended that you start in the main vehicle directory for the vehicle you are simulating , for example , start in the ArduPlane directory to simulate ArduPlane
''' )
2016-05-07 20:34:42 -03:00
2016-04-27 22:34:15 -03:00
parser . add_option ( " -v " , " --vehicle " , type = ' string ' , default = None , help = ' vehicle type (ArduPlane, ArduCopter or APMrover2) ' )
parser . add_option ( " -f " , " --frame " , type = ' string ' , default = None , help = ''' set aircraft frame type
for copters can choose + , X , quad or octa
for planes can choose elevon or vtail ''' )
parser . add_option ( " -C " , " --sim_vehicle_sh_compatible " , action = ' store_true ' , default = False , help = ' be compatible with the way sim_vehicle.sh works; make this the first option ' )
2016-05-07 20:34:42 -03:00
parser . add_option ( " -H " , " --hil " , action = ' store_true ' , default = False , help = " start HIL " )
group_build = optparse . OptionGroup ( parser , " Build options " )
group_build . add_option ( " -N " , " --no-rebuild " , action = ' store_true ' , default = False , help = " don ' t rebuild before starting ardupilot " )
group_build . add_option ( " -D " , " --debug " , action = ' store_true ' , default = False , help = " build with debugging " )
group_build . add_option ( " -c " , " --clean " , action = ' store_true ' , default = False , help = ' do a make clean before building ' )
2016-05-11 13:15:30 -03:00
group_build . add_option ( " -j " , " --jobs " , default = None , type = ' int ' , help = ' number of processors to use during build (default for waf : number of processor, for make : 1) ' )
2016-05-07 20:34:42 -03:00
group_build . add_option ( " -b " , " --build-target " , default = None , type = ' string ' , help = ' override SITL build target ' )
group_build . add_option ( " -s " , " --build-system " , default = " waf " , type = ' choice ' , choices = [ " make " , " waf " ] , help = ' build system to use ' )
group_build . add_option ( " " , " --no-rebuild-on-failure " , dest = " rebuild_on_failure " , action = ' store_false ' , default = True , help = ' if build fails, do not clean and rebuild ' )
parser . add_option_group ( group_build )
group_sim = optparse . OptionGroup ( parser , " Simulation options " )
group_sim . add_option ( " -I " , " --instance " , default = 0 , type = ' int ' , help = ' instance of simulator ' )
group_sim . add_option ( " -V " , " --valgrind " , action = ' store_true ' , default = False , help = ' enable valgrind for memory access checking (very slow!) ' )
group_sim . add_option ( " -T " , " --tracker " , action = ' store_true ' , default = False , help = " start an antenna tracker instance " )
group_sim . add_option ( " -A " , " --sitl-instance-args " , type = ' string ' , default = None , help = ' pass arguments to SITL instance ' )
#group_sim.add_option("-R", "--reverse-throttle", action='store_true', default=False, help="reverse throttle in plane")
group_sim . add_option ( " -G " , " --gdb " , action = ' store_true ' , default = False , help = " use gdb for debugging ardupilot " )
group_sim . add_option ( " -g " , " --gdb-stopped " , action = ' store_true ' , default = False , help = " use gdb for debugging ardupilot (no auto-start) " )
group_sim . add_option ( " -d " , " --delay-start " , default = 0 , type = ' float ' , help = ' delays the start of mavproxy by the number of seconds ' )
group_sim . add_option ( " -B " , " --breakpoint " , type = ' string ' , action = " append " , default = [ ] , help = ' add a breakpoint at given location in debugger ' )
group_sim . add_option ( " -M " , " --mavlink-gimbal " , action = ' store_true ' , default = False , help = ' enable MAVLink gimbal ' )
group_sim . add_option ( " -L " , " --location " , type = ' string ' , default = ' CMAC ' , help = ' select start location from Tools/autotest/locations.txt ' )
group_sim . add_option ( " -l " , " --custom-location " , type = ' string ' , default = None , help = ' set custom start location ' )
group_sim . add_option ( " -S " , " --speedup " , default = 1 , type = ' int ' , help = ' set simulation speedup (1 for wall clock time) ' )
group_sim . add_option ( " -t " , " --tracker-location " , default = ' CMAC_PILOTSBOX ' , type = ' string ' , help = ' set antenna tracker start location ' )
group_sim . add_option ( " -w " , " --wipe-eeprom " , action = ' store_true ' , default = False , help = ' wipe EEPROM and reload parameters ' )
group_sim . add_option ( " -m " , " --mavproxy-args " , default = None , type = ' string ' , help = ' additional arguments to pass to mavproxy.py ' )
2016-05-12 08:09:45 -03:00
group_sim . add_option ( " " , " --strace " , action = ' store_true ' , default = False , help = " strace the ArduPilot binary " )
2016-06-22 00:42:45 -03:00
group_sim . add_option ( " " , " --model " , type = ' string ' , default = None , help = ' Override simulation model to use ' )
2016-05-07 20:34:42 -03:00
parser . add_option_group ( group_sim )
2016-04-27 22:34:15 -03:00
2016-04-28 23:16:53 -03:00
# special-cased parameters for mavproxy, because some people's fingers
# have long memories, and they don't want to use -C :-)
group = optparse . OptionGroup ( parser , " Compatibility MAVProxy options (consider using --mavproxy-args instead) " )
group . add_option ( " " , " --out " , default = [ ] , type = ' string ' , action = " append " , help = ' create an additional mavlink output ' )
group . add_option ( " " , " --map " , default = False , action = ' store_true ' , help = ' load map module on startup ' )
group . add_option ( " " , " --console " , default = False , action = ' store_true ' , help = ' load console module on startup ' )
parser . add_option_group ( group )
2016-04-27 22:34:15 -03:00
opts , args = parser . parse_args ( )
2016-05-11 23:34:49 -03:00
if opts . sim_vehicle_sh_compatible and opts . jobs is None :
opts . jobs = 1
2016-04-27 22:34:15 -03:00
# validate parameters
if opts . hil :
if opts . valgrind :
print ( " May not use valgrind with hil " )
sys . exit ( 1 )
if opts . gdb or opts . gdb_stopped :
print ( " May not use gdb with hil " )
sys . exit ( 1 )
2016-05-12 08:09:45 -03:00
if opts . strace :
print ( " May not use strace with hil " )
sys . exit ( 1 )
2016-04-27 22:34:15 -03:00
if opts . valgrind and ( opts . gdb or opts . gdb_stopped ) :
print ( " May not use valgrind with gdb " )
sys . exit ( 1 )
2016-05-12 08:09:45 -03:00
if opts . strace and ( opts . gdb or opts . gdb_stopped ) :
print ( " May not use strace with gdb " )
sys . exit ( 1 )
if opts . strace and opts . valgrind :
print ( " valgrind and strace almost certainly not a good idea " )
2016-04-27 22:34:15 -03:00
# magically determine vehicle type (if required):
if opts . vehicle is None :
cwd = os . getcwd ( )
opts . vehicle = os . path . basename ( cwd )
# determine a frame type if not specified:
default_frame_for_vehicle = {
" APMrover2 " : " rover " ,
" ArduPlane " : " jsbsim " ,
" ArduCopter " : " quad " ,
" AntennaTracker " : " tracker "
}
2016-06-23 21:48:24 -03:00
if not default_frame_for_vehicle . has_key ( opts . vehicle ) :
# try in parent directories, useful for having config in subdirectories
cwd = os . getcwd ( )
while cwd :
bname = os . path . basename ( cwd )
if not bname :
break
if bname in default_frame_for_vehicle :
opts . vehicle = bname
break
cwd = os . path . dirname ( cwd )
2016-04-28 23:16:53 -03:00
# try to validate vehicle
if not default_frame_for_vehicle . has_key ( opts . vehicle ) :
progress ( " ** Is ( %s ) really your vehicle type? Try -v VEHICLETYPE if not, or be in the e.g. ArduCopter subdirectory " % ( opts . vehicle , ) )
2016-04-27 22:34:15 -03:00
# determine frame options (e.g. build type might be "sitl")
if opts . frame is None :
opts . frame = default_frame_for_vehicle [ opts . vehicle ]
# setup ports for this instance
mavlink_port = " tcp:127.0.0.1: " + str ( 5760 + 10 * opts . instance )
simout_port = " 127.0.0.1: " + str ( 5501 + 10 * opts . instance )
2016-04-28 23:16:53 -03:00
'''
make_target : option passed to make to create binaries . Usually sitl , and " -debug " may be appended if - D is passed to sim_vehicle . py
2016-04-27 22:34:15 -03:00
default_params_filename : filename of default parameters file . Taken to be relative to autotest dir .
extra_mavlink_cmds : extra parameters that will be passed to mavproxy
'''
_options_for_frame = {
2016-05-13 16:47:12 -03:00
" calibration " : {
" extra_mavlink_cmds " : " module load sitl_calibration; " ,
} ,
2016-05-23 10:38:06 -03:00
# COPTER
2016-04-27 22:34:15 -03:00
" + " : {
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arducopter-quad " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " copter_params.parm "
} ,
" quad " : {
" model " : " + " ,
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arducopter-quad " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " copter_params.parm "
} ,
" X " : {
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arducopter-quad " ,
2016-04-27 22:34:15 -03:00
# this param set FRAME doesn't actually work because mavproxy
# won't set a parameter unless it knows of it, and the param fetch happens asynchronously
2016-04-28 23:16:53 -03:00
" default_params_filename " : " copter_params.parm " ,
2016-05-23 10:38:06 -03:00
" extra_mavlink_cmds " : " param fetch frame; param set FRAME 1; "
2016-04-27 22:34:15 -03:00
} ,
2016-05-23 10:30:59 -03:00
" hexa " : {
" make_target " : " sitl-hexa " ,
" waf_target " : " bin/arducopter-hexa " ,
" default_params_filename " : " copter_params.parm " ,
} ,
2016-04-27 22:34:15 -03:00
" octa " : {
2016-04-28 23:16:53 -03:00
" make_target " : " sitl-octa " ,
" waf_target " : " bin/arducopter-octa " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " copter_params.parm " ,
} ,
" tri " : {
2016-04-28 23:16:53 -03:00
" make_target " : " sitl-tri " ,
" waf_target " : " bin/arducopter-tri " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " tri_params.parm " ,
} ,
" y6 " : {
2016-04-28 23:16:53 -03:00
" make_target " : " sitl-y6 " ,
" waf_target " : " bin/arducopter-y6 " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " y6_params.parm " ,
} ,
2016-05-23 10:38:06 -03:00
# COPTER TYPES
" IrisRos " : {
" waf_target " : " bin/arducopter-quad " ,
" default_params_filename " : " copter_params.parm " ,
} ,
2016-04-27 22:34:15 -03:00
" firefly " : {
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arducopter-firefly " ,
2016-05-23 10:38:06 -03:00
" default_params_filename " : " firefly.parm " ,
2016-04-27 22:34:15 -03:00
} ,
2016-05-23 10:38:06 -03:00
# HELICOPTER
2016-04-27 22:34:15 -03:00
" heli " : {
2016-05-23 10:38:06 -03:00
" make_target " : " sitl-heli " ,
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arducopter-heli " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " Helicopter.parm " ,
} ,
2016-05-23 10:38:06 -03:00
" heli-dual " : {
" make_target " : " sitl-heli-dual " ,
" waf_target " : " bin/arducopter-coax " , # is this correct? -pb201604301447
2016-04-27 22:34:15 -03:00
} ,
2016-05-23 10:38:06 -03:00
" heli-compound " : {
" make_target " : " sitl-heli-compound " ,
" waf_target " : " bin/arducopter-coax " , # is this correct? -pb201604301447
2016-04-27 22:34:15 -03:00
} ,
2016-05-26 03:29:37 -03:00
" singlecopter " : {
" make_target " : " sitl-single " ,
" waf_target " : " bin/arducopter-single " ,
" default_params_filename " : " SingleCopter.parm " ,
} ,
2016-05-26 04:09:31 -03:00
" coaxcopter " : {
" make_target " : " sitl-coax " ,
" waf_target " : " bin/arducopter-coax " ,
" default_params_filename " : " CoaxCopter.parm " ,
} ,
2016-05-23 10:38:06 -03:00
# PLANE
2016-05-01 19:52:43 -03:00
" quadplane-tilttri " : {
2016-06-30 01:15:59 -03:00
" make_target " : " sitl-tri " ,
" waf_target " : " bin/arduplane-tri " ,
2016-05-01 19:52:43 -03:00
" default_params_filename " : " quadplane-tilttri.parm " ,
} ,
2016-06-30 01:15:59 -03:00
" quadplane-tri " : {
" make_target " : " sitl-tri " ,
" waf_target " : " bin/arduplane-tri " ,
" default_params_filename " : " quadplane-tri.parm " ,
} ,
2016-04-27 22:34:15 -03:00
" quadplane " : {
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arduplane " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " quadplane.parm " ,
} ,
" plane-elevon " : {
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arduplane " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " plane-elevons.parm " ,
} ,
" plane-vtail " : {
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arduplane " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " plane-vtail.parm " ,
} ,
" plane " : {
2016-04-28 23:16:53 -03:00
" waf_target " : " bin/arduplane " ,
2016-04-27 22:34:15 -03:00
" default_params_filename " : " plane.parm " ,
} ,
2016-05-23 10:38:06 -03:00
# ROVER
2016-05-12 10:30:01 -03:00
" rover " : {
" waf_target " : " bin/ardurover " ,
" default_params_filename " : " Rover.parm " ,
} ,
2016-05-23 21:21:04 -03:00
" rover-skid " : {
" waf_target " : " bin/ardurover " ,
" default_params_filename " : " Rover-skid.parm " ,
2016-05-24 08:02:36 -03:00
} ,
2016-05-23 10:38:06 -03:00
# SIM
" Gazebo " : {
" waf_target " : " bin/arducopter-quad " ,
" default_params_filename " : " copter_params.parm " ,
} ,
" last_letter " : {
" waf_target " : " bin/arduplane " ,
} ,
" CRRCSim " : {
" waf_target " : " bin/arduplane " ,
} ,
" jsbsim " : {
" waf_target " : " bin/arduplane " ,
" default_params_filename " : " ArduPlane.parm " ,
2016-05-23 21:21:04 -03:00
} ,
2016-04-27 22:34:15 -03:00
}
2016-05-07 20:34:42 -03:00
_default_waf_target = {
" ArduPlane " : " bin/arduplane " ,
" ArduCopter " : " bin/arducopter-quad " ,
2016-05-11 04:43:06 -03:00
" APMrover2 " : " bin/ardurover " ,
2016-05-07 20:34:42 -03:00
" AntennaTracker " : " bin/antennatracker " ,
}
def default_waf_target ( vehicle ) :
''' returns a waf target based on vehicle type, which is often determined by which directory the user is in '''
return _default_waf_target [ vehicle ]
def options_for_frame ( frame , vehicle , opts ) :
2016-04-27 22:34:15 -03:00
''' return informatiom about how to sitl for frame e.g. build-type==sitl '''
2016-05-07 11:31:23 -03:00
ret = None
2016-04-27 22:34:15 -03:00
if frame in _options_for_frame :
ret = _options_for_frame [ frame ]
else :
for p in [ " octa " , " tri " , " y6 " , " firefly " , " heli " , " last_letter " , " jsbsim " , " quadplane " , " plane-elevon " , " plane-vtail " , " plane " ] :
if frame . startswith ( p ) :
ret = _options_for_frame [ p ]
break
if ret is None :
if frame . endswith ( " -heli " ) :
ret = _options_for_frame [ " heli " ]
if ret is None :
ret = { }
if not ret . has_key ( " model " ) :
ret [ " model " ] = frame
2016-04-28 23:16:53 -03:00
2016-06-22 01:10:27 -03:00
if not ret . has_key ( " sitl-port " ) :
ret [ " sitl-port " ] = True
2016-06-22 00:42:45 -03:00
if opts . model is not None :
ret [ " model " ] = opts . model
2016-06-30 07:26:14 -03:00
if ( ret [ " model " ] . find ( " xplane " ) != - 1 or
ret [ " model " ] . find ( " flightaxis " ) != - 1 ) :
ret [ " sitl-port " ] = False
2016-06-22 00:42:45 -03:00
2016-04-28 23:16:53 -03:00
if not ret . has_key ( " make_target " ) :
ret [ " make_target " ] = " sitl "
2016-05-07 20:34:42 -03:00
if not ret . has_key ( " waf_target " ) :
ret [ " waf_target " ] = default_waf_target ( vehicle )
2016-04-27 22:34:15 -03:00
if opts . build_target is not None :
2016-04-28 23:16:53 -03:00
ret [ " make_target " ] = opts . build_target
ret [ " waf_target " ] = opts . build_target
2016-04-27 22:34:15 -03:00
return ret
2016-05-25 06:40:14 -03:00
def do_build_waf ( opts , frame_options ) :
2016-05-12 00:32:36 -03:00
''' build sitl using waf '''
2016-04-28 23:16:53 -03:00
progress ( " WAF build " )
old_dir = os . getcwd ( )
2016-05-12 00:32:36 -03:00
root_dir = find_root_dir ( )
2016-04-28 23:16:53 -03:00
os . chdir ( root_dir )
2016-05-12 00:32:36 -03:00
waf_light = os . path . join ( root_dir , " modules/waf/waf-light " )
2016-04-28 23:16:53 -03:00
cmd_configure = [ waf_light , " configure " , " --board " , " sitl " ]
2016-05-06 00:11:53 -03:00
if opts . debug :
cmd_configure . append ( " --debug " )
2016-04-28 23:16:53 -03:00
run_cmd_blocking ( " Configure waf " , cmd_configure )
if opts . clean :
run_cmd_blocking ( " Building clean " , [ waf_light , " clean " ] )
2016-05-11 13:15:30 -03:00
cmd_build = [ waf_light , " build " , " --target " , frame_options [ " waf_target " ] ]
if opts . jobs is not None :
cmd_build + = [ ' -j ' , str ( opts . jobs ) ]
2016-05-11 23:44:56 -03:00
_ , sts = run_cmd_blocking ( " Building " , cmd_build )
2016-04-28 23:16:53 -03:00
2016-05-07 20:34:42 -03:00
if sts != 0 : # build failed
if opts . rebuild_on_failure :
progress ( " Build failed; cleaning and rebuilding " )
run_cmd_blocking ( " Building clean " , [ waf_light , " clean " ] )
2016-04-28 23:16:53 -03:00
2016-05-11 23:44:56 -03:00
_ , sts = run_cmd_blocking ( " Building " , cmd_build )
2016-05-07 20:34:42 -03:00
if sts != 0 :
progress ( " Build failed " )
sys . exit ( 1 )
else :
2016-04-28 23:16:53 -03:00
progress ( " Build failed " )
sys . exit ( 1 )
os . chdir ( old_dir )
def do_build ( vehicledir , opts , frame_options ) :
''' build build target (e.g. sitl) in directory vehicledir '''
if opts . build_system == ' waf ' :
2016-05-25 06:40:14 -03:00
return do_build_waf ( opts , frame_options )
2016-04-28 23:16:53 -03:00
2016-04-27 22:34:15 -03:00
old_dir = os . getcwd ( )
os . chdir ( vehicledir )
if opts . clean :
2016-04-28 23:16:53 -03:00
run_cmd_blocking ( " Building clean " , [ " make " , " clean " ] )
build_target = frame_options [ " make_target " ]
if opts . debug :
build_target + = " -debug "
2016-05-11 13:15:30 -03:00
build_cmd = [ " make " , build_target ]
if opts . jobs is not None :
build_cmd + = [ ' -j ' , str ( opts . jobs ) ]
2016-05-11 23:44:56 -03:00
_ , sts = run_cmd_blocking ( " Building %s " % ( build_target ) , build_cmd )
2016-04-27 22:34:15 -03:00
if sts != 0 :
progress ( " Build failed; cleaning and rebuilding " )
2016-05-11 23:44:56 -03:00
run_cmd_blocking ( " Cleaning " , [ " make " , " clean " ] )
_ , sts = run_cmd_blocking ( " Building %s " % ( build_target ) , build_cmd )
2016-04-27 22:34:15 -03:00
if sts != 0 :
progress ( " Build failed " )
sys . exit ( 1 )
os . chdir ( old_dir )
def find_location_by_name ( autotest , locname ) :
''' search locations.txt for locname, return GPS coords '''
locations_filepath = os . path . join ( autotest , " locations.txt " )
for line in open ( locations_filepath , ' r ' ) :
line = line . rstrip ( " \n " )
( name , loc ) = line . split ( " = " )
if name == locname :
return loc
print ( " Failed to find location ( %s ) " % ( opts . location ) )
sys . exit ( 1 )
2016-04-28 23:16:53 -03:00
def progress_cmd ( what , cmd ) :
''' print cmd in a way a user could cut-and-paste to get the same effect '''
progress ( what )
shell_text = " %s " % ( " " . join ( [ ' " %s " ' % x for x in cmd ] ) )
progress ( shell_text )
2016-06-23 00:31:38 -03:00
def run_cmd_blocking ( what , cmd , quiet = False , * * kw ) :
if not quiet :
progress_cmd ( what , cmd )
2016-05-13 17:42:39 -03:00
p = subprocess . Popen ( cmd , * * kw )
2016-05-11 23:44:56 -03:00
return os . waitpid ( p . pid , 0 )
2016-04-28 23:16:53 -03:00
2016-04-27 22:34:15 -03:00
def run_in_terminal_window ( autotest , name , cmd ) :
''' execute the run_in_terminal_window.sh command for cmd '''
runme = [ os . path . join ( autotest , " run_in_terminal_window.sh " ) , name ]
runme . extend ( cmd )
2016-04-28 23:16:53 -03:00
progress_cmd ( " Run " + name , runme )
2016-04-27 22:34:15 -03:00
p = subprocess . Popen ( runme ) # bg this explicitly?!
tracker_uarta = None # blemish
def start_antenna_tracker ( autotest , opts ) :
''' compile and run the AntennaTracker, add tracker to mavproxy '''
global tracker_uarta
progress ( " Preparing antenna tracker " )
tracker_home = find_location_by_name ( find_autotest_dir ( ) , opts . tracker_location )
vehicledir = os . path . join ( autotest , " ../../ " + " AntennaTracker " )
do_build ( vehicledir , opts , " sitl-debug " )
tracker_instance = 1
os . chdir ( vehicledir )
tracker_uarta = " tcp:127.0.0.1: " + str ( 5760 + 10 * tracker_instance )
exe = os . path . join ( vehicledir , " AntennaTracker.elf " )
run_in_terminal_window ( autotest , " AntennaTracker " , [ " nice " , exe , " -I " + str ( tracker_instance ) , " --model=tracker " , " --home= " + tracker_home ] )
2016-04-28 23:16:53 -03:00
def start_vehicle ( vehicle_binary , autotest , opts , stuff , loc ) :
''' run the ArduPilot binary '''
2016-04-27 22:34:15 -03:00
cmd_name = opts . vehicle
cmd = [ ]
if opts . valgrind :
cmd_name + = " (valgrind) "
cmd . append ( " valgrind " )
if opts . gdb :
cmd_name + = " (gdb) "
cmd . append ( " gdb " )
gdb_commands_file = tempfile . NamedTemporaryFile ( delete = False )
atexit . register ( os . unlink , gdb_commands_file . name )
2016-04-28 23:16:53 -03:00
for breakpoint in opts . breakpoint :
gdb_commands_file . write ( " b %s \n " % ( breakpoint , ) )
2016-04-27 22:34:15 -03:00
gdb_commands_file . write ( " r \n " )
gdb_commands_file . close ( )
cmd . extend ( [ " -x " , gdb_commands_file . name ] )
cmd . append ( " --args " )
2016-05-12 08:09:45 -03:00
if opts . strace :
cmd_name + = " (strace) "
cmd . append ( " strace " )
strace_options = [ ' -o ' , vehicle_binary + ' .strace ' , ' -s ' , ' 8000 ' , ' -ttt ' ]
cmd . extend ( strace_options )
2016-04-27 22:34:15 -03:00
2016-04-28 23:16:53 -03:00
cmd . append ( vehicle_binary )
2016-04-27 22:34:15 -03:00
cmd . append ( " -S " )
cmd . append ( " -I " + str ( opts . instance ) )
cmd . extend ( [ " --home " , loc ] )
if opts . wipe_eeprom :
cmd . append ( " -w " )
cmd . extend ( [ " --model " , stuff [ " model " ] ] )
cmd . extend ( [ " --speedup " , str ( opts . speedup ) ] )
if opts . sitl_instance_args :
cmd . extend ( opts . sitl_instance_args . split ( " " ) ) # this could be a lot better..
if opts . mavlink_gimbal :
cmd . append ( " --gimbal " )
if stuff . has_key ( " default_params_filename " ) :
path = os . path . join ( autotest , stuff [ " default_params_filename " ] )
progress ( " Using defaults from ( %s ) " % ( path , ) )
cmd . extend ( [ " --defaults " , path ] )
run_in_terminal_window ( autotest , cmd_name , cmd )
def start_mavproxy ( opts , stuff ) :
''' run mavproxy '''
# FIXME: would be nice to e.g. "mavproxy.mavproxy(....).run" rather than shelling out
extra_cmd = " "
cmd = [ ]
2016-04-28 23:16:53 -03:00
if under_cygwin ( ) :
cmd . append ( " /usr/bin/cygstart " )
2016-04-27 22:34:15 -03:00
cmd . append ( " -w " )
cmd . append ( " /cygdrive/c/Program Files (x86)/MAVProxy/mavproxy.exe " )
else :
cmd . append ( " mavproxy.py " )
if opts . hil :
cmd . extend ( [ " --load-module " , " HIL " ] )
else :
2016-06-22 01:10:27 -03:00
cmd . extend ( [ " --master " , mavlink_port ] )
if stuff [ " sitl-port " ] :
cmd . extend ( [ " --sitl " , simout_port ] )
2016-04-27 22:34:15 -03:00
# If running inside of a vagrant guest, then we probably want to forward our mavlink out to the containing host OS
if getpass . getuser ( ) == " vagrant " :
cmd . extend ( [ " --out " , " 10.0.2.2:14550 " ] )
for port in [ 14550 , 14551 ] :
cmd . extend ( [ " --out " , " 127.0.0.1: " + str ( port ) ] )
if opts . tracker :
cmd . extend ( [ " --load-module " , " tracker " ] )
global tracker_uarta
# tracker_uarta is set when we start the tracker...
extra_cmd + = " module load map; tracker set port %s ; tracker start; tracker arm; " % ( tracker_uarta , )
if opts . mavlink_gimbal :
cmd . extend ( [ " --load-module " , " gimbal " ] )
if stuff . has_key ( " extra_mavlink_cmds " ) :
extra_cmd + = " " + stuff [ " extra_mavlink_cmds " ]
if opts . mavproxy_args :
cmd . extend ( opts . mavproxy_args . split ( " " ) ) # this could be a lot better..
2016-05-12 14:15:46 -03:00
# compatibility pass-through parameters (for those that don't want
2016-04-28 23:16:53 -03:00
# to use -C :-)
for out in opts . out :
cmd . extend ( [ ' --out ' , out ] )
if opts . map :
cmd . append ( ' --map ' )
if opts . console :
cmd . append ( ' --console ' )
2016-04-27 22:34:15 -03:00
if len ( extra_cmd ) :
cmd . extend ( [ ' --cmd ' , extra_cmd ] )
2016-05-13 17:55:06 -03:00
local_mp_modules_dir = os . path . abspath (
os . path . join ( __file__ , ' .. ' , ' .. ' , ' mavproxy_modules ' ) )
env = dict ( os . environ )
env [ ' PYTHONPATH ' ] = local_mp_modules_dir + os . pathsep + env . get ( ' PYTHONPATH ' , ' ' )
run_cmd_blocking ( " Run MavProxy " , cmd , env = env )
2016-04-27 22:34:15 -03:00
progress ( " MAVProxy exitted " )
2016-05-07 20:34:42 -03:00
frame_options = options_for_frame ( opts . frame , opts . vehicle , opts )
2016-04-27 22:34:15 -03:00
if frame_options [ " model " ] == " jsbsim " :
check_jsbsim_version ( )
2016-05-12 00:32:36 -03:00
vehicledir = os . path . realpath ( os . path . join ( find_root_dir ( ) , opts . vehicle ) )
2016-04-27 22:34:15 -03:00
if not os . path . exists ( vehicledir ) :
print ( " vehicle directory ( %s ) does not exist " % ( vehicledir , ) )
sys . exit ( 1 )
if not opts . hil :
if opts . instance == 0 :
kill_tasks ( )
if opts . tracker :
start_antenna_tracker ( find_autotest_dir ( ) , opts )
if opts . custom_location :
loc = opts . custom_location
progress ( " Starting up at %s " % ( loc , ) )
else :
loc = find_location_by_name ( find_autotest_dir ( ) , opts . location )
progress ( " Starting up at %s ( %s ) " % ( loc , opts . location ) )
if opts . hil :
# (unlikely)
run_in_terminal_window ( find_autotest_dir ( ) , " JSBSim " , [ os . path . join ( find_autotest_dir ( ) , " jsb_sim/runsim.py " ) , " --home " , loc , " --speedup= " + str ( opts . speedup ) ] )
else :
2016-04-28 23:16:53 -03:00
if not opts . no_rebuild : # i.e. we should rebuild
do_build ( vehicledir , opts , frame_options )
if opts . build_system == " waf " :
2016-05-08 23:11:32 -03:00
if opts . debug :
2016-05-12 00:32:36 -03:00
binary_basedir = " build/sitl-debug "
2016-05-08 23:11:32 -03:00
else :
2016-05-12 00:32:36 -03:00
binary_basedir = " build/sitl "
vehicle_binary = os . path . join ( find_root_dir ( ) , binary_basedir , frame_options [ " waf_target " ] )
2016-04-28 23:16:53 -03:00
else :
vehicle_binary = os . path . join ( vehicledir , opts . vehicle + " .elf " )
if not os . path . exists ( vehicle_binary ) :
print ( " Vehicle binary ( %s ) does not exist " % ( vehicle_binary , ) )
sys . exit ( 1 )
start_vehicle ( vehicle_binary , find_autotest_dir ( ) , opts , frame_options , loc )
2016-04-27 22:34:15 -03:00
if opts . delay_start :
progress ( " Sleeping for %f seconds " % ( opts . delay_start , ) )
time . sleep ( float ( opts . delay_start ) )
start_mavproxy ( opts , frame_options )
sys . exit ( 0 )