mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-06-01 02:55:07 +08:00
Merge remote-tracking branch 'upstream/master' into ros
This commit is contained in:
+1
-1
Submodule NuttX updated: 255dc96065...dbcccb2455
@@ -0,0 +1,31 @@
|
|||||||
|
#!nsh
|
||||||
|
#
|
||||||
|
# HobbyKing SK450 DeadCat modification
|
||||||
|
#
|
||||||
|
# Anton Matosov <anton.matosov@gmail.com>
|
||||||
|
#
|
||||||
|
|
||||||
|
sh /etc/init.d/rc.mc_defaults
|
||||||
|
|
||||||
|
if [ $AUTOCNF == yes ]
|
||||||
|
then
|
||||||
|
param set MC_ROLL_P 6.0
|
||||||
|
param set MC_ROLLRATE_P 0.04
|
||||||
|
param set MC_ROLLRATE_I 0.1
|
||||||
|
param set MC_ROLLRATE_D 0.0015
|
||||||
|
|
||||||
|
param set MC_PITCH_P 6.0
|
||||||
|
param set MC_PITCHRATE_P 0.08
|
||||||
|
param set MC_PITCHRATE_I 0.2
|
||||||
|
param set MC_PITCHRATE_D 0.0015
|
||||||
|
|
||||||
|
param set MC_YAW_P 2.8
|
||||||
|
param set MC_YAWRATE_P 0.1
|
||||||
|
param set MC_YAWRATE_I 0.07
|
||||||
|
param set MC_YAWRATE_D 0.0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set MIXER sk450_deadcat
|
||||||
|
|
||||||
|
set PWM_OUT 1234
|
||||||
|
set PWM_MIN 1050
|
||||||
@@ -226,6 +226,11 @@ then
|
|||||||
sh /etc/init.d/10018_tbs_endurance
|
sh /etc/init.d/10018_tbs_endurance
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if param compare SYS_AUTOSTART 10019
|
||||||
|
then
|
||||||
|
sh /etc/init.d/10019_sk450_deadcat
|
||||||
|
fi
|
||||||
|
|
||||||
#
|
#
|
||||||
# Hexa Coaxial
|
# Hexa Coaxial
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ then
|
|||||||
else
|
else
|
||||||
sh /etc/init.d/rc.autostart
|
sh /etc/init.d/rc.autostart
|
||||||
fi
|
fi
|
||||||
|
unset MODE
|
||||||
|
|
||||||
#
|
#
|
||||||
# Override parameters from user configuration file
|
# Override parameters from user configuration file
|
||||||
@@ -185,6 +186,7 @@ then
|
|||||||
param set SYS_AUTOCONFIG 0
|
param set SYS_AUTOCONFIG 0
|
||||||
param save
|
param save
|
||||||
fi
|
fi
|
||||||
|
unset AUTOCNF
|
||||||
|
|
||||||
set IO_PRESENT no
|
set IO_PRESENT no
|
||||||
|
|
||||||
@@ -524,7 +526,7 @@ then
|
|||||||
then
|
then
|
||||||
set MAV_TYPE 2
|
set MAV_TYPE 2
|
||||||
fi
|
fi
|
||||||
if [ $MIXER == quad_w ]
|
if [ $MIXER == quad_w -o $MIXER == sk450_deadcat ]
|
||||||
then
|
then
|
||||||
set MAV_TYPE 2
|
set MAV_TYPE 2
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Multirotor mixer for PX4FMU
|
||||||
|
===========================
|
||||||
|
|
||||||
|
This file defines a single mixer for a quadrotor in SK450 DeadCat configuration. All controls are mixed 100%.
|
||||||
|
|
||||||
|
R: 4dc 10000 10000 10000 0
|
||||||
|
|
||||||
|
Gimbal / payload mixer for last four channels
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
M: 1
|
||||||
|
O: 10000 10000 0 -10000 10000
|
||||||
|
S: 0 4 10000 10000 0 -10000 10000
|
||||||
|
|
||||||
|
M: 1
|
||||||
|
O: 10000 10000 0 -10000 10000
|
||||||
|
S: 0 5 10000 10000 0 -10000 10000
|
||||||
|
|
||||||
|
M: 1
|
||||||
|
O: 10000 10000 0 -10000 10000
|
||||||
|
S: 0 6 10000 10000 0 -10000 10000
|
||||||
|
|
||||||
|
M: 1
|
||||||
|
O: 10000 10000 0 -10000 10000
|
||||||
|
S: 0 7 10000 10000 0 -10000 10000
|
||||||
+53
-20
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
# Copyright (C) 2012, 2013 PX4 Development Team. All rights reserved.
|
# Copyright (C) 2012-2015 PX4 Development Team. All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
# modification, are permitted provided that the following conditions
|
# modification, are permitted provided that the following conditions
|
||||||
@@ -227,16 +227,21 @@ class uploader(object):
|
|||||||
+ uploader.EOC)
|
+ uploader.EOC)
|
||||||
self.__getSync()
|
self.__getSync()
|
||||||
|
|
||||||
# def __trySync(self):
|
def __trySync(self):
|
||||||
# c = self.__recv()
|
try:
|
||||||
# if (c != self.INSYNC):
|
self.port.flush()
|
||||||
# #print("unexpected 0x%x instead of INSYNC" % ord(c))
|
if (self.__recv() != self.INSYNC):
|
||||||
# return False;
|
#print("unexpected 0x%x instead of INSYNC" % ord(c))
|
||||||
# c = self.__recv()
|
return False;
|
||||||
# if (c != self.OK):
|
|
||||||
# #print("unexpected 0x%x instead of OK" % ord(c))
|
if (self.__recv() != self.OK):
|
||||||
# return False
|
#print("unexpected 0x%x instead of OK" % ord(c))
|
||||||
# return True
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
except RuntimeError:
|
||||||
|
#timeout, no response yet
|
||||||
|
return False
|
||||||
|
|
||||||
# send the GET_DEVICE command and wait for an info parameter
|
# send the GET_DEVICE command and wait for an info parameter
|
||||||
def __getInfo(self, param):
|
def __getInfo(self, param):
|
||||||
@@ -261,19 +266,37 @@ class uploader(object):
|
|||||||
self.__getSync()
|
self.__getSync()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def __drawProgressBar(self, progress, maxVal):
|
||||||
|
if maxVal < progress:
|
||||||
|
progress = maxVal
|
||||||
|
|
||||||
|
percent = (float(progress) / float(maxVal)) * 100.0
|
||||||
|
|
||||||
|
sys.stdout.write("\rprogress:[%-20s] %.2f%%" % ('='*int(percent/5.0), percent))
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
# send the CHIP_ERASE command and wait for the bootloader to become ready
|
# send the CHIP_ERASE command and wait for the bootloader to become ready
|
||||||
def __erase(self):
|
def __erase(self):
|
||||||
self.__send(uploader.CHIP_ERASE
|
self.__send(uploader.CHIP_ERASE
|
||||||
+ uploader.EOC)
|
+ uploader.EOC)
|
||||||
|
|
||||||
# erase is very slow, give it 20s
|
# erase is very slow, give it 20s
|
||||||
deadline = time.time() + 20
|
deadline = time.time() + 20.0
|
||||||
while time.time() < deadline:
|
while time.time() < deadline:
|
||||||
try:
|
|
||||||
self.__getSync()
|
#Draw progress bar (erase usually takes about 9 seconds to complete)
|
||||||
return
|
estimatedTimeRemaining = deadline-time.time()
|
||||||
except RuntimeError:
|
if estimatedTimeRemaining > 0:
|
||||||
# we timed out, that's OK
|
self.__drawProgressBar(20.0-estimatedTimeRemaining, 9.0)
|
||||||
continue
|
else:
|
||||||
|
self.__drawProgressBar(10.0, 10.0)
|
||||||
|
sys.stdout.write(" (timeout: %d seconds) " % int(time.time()-deadline) )
|
||||||
|
|
||||||
|
if self.__trySync():
|
||||||
|
self.__drawProgressBar(10.0, 10.0)
|
||||||
|
sys.stdout.write("\nerase complete!\n")
|
||||||
|
return;
|
||||||
|
|
||||||
raise RuntimeError("timed out waiting for erase")
|
raise RuntimeError("timed out waiting for erase")
|
||||||
|
|
||||||
@@ -329,9 +352,18 @@ class uploader(object):
|
|||||||
def __program(self, fw):
|
def __program(self, fw):
|
||||||
code = fw.image
|
code = fw.image
|
||||||
groups = self.__split_len(code, uploader.PROG_MULTI_MAX)
|
groups = self.__split_len(code, uploader.PROG_MULTI_MAX)
|
||||||
|
|
||||||
|
uploadProgress = 0
|
||||||
for bytes in groups:
|
for bytes in groups:
|
||||||
self.__program_multi(bytes)
|
self.__program_multi(bytes)
|
||||||
|
|
||||||
|
#Print upload progress (throttled, so it does not delay upload progress)
|
||||||
|
uploadProgress += 1
|
||||||
|
if uploadProgress % 256 == 0:
|
||||||
|
self.__drawProgressBar(uploadProgress, len(groups))
|
||||||
|
self.__drawProgressBar(100, 100)
|
||||||
|
print("\nprogram complete!")
|
||||||
|
|
||||||
# verify code
|
# verify code
|
||||||
def __verify_v2(self, fw):
|
def __verify_v2(self, fw):
|
||||||
self.__send(uploader.CHIP_VERIFY
|
self.__send(uploader.CHIP_VERIFY
|
||||||
@@ -436,7 +468,6 @@ class uploader(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Detect python version
|
# Detect python version
|
||||||
if sys.version_info[0] < 3:
|
if sys.version_info[0] < 3:
|
||||||
runningPython3 = False
|
runningPython3 = False
|
||||||
@@ -511,8 +542,10 @@ while True:
|
|||||||
print("attempting reboot on %s..." % port)
|
print("attempting reboot on %s..." % port)
|
||||||
print("if the board does not respond, unplug and re-plug the USB connector.")
|
print("if the board does not respond, unplug and re-plug the USB connector.")
|
||||||
up.send_reboot()
|
up.send_reboot()
|
||||||
|
|
||||||
# wait for the reboot, without we might run into Serial I/O Error 5
|
# wait for the reboot, without we might run into Serial I/O Error 5
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# always close the port
|
# always close the port
|
||||||
up.close()
|
up.close()
|
||||||
continue
|
continue
|
||||||
@@ -524,7 +557,7 @@ while True:
|
|||||||
except RuntimeError as ex:
|
except RuntimeError as ex:
|
||||||
|
|
||||||
# print the error
|
# print the error
|
||||||
print("ERROR: %s" % ex.args)
|
print("\nERROR: %s" % ex.args)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# always close the port
|
# always close the port
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ MODULES += drivers/ll40ls
|
|||||||
# MODULES += drivers/trone
|
# MODULES += drivers/trone
|
||||||
MODULES += drivers/gps
|
MODULES += drivers/gps
|
||||||
MODULES += drivers/hil
|
MODULES += drivers/hil
|
||||||
MODULES += drivers/hott
|
# MODULES += drivers/hott
|
||||||
MODULES += drivers/hott/hott_telemetry
|
# MODULES += drivers/hott/hott_telemetry
|
||||||
MODULES += drivers/hott/hott_sensors
|
# MODULES += drivers/hott/hott_sensors
|
||||||
# MODULES += drivers/blinkm
|
# MODULES += drivers/blinkm
|
||||||
MODULES += drivers/airspeed
|
MODULES += drivers/airspeed
|
||||||
MODULES += drivers/ets_airspeed
|
MODULES += drivers/ets_airspeed
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ CONFIG_ARCH_BOARD=""
|
|||||||
#
|
#
|
||||||
CONFIG_NSH_MMCSDMINOR=0
|
CONFIG_NSH_MMCSDMINOR=0
|
||||||
CONFIG_NSH_MMCSDSLOTNO=0
|
CONFIG_NSH_MMCSDSLOTNO=0
|
||||||
|
CONFIG_MMCSD_HAVE_SDIOWAIT_WRCOMPLETE=y
|
||||||
#
|
#
|
||||||
# Board-Specific Options
|
# Board-Specific Options
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -441,7 +441,6 @@ private:
|
|||||||
SimpleMixer operator=(const SimpleMixer&);
|
SimpleMixer operator=(const SimpleMixer&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supported multirotor geometries.
|
* Supported multirotor geometries.
|
||||||
*
|
*
|
||||||
@@ -460,12 +459,14 @@ class __EXPORT MultirotorMixer : public Mixer
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
||||||
* Precalculated rotor mix.
|
* Precalculated rotor mix.
|
||||||
*/
|
*/
|
||||||
struct Rotor {
|
struct Rotor {
|
||||||
float roll_scale; /**< scales roll for this rotor */
|
float roll_scale; /**< scales roll for this rotor */
|
||||||
float pitch_scale; /**< scales pitch for this rotor */
|
float pitch_scale; /**< scales pitch for this rotor */
|
||||||
float yaw_scale; /**< scales yaw for this rotor */
|
float yaw_scale; /**< scales yaw for this rotor */
|
||||||
|
float out_scale; /**< scales total out for this rotor */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -75,7 +75,8 @@ float constrain(float val, float min, float max)
|
|||||||
{
|
{
|
||||||
return (val < min) ? min : ((val > max) ? max : val);
|
return (val < min) ? min : ((val > max) ? max : val);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
MultirotorMixer::MultirotorMixer(ControlCallback control_cb,
|
MultirotorMixer::MultirotorMixer(ControlCallback control_cb,
|
||||||
uintptr_t cb_handle,
|
uintptr_t cb_handle,
|
||||||
@@ -89,6 +90,7 @@ MultirotorMixer::MultirotorMixer(ControlCallback control_cb,
|
|||||||
_pitch_scale(pitch_scale),
|
_pitch_scale(pitch_scale),
|
||||||
_yaw_scale(yaw_scale),
|
_yaw_scale(yaw_scale),
|
||||||
_idle_speed(-1.0f + idle_speed * 2.0f), /* shift to output range here to avoid runtime calculation */
|
_idle_speed(-1.0f + idle_speed * 2.0f), /* shift to output range here to avoid runtime calculation */
|
||||||
|
_limits_pub(),
|
||||||
_rotor_count(_config_rotor_count[(MultirotorGeometryUnderlyingType)geometry]),
|
_rotor_count(_config_rotor_count[(MultirotorGeometryUnderlyingType)geometry]),
|
||||||
_rotors(_config_index[(MultirotorGeometryUnderlyingType)geometry])
|
_rotors(_config_index[(MultirotorGeometryUnderlyingType)geometry])
|
||||||
{
|
{
|
||||||
@@ -152,6 +154,9 @@ MultirotorMixer::from_text(Mixer::ControlCallback control_cb, uintptr_t cb_handl
|
|||||||
} else if (!strcmp(geomname, "4w")) {
|
} else if (!strcmp(geomname, "4w")) {
|
||||||
geometry = MultirotorGeometry::QUAD_WIDE;
|
geometry = MultirotorGeometry::QUAD_WIDE;
|
||||||
|
|
||||||
|
} else if (!strcmp(geomname, "4dc")) {
|
||||||
|
geometry = MultirotorGeometry::QUAD_DEADCAT;
|
||||||
|
|
||||||
} else if (!strcmp(geomname, "6+")) {
|
} else if (!strcmp(geomname, "6+")) {
|
||||||
geometry = MultirotorGeometry::HEX_PLUS;
|
geometry = MultirotorGeometry::HEX_PLUS;
|
||||||
|
|
||||||
@@ -212,6 +217,8 @@ MultirotorMixer::mix(float *outputs, unsigned space)
|
|||||||
pitch * _rotors[i].pitch_scale +
|
pitch * _rotors[i].pitch_scale +
|
||||||
thrust;
|
thrust;
|
||||||
|
|
||||||
|
out *= _rotors[i].out_scale;
|
||||||
|
|
||||||
/* limit yaw if it causes outputs clipping */
|
/* limit yaw if it causes outputs clipping */
|
||||||
if (out >= 0.0f && out < -yaw * _rotors[i].yaw_scale) {
|
if (out >= 0.0f && out < -yaw * _rotors[i].yaw_scale) {
|
||||||
yaw = -out / _rotors[i].yaw_scale;
|
yaw = -out / _rotors[i].yaw_scale;
|
||||||
|
|||||||
@@ -69,6 +69,13 @@ quad_plus = [
|
|||||||
[ 180, CW],
|
[ 180, CW],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
quad_deadcat = [
|
||||||
|
[ 63, CCW, 1.0],
|
||||||
|
[-135, CCW, 0.964],
|
||||||
|
[ -63, CW, 1.0],
|
||||||
|
[ 135, CW, 0.964],
|
||||||
|
]
|
||||||
|
|
||||||
quad_v = [
|
quad_v = [
|
||||||
[ 18.8, 0.4242],
|
[ 18.8, 0.4242],
|
||||||
[ -18.8, 1.0],
|
[ -18.8, 1.0],
|
||||||
@@ -148,13 +155,18 @@ twin_engine = [
|
|||||||
[-90, 0.0],
|
[-90, 0.0],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
tables = [quad_x, quad_plus, quad_v, quad_wide, quad_deadcat, hex_x, hex_plus, hex_cox, octa_x, octa_plus, octa_cox, twin_engine]
|
||||||
|
|
||||||
def variableName(variable):
|
def variableName(variable):
|
||||||
for variableName, value in list(globals().items()):
|
for variableName, value in list(globals().items()):
|
||||||
if value is variable:
|
if value is variable:
|
||||||
return variableName
|
return variableName
|
||||||
|
|
||||||
tables = [quad_x, quad_plus, quad_v, quad_wide, hex_x, hex_plus, hex_cox, octa_x, octa_plus, octa_cox, twin_engine]
|
def unpackScales(scalesList):
|
||||||
|
if len(scalesList) == 2:
|
||||||
|
scalesList += [1.0] #Add thrust scale
|
||||||
|
return scalesList
|
||||||
|
|
||||||
def printEnum():
|
def printEnum():
|
||||||
print("enum class MultirotorGeometry : MultirotorGeometryUnderlyingType {")
|
print("enum class MultirotorGeometry : MultirotorGeometryUnderlyingType {")
|
||||||
@@ -167,10 +179,11 @@ def printEnum():
|
|||||||
def printScaleTables():
|
def printScaleTables():
|
||||||
for table in tables:
|
for table in tables:
|
||||||
print("const MultirotorMixer::Rotor _config_{}[] = {{".format(variableName(table)))
|
print("const MultirotorMixer::Rotor _config_{}[] = {{".format(variableName(table)))
|
||||||
for (angle, yawScale) in table:
|
for row in table:
|
||||||
|
angle, yawScale, thrustScale = unpackScales(row)
|
||||||
rollScale = rcos(angle + 90)
|
rollScale = rcos(angle + 90)
|
||||||
pitchScale = rcos(angle)
|
pitchScale = rcos(angle)
|
||||||
print("\t{{ {:9f}, {:9f}, {:9f} }},".format(rollScale, pitchScale, yawScale))
|
print("\t{{ {:9f}, {:9f}, {:9f}, {:9f} }},".format(rollScale, pitchScale, yawScale, thrustScale))
|
||||||
print("};\n")
|
print("};\n")
|
||||||
|
|
||||||
def printScaleTablesIndex():
|
def printScaleTablesIndex():
|
||||||
|
|||||||
Reference in New Issue
Block a user