mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-24 03:53:33 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -0,0 +1,122 @@
|
|||||||
|
#!nsh
|
||||||
|
#
|
||||||
|
# Flight startup script for PX4FMU+PX4IO
|
||||||
|
#
|
||||||
|
|
||||||
|
# disable USB and autostart
|
||||||
|
set USB no
|
||||||
|
set MODE custom
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start the ORB (first app to start)
|
||||||
|
#
|
||||||
|
uorb start
|
||||||
|
|
||||||
|
#
|
||||||
|
# Load microSD params
|
||||||
|
#
|
||||||
|
echo "[init] loading microSD params"
|
||||||
|
param select /fs/microsd/params
|
||||||
|
if [ -f /fs/microsd/params ]
|
||||||
|
then
|
||||||
|
param load /fs/microsd/params
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Load default params for this platform
|
||||||
|
#
|
||||||
|
if param compare SYS_AUTOCONFIG 1
|
||||||
|
then
|
||||||
|
# Set all params here, then disable autoconfig
|
||||||
|
param set SYS_AUTOCONFIG 0
|
||||||
|
param save /fs/microsd/params
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Force some key parameters to sane values
|
||||||
|
# MAV_TYPE 1 = fixed wing, 2 = quadrotor, 13 = hexarotor
|
||||||
|
# see https://pixhawk.ethz.ch/mavlink/
|
||||||
|
#
|
||||||
|
param set MAV_TYPE 10
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check if PX4IO Firmware should be upgraded (from Andrew Tridgell)
|
||||||
|
#
|
||||||
|
if [ -f /fs/microsd/px4io.bin ]
|
||||||
|
then
|
||||||
|
echo "PX4IO Firmware found. Checking Upgrade.."
|
||||||
|
if cmp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
|
||||||
|
then
|
||||||
|
echo "No newer version, skipping upgrade."
|
||||||
|
else
|
||||||
|
echo "Loading /fs/microsd/px4io.bin"
|
||||||
|
if px4io update /fs/microsd/px4io.bin > /fs/microsd/px4io_update.log
|
||||||
|
then
|
||||||
|
cp /fs/microsd/px4io.bin /fs/microsd/px4io.bin.current
|
||||||
|
echo "Flashed /fs/microsd/px4io.bin OK" >> /fs/microsd/px4io_update.log
|
||||||
|
else
|
||||||
|
echo "Failed flashing /fs/microsd/px4io.bin" >> /fs/microsd/px4io_update.log
|
||||||
|
echo "Failed to upgrade PX4IO firmware - check if PX4IO is in bootloader mode"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start MAVLink (depends on orb)
|
||||||
|
#
|
||||||
|
mavlink start -d /dev/ttyS1 -b 57600
|
||||||
|
usleep 5000
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start the commander (depends on orb, mavlink)
|
||||||
|
#
|
||||||
|
commander start
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start PX4IO interface (depends on orb, commander)
|
||||||
|
#
|
||||||
|
px4io start
|
||||||
|
|
||||||
|
#
|
||||||
|
# Allow PX4IO to recover from midair restarts.
|
||||||
|
# this is very unlikely, but quite safe and robust.
|
||||||
|
px4io recovery
|
||||||
|
|
||||||
|
#
|
||||||
|
# Disable px4io topic limiting
|
||||||
|
#
|
||||||
|
px4io limit 200
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start the sensors (depends on orb, px4io)
|
||||||
|
#
|
||||||
|
sh /etc/init.d/rc.sensors
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start GPS interface (depends on orb)
|
||||||
|
#
|
||||||
|
gps start
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start the attitude estimator (depends on orb)
|
||||||
|
#
|
||||||
|
attitude_estimator_ekf start
|
||||||
|
|
||||||
|
#
|
||||||
|
# Load mixer and start controllers (depends on px4io)
|
||||||
|
#
|
||||||
|
md25 start 3 0x58
|
||||||
|
segway start
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start logging
|
||||||
|
#
|
||||||
|
sdlog2 start -r 50 -a -b 14
|
||||||
|
|
||||||
|
#
|
||||||
|
# Start system state
|
||||||
|
#
|
||||||
|
if blinkm start
|
||||||
|
then
|
||||||
|
blinkm systemstate
|
||||||
|
fi
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
====== PX4 LOG CONVERSION ======
|
||||||
|
|
||||||
|
On each log session (commonly started and stopped by arming and disarming the vehicle) a new file logxxx.bin is created. In many cases there will be only one logfile named log001.bin (only one flight).
|
||||||
|
|
||||||
|
There are two conversion scripts in this ZIP file:
|
||||||
|
|
||||||
|
logconv.m: This is a MATLAB script which will automatically convert and display the flight data with a GUI. If running this script, the second script can be ignored.
|
||||||
|
|
||||||
|
sdlog2_dump.py: This is a Python script (compatible with v2 and v3) which converts the self-describing binary log format to a CSV file. To export a CSV file from within a shell (Windows CMD or BASH on Linux / Mac OS), run:
|
||||||
|
|
||||||
|
python sdlog2_dump.py log001.bin -f "export.csv" -t "TIME" -d "," -n ""
|
||||||
|
|
||||||
|
Python can be downloaded from http://python.org, but is available as default on Mac OS and Linux.
|
||||||
+26
-24
@@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""Dump binary log generated by sdlog2 or APM as CSV
|
from __future__ import print_function
|
||||||
|
|
||||||
|
"""Dump binary log generated by PX4's sdlog2 or APM as CSV
|
||||||
|
|
||||||
Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[.field1,field2,...]]
|
Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[.field1,field2,...]]
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ class SDLog2Parser:
|
|||||||
self.__msg_descrs = {} # message descriptions by message type map
|
self.__msg_descrs = {} # message descriptions by message type map
|
||||||
self.__msg_labels = {} # message labels by message name map
|
self.__msg_labels = {} # message labels by message name map
|
||||||
self.__msg_names = [] # message names in the same order as FORMAT messages
|
self.__msg_names = [] # message names in the same order as FORMAT messages
|
||||||
self.__buffer = "" # buffer for input binary data
|
self.__buffer = "" # buffer for input binary data
|
||||||
self.__ptr = 0 # read pointer in buffer
|
self.__ptr = 0 # read pointer in buffer
|
||||||
self.__csv_columns = [] # CSV file columns in correct order in format "MSG.label"
|
self.__csv_columns = [] # CSV file columns in correct order in format "MSG.label"
|
||||||
self.__csv_data = {} # current values for all columns
|
self.__csv_data = {} # current values for all columns
|
||||||
@@ -105,7 +107,7 @@ class SDLog2Parser:
|
|||||||
for msg_name, show_fields in self.__msg_filter:
|
for msg_name, show_fields in self.__msg_filter:
|
||||||
self.__msg_filter_map[msg_name] = show_fields
|
self.__msg_filter_map[msg_name] = show_fields
|
||||||
first_data_msg = True
|
first_data_msg = True
|
||||||
f = open(fn, "r")
|
f = open(fn, "rb")
|
||||||
bytes_read = 0
|
bytes_read = 0
|
||||||
while True:
|
while True:
|
||||||
chunk = f.read(self.BLOCK_SIZE)
|
chunk = f.read(self.BLOCK_SIZE)
|
||||||
@@ -168,9 +170,9 @@ class SDLog2Parser:
|
|||||||
self.__csv_columns.append(full_label)
|
self.__csv_columns.append(full_label)
|
||||||
self.__csv_data[full_label] = None
|
self.__csv_data[full_label] = None
|
||||||
if self.__file != None:
|
if self.__file != None:
|
||||||
print >> self.__file, self.__csv_delim.join(self.__csv_columns)
|
print(self.__csv_delim.join(self.__csv_columns), file=self.__file)
|
||||||
else:
|
else:
|
||||||
print self.__csv_delim.join(self.__csv_columns)
|
print(self.__csv_delim.join(self.__csv_columns))
|
||||||
|
|
||||||
def __printCSVRow(self):
|
def __printCSVRow(self):
|
||||||
s = []
|
s = []
|
||||||
@@ -183,18 +185,18 @@ class SDLog2Parser:
|
|||||||
s.append(v)
|
s.append(v)
|
||||||
|
|
||||||
if self.__file != None:
|
if self.__file != None:
|
||||||
print >> self.__file, self.__csv_delim.join(s)
|
print(self.__csv_delim.join(s), file=self.__file)
|
||||||
else:
|
else:
|
||||||
print self.__csv_delim.join(s)
|
print(self.__csv_delim.join(s))
|
||||||
|
|
||||||
def __parseMsgDescr(self):
|
def __parseMsgDescr(self):
|
||||||
data = struct.unpack(self.MSG_FORMAT_STRUCT, self.__buffer[self.__ptr + 3 : self.__ptr + self.MSG_FORMAT_PACKET_LEN])
|
data = struct.unpack(self.MSG_FORMAT_STRUCT, self.__buffer[self.__ptr + 3 : self.__ptr + self.MSG_FORMAT_PACKET_LEN])
|
||||||
msg_type = data[0]
|
msg_type = data[0]
|
||||||
if msg_type != self.MSG_TYPE_FORMAT:
|
if msg_type != self.MSG_TYPE_FORMAT:
|
||||||
msg_length = data[1]
|
msg_length = data[1]
|
||||||
msg_name = data[2].strip("\0")
|
msg_name = str(data[2]).strip("\0")
|
||||||
msg_format = data[3].strip("\0")
|
msg_format = str(data[3]).strip("\0")
|
||||||
msg_labels = data[4].strip("\0").split(",")
|
msg_labels = str(data[4]).strip("\0").split(",")
|
||||||
# Convert msg_format to struct.unpack format string
|
# Convert msg_format to struct.unpack format string
|
||||||
msg_struct = ""
|
msg_struct = ""
|
||||||
msg_mults = []
|
msg_mults = []
|
||||||
@@ -211,8 +213,8 @@ class SDLog2Parser:
|
|||||||
self.__msg_names.append(msg_name)
|
self.__msg_names.append(msg_name)
|
||||||
if self.__debug_out:
|
if self.__debug_out:
|
||||||
if self.__filterMsg(msg_name) != None:
|
if self.__filterMsg(msg_name) != None:
|
||||||
print "MSG FORMAT: type = %i, length = %i, name = %s, format = %s, labels = %s, struct = %s, mults = %s" % (
|
print("MSG FORMAT: type = %i, length = %i, name = %s, format = %s, labels = %s, struct = %s, mults = %s" % (
|
||||||
msg_type, msg_length, msg_name, msg_format, str(msg_labels), msg_struct, msg_mults)
|
msg_type, msg_length, msg_name, msg_format, str(msg_labels), msg_struct, msg_mults))
|
||||||
self.__ptr += self.MSG_FORMAT_PACKET_LEN
|
self.__ptr += self.MSG_FORMAT_PACKET_LEN
|
||||||
|
|
||||||
def __parseMsg(self, msg_descr):
|
def __parseMsg(self, msg_descr):
|
||||||
@@ -223,7 +225,7 @@ class SDLog2Parser:
|
|||||||
show_fields = self.__filterMsg(msg_name)
|
show_fields = self.__filterMsg(msg_name)
|
||||||
if (show_fields != None):
|
if (show_fields != None):
|
||||||
data = list(struct.unpack(msg_struct, self.__buffer[self.__ptr+self.MSG_HEADER_LEN:self.__ptr+msg_length]))
|
data = list(struct.unpack(msg_struct, self.__buffer[self.__ptr+self.MSG_HEADER_LEN:self.__ptr+msg_length]))
|
||||||
for i in xrange(len(data)):
|
for i in range(len(data)):
|
||||||
if type(data[i]) is str:
|
if type(data[i]) is str:
|
||||||
data[i] = data[i].strip("\0")
|
data[i] = data[i].strip("\0")
|
||||||
m = msg_mults[i]
|
m = msg_mults[i]
|
||||||
@@ -231,14 +233,14 @@ class SDLog2Parser:
|
|||||||
data[i] = data[i] * m
|
data[i] = data[i] * m
|
||||||
if self.__debug_out:
|
if self.__debug_out:
|
||||||
s = []
|
s = []
|
||||||
for i in xrange(len(data)):
|
for i in range(len(data)):
|
||||||
label = msg_labels[i]
|
label = msg_labels[i]
|
||||||
if show_fields == "*" or label in show_fields:
|
if show_fields == "*" or label in show_fields:
|
||||||
s.append(label + "=" + str(data[i]))
|
s.append(label + "=" + str(data[i]))
|
||||||
print "MSG %s: %s" % (msg_name, ", ".join(s))
|
print("MSG %s: %s" % (msg_name, ", ".join(s)))
|
||||||
else:
|
else:
|
||||||
# update CSV data buffer
|
# update CSV data buffer
|
||||||
for i in xrange(len(data)):
|
for i in range(len(data)):
|
||||||
label = msg_labels[i]
|
label = msg_labels[i]
|
||||||
if label in show_fields:
|
if label in show_fields:
|
||||||
self.__csv_data[msg_name + "_" + label] = data[i]
|
self.__csv_data[msg_name + "_" + label] = data[i]
|
||||||
@@ -250,14 +252,14 @@ class SDLog2Parser:
|
|||||||
|
|
||||||
def _main():
|
def _main():
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print "Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[.field1,field2,...]] [-t TIME_MSG_NAME]\n"
|
print("Usage: python sdlog2_dump.py <log.bin> [-v] [-e] [-d delimiter] [-n null] [-m MSG[.field1,field2,...]] [-t TIME_MSG_NAME]\n")
|
||||||
print "\t-v\tUse plain debug output instead of CSV.\n"
|
print("\t-v\tUse plain debug output instead of CSV.\n")
|
||||||
print "\t-e\tRecover from errors.\n"
|
print("\t-e\tRecover from errors.\n")
|
||||||
print "\t-d\tUse \"delimiter\" in CSV. Default is \",\".\n"
|
print("\t-d\tUse \"delimiter\" in CSV. Default is \",\".\n")
|
||||||
print "\t-n\tUse \"null\" as placeholder for empty values in CSV. Default is empty.\n"
|
print("\t-n\tUse \"null\" as placeholder for empty values in CSV. Default is empty.\n")
|
||||||
print "\t-m MSG[.field1,field2,...]\n\t\tDump only messages of specified type, and only specified fields.\n\t\tMultiple -m options allowed."
|
print("\t-m MSG[.field1,field2,...]\n\t\tDump only messages of specified type, and only specified fields.\n\t\tMultiple -m options allowed.")
|
||||||
print "\t-t\tSpecify TIME message name to group data messages by time and significantly reduce duplicate output.\n"
|
print("\t-t\tSpecify TIME message name to group data messages by time and significantly reduce duplicate output.\n")
|
||||||
print "\t-fPrint to file instead of stdout"
|
print("\t-fPrint to file instead of stdout")
|
||||||
return
|
return
|
||||||
fn = sys.argv[1]
|
fn = sys.argv[1]
|
||||||
debug_out = False
|
debug_out = False
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ MODULES += examples/flow_position_estimator
|
|||||||
#
|
#
|
||||||
# Vehicle Control
|
# Vehicle Control
|
||||||
#
|
#
|
||||||
|
MODULES += modules/segway
|
||||||
MODULES += modules/fixedwing_backside
|
MODULES += modules/fixedwing_backside
|
||||||
MODULES += modules/fixedwing_att_control
|
MODULES += modules/fixedwing_att_control
|
||||||
MODULES += modules/fixedwing_pos_control
|
MODULES += modules/fixedwing_pos_control
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include "BlockSysIdent.hpp"
|
||||||
|
|
||||||
|
BlockSysIdent::BlockSysIdent() :
|
||||||
|
Block(NULL, "SYSID"),
|
||||||
|
_freq(this, "FREQ"),
|
||||||
|
_ampl(this, "AMPL")
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include <controllib/block/Block.hpp>
|
||||||
|
#include <controllib/block/BlockParam.hpp>
|
||||||
|
|
||||||
|
class BlockSysIdent : public control::Block {
|
||||||
|
public:
|
||||||
|
BlockSysIdent();
|
||||||
|
private:
|
||||||
|
control::BlockParam<float> _freq;
|
||||||
|
control::BlockParam<float> _ampl;
|
||||||
|
};
|
||||||
@@ -45,9 +45,16 @@
|
|||||||
#include "md25.hpp"
|
#include "md25.hpp"
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <arch/board/board.h>
|
#include <arch/board/board.h>
|
||||||
|
#include <mavlink/mavlink_log.h>
|
||||||
|
|
||||||
|
#include <controllib/uorb/UOrbPublication.hpp>
|
||||||
|
#include <uORB/topics/debug_key_value.h>
|
||||||
|
#include <drivers/drv_hrt.h>
|
||||||
|
|
||||||
// registers
|
// registers
|
||||||
enum {
|
enum {
|
||||||
@@ -72,6 +79,9 @@ enum {
|
|||||||
REG_COMMAND_RW,
|
REG_COMMAND_RW,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// File descriptors
|
||||||
|
static int mavlink_fd;
|
||||||
|
|
||||||
MD25::MD25(const char *deviceName, int bus,
|
MD25::MD25(const char *deviceName, int bus,
|
||||||
uint16_t address, uint32_t speed) :
|
uint16_t address, uint32_t speed) :
|
||||||
I2C("MD25", deviceName, bus, address, speed),
|
I2C("MD25", deviceName, bus, address, speed),
|
||||||
@@ -106,7 +116,8 @@ MD25::MD25(const char *deviceName, int bus,
|
|||||||
setMotor2Speed(0);
|
setMotor2Speed(0);
|
||||||
resetEncoders();
|
resetEncoders();
|
||||||
_setMode(MD25::MODE_UNSIGNED_SPEED);
|
_setMode(MD25::MODE_UNSIGNED_SPEED);
|
||||||
setSpeedRegulation(true);
|
setSpeedRegulation(false);
|
||||||
|
setMotorAccel(10);
|
||||||
setTimeout(true);
|
setTimeout(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,6 +309,12 @@ int MD25::setDeviceAddress(uint8_t address)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MD25::setMotorAccel(uint8_t accel)
|
||||||
|
{
|
||||||
|
return _writeUint8(REG_ACCEL_RATE_RW,
|
||||||
|
accel);
|
||||||
|
}
|
||||||
|
|
||||||
int MD25::setMotor1Speed(float value)
|
int MD25::setMotor1Speed(float value)
|
||||||
{
|
{
|
||||||
return _writeUint8(REG_SPEED1_RW,
|
return _writeUint8(REG_SPEED1_RW,
|
||||||
@@ -451,12 +468,12 @@ int md25Test(const char *deviceName, uint8_t bus, uint8_t address)
|
|||||||
MD25 md25("/dev/md25", bus, address);
|
MD25 md25("/dev/md25", bus, address);
|
||||||
|
|
||||||
// print status
|
// print status
|
||||||
char buf[200];
|
char buf[400];
|
||||||
md25.status(buf, sizeof(buf));
|
md25.status(buf, sizeof(buf));
|
||||||
printf("%s\n", buf);
|
printf("%s\n", buf);
|
||||||
|
|
||||||
// setup for test
|
// setup for test
|
||||||
md25.setSpeedRegulation(true);
|
md25.setSpeedRegulation(false);
|
||||||
md25.setTimeout(true);
|
md25.setTimeout(true);
|
||||||
float dt = 0.1;
|
float dt = 0.1;
|
||||||
float speed = 0.2;
|
float speed = 0.2;
|
||||||
@@ -550,4 +567,68 @@ int md25Test(const char *deviceName, uint8_t bus, uint8_t address)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int md25Sine(const char *deviceName, uint8_t bus, uint8_t address, float amplitude, float frequency)
|
||||||
|
{
|
||||||
|
printf("md25 sine: starting\n");
|
||||||
|
|
||||||
|
// setup
|
||||||
|
MD25 md25("/dev/md25", bus, address);
|
||||||
|
|
||||||
|
// print status
|
||||||
|
char buf[400];
|
||||||
|
md25.status(buf, sizeof(buf));
|
||||||
|
printf("%s\n", buf);
|
||||||
|
|
||||||
|
// setup for test
|
||||||
|
md25.setSpeedRegulation(false);
|
||||||
|
md25.setTimeout(true);
|
||||||
|
float dt = 0.01;
|
||||||
|
float t_final = 60.0;
|
||||||
|
float prev_revolution = md25.getRevolutions1();
|
||||||
|
|
||||||
|
// debug publication
|
||||||
|
control::UOrbPublication<debug_key_value_s> debug_msg(NULL,
|
||||||
|
ORB_ID(debug_key_value));
|
||||||
|
|
||||||
|
// sine wave for motor 1
|
||||||
|
md25.resetEncoders();
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
// input
|
||||||
|
uint64_t timestamp = hrt_absolute_time();
|
||||||
|
float t = timestamp/1000000.0f;
|
||||||
|
|
||||||
|
float input_value = amplitude*sinf(2*M_PI*frequency*t);
|
||||||
|
md25.setMotor1Speed(input_value);
|
||||||
|
|
||||||
|
// output
|
||||||
|
md25.readData();
|
||||||
|
float current_revolution = md25.getRevolutions1();
|
||||||
|
|
||||||
|
// send input message
|
||||||
|
//strncpy(debug_msg.key, "md25 in ", 10);
|
||||||
|
//debug_msg.timestamp_ms = 1000*timestamp;
|
||||||
|
//debug_msg.value = input_value;
|
||||||
|
//debug_msg.update();
|
||||||
|
|
||||||
|
// send output message
|
||||||
|
strncpy(debug_msg.key, "md25 out ", 10);
|
||||||
|
debug_msg.timestamp_ms = 1000*timestamp;
|
||||||
|
debug_msg.value = current_revolution;
|
||||||
|
debug_msg.update();
|
||||||
|
|
||||||
|
if (t > t_final) break;
|
||||||
|
|
||||||
|
// update for next step
|
||||||
|
prev_revolution = current_revolution;
|
||||||
|
|
||||||
|
// sleep
|
||||||
|
usleep(1000000 * dt);
|
||||||
|
}
|
||||||
|
md25.setMotor1Speed(0);
|
||||||
|
|
||||||
|
printf("md25 sine complete\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
|
// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <controllib/block/UOrbSubscription.hpp>
|
#include <controllib/uorb/UOrbSubscription.hpp>
|
||||||
#include <uORB/topics/actuator_controls.h>
|
#include <uORB/topics/actuator_controls.h>
|
||||||
#include <drivers/device/i2c.h>
|
#include <drivers/device/i2c.h>
|
||||||
|
|
||||||
@@ -212,6 +212,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
int setDeviceAddress(uint8_t address);
|
int setDeviceAddress(uint8_t address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set motor acceleration
|
||||||
|
* @param accel
|
||||||
|
* controls motor speed change (1-10)
|
||||||
|
* accel rate | time for full fwd. to full rev.
|
||||||
|
* 1 | 6.375 s
|
||||||
|
* 2 | 1.6 s
|
||||||
|
* 3 | 0.675 s
|
||||||
|
* 5(default) | 1.275 s
|
||||||
|
* 10 | 0.65 s
|
||||||
|
*/
|
||||||
|
int setMotorAccel(uint8_t accel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set motor 1 speed
|
* set motor 1 speed
|
||||||
* @param normSpeed normalize speed between -1 and 1
|
* @param normSpeed normalize speed between -1 and 1
|
||||||
@@ -290,4 +303,7 @@ private:
|
|||||||
// unit testing
|
// unit testing
|
||||||
int md25Test(const char *deviceName, uint8_t bus, uint8_t address);
|
int md25Test(const char *deviceName, uint8_t bus, uint8_t address);
|
||||||
|
|
||||||
|
// sine testing
|
||||||
|
int md25Sine(const char *deviceName, uint8_t bus, uint8_t address, float amplitude, float frequency);
|
||||||
|
|
||||||
// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
|
// vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ usage(const char *reason)
|
|||||||
if (reason)
|
if (reason)
|
||||||
fprintf(stderr, "%s\n", reason);
|
fprintf(stderr, "%s\n", reason);
|
||||||
|
|
||||||
fprintf(stderr, "usage: md25 {start|stop|status|search|test|change_address}\n\n");
|
fprintf(stderr, "usage: md25 {start|stop|read|status|search|test|change_address}\n\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +136,28 @@ int md25_main(int argc, char *argv[])
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "sine")) {
|
||||||
|
|
||||||
|
if (argc < 6) {
|
||||||
|
printf("usage: md25 sine bus address amp freq\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *deviceName = "/dev/md25";
|
||||||
|
|
||||||
|
uint8_t bus = strtoul(argv[2], nullptr, 0);
|
||||||
|
|
||||||
|
uint8_t address = strtoul(argv[3], nullptr, 0);
|
||||||
|
|
||||||
|
float amplitude = atof(argv[4]);
|
||||||
|
|
||||||
|
float frequency = atof(argv[5]);
|
||||||
|
|
||||||
|
md25Sine(deviceName, bus, address, amplitude, frequency);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(argv[1], "probe")) {
|
if (!strcmp(argv[1], "probe")) {
|
||||||
if (argc < 4) {
|
if (argc < 4) {
|
||||||
printf("usage: md25 probe bus address\n");
|
printf("usage: md25 probe bus address\n");
|
||||||
@@ -162,6 +184,29 @@ int md25_main(int argc, char *argv[])
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "read")) {
|
||||||
|
if (argc < 4) {
|
||||||
|
printf("usage: md25 read bus address\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *deviceName = "/dev/md25";
|
||||||
|
|
||||||
|
uint8_t bus = strtoul(argv[2], nullptr, 0);
|
||||||
|
|
||||||
|
uint8_t address = strtoul(argv[3], nullptr, 0);
|
||||||
|
|
||||||
|
MD25 md25(deviceName, bus, address);
|
||||||
|
|
||||||
|
// print status
|
||||||
|
char buf[400];
|
||||||
|
md25.status(buf, sizeof(buf));
|
||||||
|
printf("%s\n", buf);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!strcmp(argv[1], "search")) {
|
if (!strcmp(argv[1], "search")) {
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
printf("usage: md25 search bus\n");
|
printf("usage: md25 search bus\n");
|
||||||
@@ -246,7 +291,7 @@ int md25_thread_main(int argc, char *argv[])
|
|||||||
uint8_t address = strtoul(argv[4], nullptr, 0);
|
uint8_t address = strtoul(argv[4], nullptr, 0);
|
||||||
|
|
||||||
// start
|
// start
|
||||||
MD25 md25("/dev/md25", bus, address);
|
MD25 md25(deviceName, bus, address);
|
||||||
|
|
||||||
thread_running = true;
|
thread_running = true;
|
||||||
|
|
||||||
|
|||||||
@@ -47,8 +47,8 @@
|
|||||||
#include <mathlib/mathlib.h>
|
#include <mathlib/mathlib.h>
|
||||||
#include <controllib/blocks.hpp>
|
#include <controllib/blocks.hpp>
|
||||||
#include <controllib/block/BlockParam.hpp>
|
#include <controllib/block/BlockParam.hpp>
|
||||||
#include <controllib/block/UOrbSubscription.hpp>
|
#include <controllib/uorb/UOrbSubscription.hpp>
|
||||||
#include <controllib/block/UOrbPublication.hpp>
|
#include <controllib/uorb/UOrbPublication.hpp>
|
||||||
|
|
||||||
#include <uORB/topics/vehicle_attitude.h>
|
#include <uORB/topics/vehicle_attitude.h>
|
||||||
#include <uORB/topics/vehicle_global_position.h>
|
#include <uORB/topics/vehicle_global_position.h>
|
||||||
|
|||||||
@@ -43,8 +43,8 @@
|
|||||||
|
|
||||||
#include "Block.hpp"
|
#include "Block.hpp"
|
||||||
#include "BlockParam.hpp"
|
#include "BlockParam.hpp"
|
||||||
#include "UOrbSubscription.hpp"
|
#include "../uorb/UOrbSubscription.hpp"
|
||||||
#include "UOrbPublication.hpp"
|
#include "../uorb/UOrbPublication.hpp"
|
||||||
|
|
||||||
namespace control
|
namespace control
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
#include <mathlib/math/test/test.hpp>
|
#include <mathlib/math/test/test.hpp>
|
||||||
|
|
||||||
#include "block/Block.hpp"
|
#include "block/Block.hpp"
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
SRCS = test_params.c \
|
SRCS = test_params.c \
|
||||||
block/Block.cpp \
|
block/Block.cpp \
|
||||||
block/BlockParam.cpp \
|
block/BlockParam.cpp \
|
||||||
block/UOrbPublication.cpp \
|
uorb/UOrbPublication.cpp \
|
||||||
block/UOrbSubscription.cpp \
|
uorb/UOrbSubscription.cpp \
|
||||||
blocks.cpp \
|
uorb/blocks.cpp \
|
||||||
fixedwing.cpp
|
blocks.cpp
|
||||||
|
|||||||
+2
-2
@@ -39,8 +39,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <uORB/uORB.h>
|
#include <uORB/uORB.h>
|
||||||
#include "Block.hpp"
|
#include "../block/Block.hpp"
|
||||||
#include "List.hpp"
|
#include "../block/List.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace control
|
namespace control
|
||||||
+2
-2
@@ -39,8 +39,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <uORB/uORB.h>
|
#include <uORB/uORB.h>
|
||||||
#include "Block.hpp"
|
#include "../block/Block.hpp"
|
||||||
#include "List.hpp"
|
#include "../block/List.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace control
|
namespace control
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file uorb_blocks.cpp
|
||||||
|
*
|
||||||
|
* uorb block library code
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "blocks.hpp"
|
||||||
|
|
||||||
|
namespace control
|
||||||
|
{
|
||||||
|
|
||||||
|
BlockWaypointGuidance::BlockWaypointGuidance(SuperBlock *parent, const char *name) :
|
||||||
|
SuperBlock(parent, name),
|
||||||
|
_xtYawLimit(this, "XT2YAW"),
|
||||||
|
_xt2Yaw(this, "XT2YAW"),
|
||||||
|
_psiCmd(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockWaypointGuidance::~BlockWaypointGuidance() {};
|
||||||
|
|
||||||
|
void BlockWaypointGuidance::update(vehicle_global_position_s &pos,
|
||||||
|
vehicle_attitude_s &att,
|
||||||
|
vehicle_global_position_setpoint_s &posCmd,
|
||||||
|
vehicle_global_position_setpoint_s &lastPosCmd)
|
||||||
|
{
|
||||||
|
|
||||||
|
// heading to waypoint
|
||||||
|
float psiTrack = get_bearing_to_next_waypoint(
|
||||||
|
(double)pos.lat / (double)1e7d,
|
||||||
|
(double)pos.lon / (double)1e7d,
|
||||||
|
(double)posCmd.lat / (double)1e7d,
|
||||||
|
(double)posCmd.lon / (double)1e7d);
|
||||||
|
|
||||||
|
// cross track
|
||||||
|
struct crosstrack_error_s xtrackError;
|
||||||
|
get_distance_to_line(&xtrackError,
|
||||||
|
(double)pos.lat / (double)1e7d,
|
||||||
|
(double)pos.lon / (double)1e7d,
|
||||||
|
(double)lastPosCmd.lat / (double)1e7d,
|
||||||
|
(double)lastPosCmd.lon / (double)1e7d,
|
||||||
|
(double)posCmd.lat / (double)1e7d,
|
||||||
|
(double)posCmd.lon / (double)1e7d);
|
||||||
|
|
||||||
|
_psiCmd = _wrap_2pi(psiTrack -
|
||||||
|
_xtYawLimit.update(_xt2Yaw.update(xtrackError.distance)));
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockUorbEnabledAutopilot::BlockUorbEnabledAutopilot(SuperBlock *parent, const char *name) :
|
||||||
|
SuperBlock(parent, name),
|
||||||
|
// subscriptions
|
||||||
|
_att(&getSubscriptions(), ORB_ID(vehicle_attitude), 20),
|
||||||
|
_attCmd(&getSubscriptions(), ORB_ID(vehicle_attitude_setpoint), 20),
|
||||||
|
_ratesCmd(&getSubscriptions(), ORB_ID(vehicle_rates_setpoint), 20),
|
||||||
|
_pos(&getSubscriptions() , ORB_ID(vehicle_global_position), 20),
|
||||||
|
_posCmd(&getSubscriptions(), ORB_ID(vehicle_global_position_set_triplet), 20),
|
||||||
|
_manual(&getSubscriptions(), ORB_ID(manual_control_setpoint), 20),
|
||||||
|
_status(&getSubscriptions(), ORB_ID(vehicle_status), 20),
|
||||||
|
_param_update(&getSubscriptions(), ORB_ID(parameter_update), 1000), // limit to 1 Hz
|
||||||
|
// publications
|
||||||
|
_actuators(&getPublications(), ORB_ID(actuator_controls_0))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockUorbEnabledAutopilot::~BlockUorbEnabledAutopilot() {};
|
||||||
|
|
||||||
|
} // namespace control
|
||||||
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 PX4 Development Team. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file uorb_blocks.h
|
||||||
|
*
|
||||||
|
* uorb block library code
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
||||||
|
#include <uORB/topics/vehicle_attitude.h>
|
||||||
|
#include <uORB/topics/vehicle_rates_setpoint.h>
|
||||||
|
#include <uORB/topics/vehicle_global_position.h>
|
||||||
|
#include <uORB/topics/vehicle_global_position_set_triplet.h>
|
||||||
|
#include <uORB/topics/manual_control_setpoint.h>
|
||||||
|
#include <uORB/topics/vehicle_status.h>
|
||||||
|
#include <uORB/topics/actuator_controls.h>
|
||||||
|
#include <uORB/topics/parameter_update.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include <drivers/drv_hrt.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <systemlib/geo/geo.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "../blocks.hpp"
|
||||||
|
#include "UOrbSubscription.hpp"
|
||||||
|
#include "UOrbPublication.hpp"
|
||||||
|
|
||||||
|
namespace control
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waypoint Guidance block
|
||||||
|
*/
|
||||||
|
class __EXPORT BlockWaypointGuidance : public SuperBlock
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
BlockLimitSym _xtYawLimit;
|
||||||
|
BlockP _xt2Yaw;
|
||||||
|
float _psiCmd;
|
||||||
|
public:
|
||||||
|
BlockWaypointGuidance(SuperBlock *parent, const char *name);
|
||||||
|
virtual ~BlockWaypointGuidance();
|
||||||
|
void update(vehicle_global_position_s &pos,
|
||||||
|
vehicle_attitude_s &att,
|
||||||
|
vehicle_global_position_setpoint_s &posCmd,
|
||||||
|
vehicle_global_position_setpoint_s &lastPosCmd);
|
||||||
|
float getPsiCmd() { return _psiCmd; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UorbEnabledAutopilot
|
||||||
|
*/
|
||||||
|
class __EXPORT BlockUorbEnabledAutopilot : public SuperBlock
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
// subscriptions
|
||||||
|
UOrbSubscription<vehicle_attitude_s> _att;
|
||||||
|
UOrbSubscription<vehicle_attitude_setpoint_s> _attCmd;
|
||||||
|
UOrbSubscription<vehicle_rates_setpoint_s> _ratesCmd;
|
||||||
|
UOrbSubscription<vehicle_global_position_s> _pos;
|
||||||
|
UOrbSubscription<vehicle_global_position_set_triplet_s> _posCmd;
|
||||||
|
UOrbSubscription<manual_control_setpoint_s> _manual;
|
||||||
|
UOrbSubscription<vehicle_status_s> _status;
|
||||||
|
UOrbSubscription<parameter_update_s> _param_update;
|
||||||
|
// publications
|
||||||
|
UOrbPublication<actuator_controls_s> _actuators;
|
||||||
|
public:
|
||||||
|
BlockUorbEnabledAutopilot(SuperBlock *parent, const char *name);
|
||||||
|
virtual ~BlockUorbEnabledAutopilot();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace control
|
||||||
|
|
||||||
@@ -86,61 +86,6 @@ void BlockStabilization::update(float pCmd, float qCmd, float rCmd,
|
|||||||
_yawDamper.update(rCmd, r, outputScale);
|
_yawDamper.update(rCmd, r, outputScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockWaypointGuidance::BlockWaypointGuidance(SuperBlock *parent, const char *name) :
|
|
||||||
SuperBlock(parent, name),
|
|
||||||
_xtYawLimit(this, "XT2YAW"),
|
|
||||||
_xt2Yaw(this, "XT2YAW"),
|
|
||||||
_psiCmd(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockWaypointGuidance::~BlockWaypointGuidance() {};
|
|
||||||
|
|
||||||
void BlockWaypointGuidance::update(vehicle_global_position_s &pos,
|
|
||||||
vehicle_attitude_s &att,
|
|
||||||
vehicle_global_position_setpoint_s &posCmd,
|
|
||||||
vehicle_global_position_setpoint_s &lastPosCmd)
|
|
||||||
{
|
|
||||||
|
|
||||||
// heading to waypoint
|
|
||||||
float psiTrack = get_bearing_to_next_waypoint(
|
|
||||||
(double)pos.lat / (double)1e7d,
|
|
||||||
(double)pos.lon / (double)1e7d,
|
|
||||||
(double)posCmd.lat / (double)1e7d,
|
|
||||||
(double)posCmd.lon / (double)1e7d);
|
|
||||||
|
|
||||||
// cross track
|
|
||||||
struct crosstrack_error_s xtrackError;
|
|
||||||
get_distance_to_line(&xtrackError,
|
|
||||||
(double)pos.lat / (double)1e7d,
|
|
||||||
(double)pos.lon / (double)1e7d,
|
|
||||||
(double)lastPosCmd.lat / (double)1e7d,
|
|
||||||
(double)lastPosCmd.lon / (double)1e7d,
|
|
||||||
(double)posCmd.lat / (double)1e7d,
|
|
||||||
(double)posCmd.lon / (double)1e7d);
|
|
||||||
|
|
||||||
_psiCmd = _wrap_2pi(psiTrack -
|
|
||||||
_xtYawLimit.update(_xt2Yaw.update(xtrackError.distance)));
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockUorbEnabledAutopilot::BlockUorbEnabledAutopilot(SuperBlock *parent, const char *name) :
|
|
||||||
SuperBlock(parent, name),
|
|
||||||
// subscriptions
|
|
||||||
_att(&getSubscriptions(), ORB_ID(vehicle_attitude), 20),
|
|
||||||
_attCmd(&getSubscriptions(), ORB_ID(vehicle_attitude_setpoint), 20),
|
|
||||||
_ratesCmd(&getSubscriptions(), ORB_ID(vehicle_rates_setpoint), 20),
|
|
||||||
_pos(&getSubscriptions() , ORB_ID(vehicle_global_position), 20),
|
|
||||||
_posCmd(&getSubscriptions(), ORB_ID(vehicle_global_position_set_triplet), 20),
|
|
||||||
_manual(&getSubscriptions(), ORB_ID(manual_control_setpoint), 20),
|
|
||||||
_status(&getSubscriptions(), ORB_ID(vehicle_status), 20),
|
|
||||||
_param_update(&getSubscriptions(), ORB_ID(parameter_update), 1000), // limit to 1 Hz
|
|
||||||
// publications
|
|
||||||
_actuators(&getPublications(), ORB_ID(actuator_controls_0))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockUorbEnabledAutopilot::~BlockUorbEnabledAutopilot() {};
|
|
||||||
|
|
||||||
BlockMultiModeBacksideAutopilot::BlockMultiModeBacksideAutopilot(SuperBlock *parent, const char *name) :
|
BlockMultiModeBacksideAutopilot::BlockMultiModeBacksideAutopilot(SuperBlock *parent, const char *name) :
|
||||||
BlockUorbEnabledAutopilot(parent, name),
|
BlockUorbEnabledAutopilot(parent, name),
|
||||||
_stabilization(this, ""), // no name needed, already unique
|
_stabilization(this, ""), // no name needed, already unique
|
||||||
+2
-66
@@ -39,31 +39,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <uORB/topics/vehicle_attitude_setpoint.h>
|
#include <controllib/blocks.hpp>
|
||||||
#include <uORB/topics/vehicle_attitude.h>
|
#include <controllib/uorb/blocks.hpp>
|
||||||
#include <uORB/topics/vehicle_rates_setpoint.h>
|
|
||||||
#include <uORB/topics/vehicle_global_position.h>
|
|
||||||
#include <uORB/topics/vehicle_global_position_set_triplet.h>
|
|
||||||
#include <uORB/topics/manual_control_setpoint.h>
|
|
||||||
#include <uORB/topics/vehicle_status.h>
|
|
||||||
#include <uORB/topics/actuator_controls.h>
|
|
||||||
#include <uORB/topics/parameter_update.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <drivers/drv_hrt.h>
|
|
||||||
#include <poll.h>
|
|
||||||
|
|
||||||
#include "blocks.hpp"
|
|
||||||
#include "block/UOrbSubscription.hpp"
|
|
||||||
#include "block/UOrbPublication.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <systemlib/geo/geo.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace control
|
namespace control
|
||||||
{
|
{
|
||||||
@@ -250,47 +227,6 @@ public:
|
|||||||
* than frontside at high speeds.
|
* than frontside at high speeds.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* Waypoint Guidance block
|
|
||||||
*/
|
|
||||||
class __EXPORT BlockWaypointGuidance : public SuperBlock
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
BlockLimitSym _xtYawLimit;
|
|
||||||
BlockP _xt2Yaw;
|
|
||||||
float _psiCmd;
|
|
||||||
public:
|
|
||||||
BlockWaypointGuidance(SuperBlock *parent, const char *name);
|
|
||||||
virtual ~BlockWaypointGuidance();
|
|
||||||
void update(vehicle_global_position_s &pos,
|
|
||||||
vehicle_attitude_s &att,
|
|
||||||
vehicle_global_position_setpoint_s &posCmd,
|
|
||||||
vehicle_global_position_setpoint_s &lastPosCmd);
|
|
||||||
float getPsiCmd() { return _psiCmd; }
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UorbEnabledAutopilot
|
|
||||||
*/
|
|
||||||
class __EXPORT BlockUorbEnabledAutopilot : public SuperBlock
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
// subscriptions
|
|
||||||
UOrbSubscription<vehicle_attitude_s> _att;
|
|
||||||
UOrbSubscription<vehicle_attitude_setpoint_s> _attCmd;
|
|
||||||
UOrbSubscription<vehicle_rates_setpoint_s> _ratesCmd;
|
|
||||||
UOrbSubscription<vehicle_global_position_s> _pos;
|
|
||||||
UOrbSubscription<vehicle_global_position_set_triplet_s> _posCmd;
|
|
||||||
UOrbSubscription<manual_control_setpoint_s> _manual;
|
|
||||||
UOrbSubscription<vehicle_status_s> _status;
|
|
||||||
UOrbSubscription<parameter_update_s> _param_update;
|
|
||||||
// publications
|
|
||||||
UOrbPublication<actuator_controls_s> _actuators;
|
|
||||||
public:
|
|
||||||
BlockUorbEnabledAutopilot(SuperBlock *parent, const char *name);
|
|
||||||
virtual ~BlockUorbEnabledAutopilot();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multi-mode Autopilot
|
* Multi-mode Autopilot
|
||||||
*/
|
*/
|
||||||
@@ -45,12 +45,13 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <systemlib/systemlib.h>
|
#include <systemlib/systemlib.h>
|
||||||
#include <controllib/fixedwing.hpp>
|
|
||||||
#include <systemlib/param/param.h>
|
#include <systemlib/param/param.h>
|
||||||
#include <systemlib/err.h>
|
#include <systemlib/err.h>
|
||||||
#include <drivers/drv_hrt.h>
|
#include <drivers/drv_hrt.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "fixedwing.hpp"
|
||||||
|
|
||||||
static bool thread_should_exit = false; /**< Deamon exit flag */
|
static bool thread_should_exit = false; /**< Deamon exit flag */
|
||||||
static bool thread_running = false; /**< Deamon status flag */
|
static bool thread_running = false; /**< Deamon status flag */
|
||||||
static int deamon_task; /**< Handle of deamon task / thread */
|
static int deamon_task; /**< Handle of deamon task / thread */
|
||||||
|
|||||||
@@ -38,4 +38,5 @@
|
|||||||
MODULE_COMMAND = fixedwing_backside
|
MODULE_COMMAND = fixedwing_backside
|
||||||
|
|
||||||
SRCS = fixedwing_backside_main.cpp \
|
SRCS = fixedwing_backside_main.cpp \
|
||||||
|
fixedwing.cpp \
|
||||||
params.c
|
params.c
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#include "BlockSegwayController.hpp"
|
||||||
|
|
||||||
|
void BlockSegwayController::update() {
|
||||||
|
// wait for a sensor update, check for exit condition every 100 ms
|
||||||
|
if (poll(&_attPoll, 1, 100) < 0) return; // poll error
|
||||||
|
|
||||||
|
uint64_t newTimeStamp = hrt_absolute_time();
|
||||||
|
float dt = (newTimeStamp - _timeStamp) / 1.0e6f;
|
||||||
|
_timeStamp = newTimeStamp;
|
||||||
|
|
||||||
|
// check for sane values of dt
|
||||||
|
// to prevent large control responses
|
||||||
|
if (dt > 1.0f || dt < 0) return;
|
||||||
|
|
||||||
|
// set dt for all child blocks
|
||||||
|
setDt(dt);
|
||||||
|
|
||||||
|
// check for new updates
|
||||||
|
if (_param_update.updated()) updateParams();
|
||||||
|
|
||||||
|
// get new information from subscriptions
|
||||||
|
updateSubscriptions();
|
||||||
|
|
||||||
|
// default all output to zero unless handled by mode
|
||||||
|
for (unsigned i = 2; i < NUM_ACTUATOR_CONTROLS; i++)
|
||||||
|
_actuators.control[i] = 0.0f;
|
||||||
|
|
||||||
|
// only update guidance in auto mode
|
||||||
|
if (_status.state_machine == SYSTEM_STATE_AUTO) {
|
||||||
|
// update guidance
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute speed command
|
||||||
|
float spdCmd = -th2v.update(_att.pitch) - q2v.update(_att.pitchspeed);
|
||||||
|
|
||||||
|
// handle autopilot modes
|
||||||
|
if (_status.state_machine == SYSTEM_STATE_AUTO ||
|
||||||
|
_status.state_machine == SYSTEM_STATE_STABILIZED) {
|
||||||
|
_actuators.control[0] = spdCmd;
|
||||||
|
_actuators.control[1] = spdCmd;
|
||||||
|
|
||||||
|
} else if (_status.state_machine == SYSTEM_STATE_MANUAL) {
|
||||||
|
if (_status.manual_control_mode == VEHICLE_MANUAL_CONTROL_MODE_DIRECT) {
|
||||||
|
_actuators.control[CH_LEFT] = _manual.throttle;
|
||||||
|
_actuators.control[CH_RIGHT] = _manual.pitch;
|
||||||
|
|
||||||
|
} else if (_status.manual_control_mode == VEHICLE_MANUAL_CONTROL_MODE_SAS) {
|
||||||
|
_actuators.control[0] = spdCmd;
|
||||||
|
_actuators.control[1] = spdCmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update all publications
|
||||||
|
updatePublications();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <controllib/uorb/blocks.hpp>
|
||||||
|
|
||||||
|
using namespace control;
|
||||||
|
|
||||||
|
class BlockSegwayController : public control::BlockUorbEnabledAutopilot {
|
||||||
|
public:
|
||||||
|
BlockSegwayController() :
|
||||||
|
BlockUorbEnabledAutopilot(NULL,"SEG"),
|
||||||
|
th2v(this, "TH2V"),
|
||||||
|
q2v(this, "Q2V"),
|
||||||
|
_attPoll(),
|
||||||
|
_timeStamp(0)
|
||||||
|
{
|
||||||
|
_attPoll.fd = _att.getHandle();
|
||||||
|
_attPoll.events = POLLIN;
|
||||||
|
}
|
||||||
|
void update();
|
||||||
|
private:
|
||||||
|
enum {CH_LEFT, CH_RIGHT};
|
||||||
|
BlockPI th2v;
|
||||||
|
BlockP q2v;
|
||||||
|
struct pollfd _attPoll;
|
||||||
|
uint64_t _timeStamp;
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
############################################################################
|
||||||
|
#
|
||||||
|
# Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions
|
||||||
|
# are met:
|
||||||
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer.
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
# notice, this list of conditions and the following disclaimer in
|
||||||
|
# the documentation and/or other materials provided with the
|
||||||
|
# distribution.
|
||||||
|
# 3. Neither the name PX4 nor the names of its contributors may be
|
||||||
|
# used to endorse or promote products derived from this software
|
||||||
|
# without specific prior written permission.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
#
|
||||||
|
# segway controller
|
||||||
|
#
|
||||||
|
|
||||||
|
MODULE_COMMAND = segway
|
||||||
|
|
||||||
|
SRCS = segway_main.cpp \
|
||||||
|
BlockSegwayController.cpp \
|
||||||
|
params.c
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include <systemlib/param/param.h>
|
||||||
|
|
||||||
|
// 16 is max name length
|
||||||
|
PARAM_DEFINE_FLOAT(SEG_TH2V_P, 10.0f); // pitch to voltage
|
||||||
|
PARAM_DEFINE_FLOAT(SEG_TH2V_I, 0.0f); // pitch integral to voltage
|
||||||
|
PARAM_DEFINE_FLOAT(SEG_TH2V_I_MAX, 0.0f); // integral limiter
|
||||||
|
PARAM_DEFINE_FLOAT(SEG_Q2V, 1.0f); // pitch rate to voltage
|
||||||
|
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012, 2013 PX4 Development Team. All rights reserved.
|
||||||
|
* Author: James Goppert
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name PX4 nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file segway_main.cpp
|
||||||
|
* @author James Goppert
|
||||||
|
*
|
||||||
|
* Segway controller using control library
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <systemlib/systemlib.h>
|
||||||
|
#include <systemlib/param/param.h>
|
||||||
|
#include <systemlib/err.h>
|
||||||
|
#include <drivers/drv_hrt.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "BlockSegwayController.hpp"
|
||||||
|
|
||||||
|
static bool thread_should_exit = false; /**< Deamon exit flag */
|
||||||
|
static bool thread_running = false; /**< Deamon status flag */
|
||||||
|
static int deamon_task; /**< Handle of deamon task / thread */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deamon management function.
|
||||||
|
*/
|
||||||
|
extern "C" __EXPORT int segway_main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mainloop of deamon.
|
||||||
|
*/
|
||||||
|
int segway_thread_main(int argc, char *argv[]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the correct usage.
|
||||||
|
*/
|
||||||
|
static void usage(const char *reason);
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(const char *reason)
|
||||||
|
{
|
||||||
|
if (reason)
|
||||||
|
fprintf(stderr, "%s\n", reason);
|
||||||
|
|
||||||
|
fprintf(stderr, "usage: segway {start|stop|status} [-p <additional params>]\n\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The deamon app only briefly exists to start
|
||||||
|
* the background job. The stack size assigned in the
|
||||||
|
* Makefile does only apply to this management task.
|
||||||
|
*
|
||||||
|
* The actual stack size should be set in the call
|
||||||
|
* to task_create().
|
||||||
|
*/
|
||||||
|
int segway_main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
if (argc < 1)
|
||||||
|
usage("missing command");
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "start")) {
|
||||||
|
|
||||||
|
if (thread_running) {
|
||||||
|
warnx("already running");
|
||||||
|
/* this is not an error */
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_should_exit = false;
|
||||||
|
|
||||||
|
deamon_task = task_spawn_cmd("segway",
|
||||||
|
SCHED_DEFAULT,
|
||||||
|
SCHED_PRIORITY_MAX - 10,
|
||||||
|
5120,
|
||||||
|
segway_thread_main,
|
||||||
|
(argv) ? (const char **)&argv[2] : (const char **)NULL);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "stop")) {
|
||||||
|
thread_should_exit = true;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "status")) {
|
||||||
|
if (thread_running) {
|
||||||
|
warnx("is running");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
warnx("not started");
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
usage("unrecognized command");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int segway_thread_main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
|
||||||
|
warnx("starting");
|
||||||
|
|
||||||
|
using namespace control;
|
||||||
|
|
||||||
|
BlockSegwayController autopilot;
|
||||||
|
|
||||||
|
thread_running = true;
|
||||||
|
|
||||||
|
while (!thread_should_exit) {
|
||||||
|
autopilot.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
warnx("exiting.");
|
||||||
|
|
||||||
|
thread_running = false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user