Skip to content
Snippets Groups Projects
Commit fae32b06 authored by bbartels's avatar bbartels
Browse files

quad: improve virtual quad cli

parent 66942ac7
No related branches found
No related tags found
No related merge requests found
......@@ -16,7 +16,7 @@ Timeout::timeout(30) {
puts("Setting up...")
# Start virtual quad
quad_pid = Process.spawn("./virt-quad -q",
quad_pid = Process.spawn("./virt-quad start -q",
{ :rlimit_as => 536870912, # 512 MiB total RAM
:rlimit_stack => 1048576}) # 1 MiB stack
......@@ -49,7 +49,7 @@ Timeout::timeout(30) {
# Send a debug command
Thread.new {
sleep 0.1
sleep 0.5
send_packet [0xBE, 1, 0, 0, 0, 0, 0, 0xBF]
}
......@@ -58,7 +58,7 @@ Timeout::timeout(30) {
# Receive the header
msg = []
for i in 1..7
sleep 0.0001
sleep 0.01
c = fifo.read(1)
msg.push(c)
end
......@@ -68,7 +68,7 @@ Timeout::timeout(30) {
msg = []
for i in 1..length
sleep 0.0001
sleep 0.01
c = fifo.read(1)
msg.push(c)
end
......
......@@ -16,7 +16,7 @@ Timeout::timeout(30) {
puts("Setting up...")
# Start virtual quad
quad_pid = Process.spawn("./virt-quad -q",
quad_pid = Process.spawn("./virt-quad start -q",
{ :rlimit_as => 536870912, # 512 MiB total RAM
:rlimit_stack => 1048576}) # 1 MiB stack
......@@ -83,7 +83,7 @@ Timeout::timeout(30) {
# Get logs
Thread.new {
sleep 0.5
sleep 1
puts("Swiching off GEAR...")
set_gear GEAR_OFF
}
......
......@@ -14,7 +14,7 @@ Dir.chdir(bin_dir)
puts("Firing up the quad...")
# Start virtual quad
quad = Process.spawn("valgrind --leak-check=full --log-file=./valgrind.out ./virt-quad")
quad = Process.spawn("valgrind --leak-check=full --log-file=./valgrind.out ./virt-quad start")
sleep 1.5
......
......@@ -17,7 +17,7 @@ Timeout::timeout(60) {
puts("Setting up...")
# Start virtual quad
quad_pid = Process.spawn("./virt-quad -q",
quad_pid = Process.spawn("./virt-quad start -q",
{ :rlimit_as => 536870912, # 512 MiB total RAM
:rlimit_stack => 1048576}) # 1 MiB stack
......
......@@ -8,17 +8,18 @@ plethoria of things required for flight in Coover 3050. In fact, you don't
even have to be in Coover 3050...
# Using the Virtual Quad
Start it up:
The virt-quad has help output. Get started with:
```
make run
./virt-quad
```
And you can do things with it. You'll notice it will make a bunch of FIFOs in
the current directory. Write to / read from these FIFOs as you see fit.
## Using the UART Driver
## Writing to FIFO from shell
The UART interface is implemented with unix FIFOs. You can treat these FIFOs
as regular unix files. Read from uart-tx to hear with the quad is saying. Write
to uart-rx to tell the quad something.
```
echo "170000" > virt-quad-fifos/pwm-input-gear # Setting the gear to '1'
cat virt-quad-fifos/pwm-output-motor1 # Read the motor 1 pwm signal
echo "hello world" > virt-quad-fifos/uart-rx
cat virt-quad-fifos/uart-tx
```
\ No newline at end of file
......@@ -4,15 +4,28 @@
#include "quad_app.h"
#include <fcntl.h>
struct VirtQuadIO *virt_quad_io;
int virt_quad_io_file_descriptor;
enum CLISubCommand {
START,
GET,
SET,
USAGE,
HELP,
};
int start_virt_quad(char *argv[]);
int handle_io_output(const char *name);
int handle_io_input(const char *name, const char *value_str);
void set_shm(float value, float *dest, pthread_mutex_t *lock);
void print_shm_float(float *value, pthread_mutex_t *lock);
void print_shm_int(int *value, pthread_mutex_t *lock);
void usage(char *executable_name);
struct VirtQuadIO *virt_quad_io;
int virt_quad_io_file_descriptor;
enum CLISubCommand parse_sub_command(char *argv[]);
void open_new_shm_io();
void open_existing_shm_io();
void help_sub_command(char *argv[]);
/**
* Implement each of the hardware interfaces.
......@@ -33,61 +46,91 @@ int setup_hardware(hardware_t *hardware) {
}
int main(int argc, char *argv[]) {
int fd;
enum CLISubCommand sub_command = parse_sub_command(argv + 1);
switch (sub_command) {
case START:
open_new_shm_io();
start_virt_quad(argv + 2); // will block
break;
case SET:
open_existing_shm_io();
handle_io_input(argv[2], argv[3]);
break;
case GET:
open_existing_shm_io();
handle_io_output(argv[2]);
break;
case HELP:
help_sub_command(argv);
break;
case USAGE:
usage(argv[0]);
break;
}
// Decide if we are launching the quad or parsing arguments
if (argv[1] == NULL || strcmp(argv[1], "-q") == 0) {
// launch the quad
// Allow making the quad quiet
if (argv[1] != NULL && strcmp(argv[1], "-q") == 0) {
fd = open("/dev/null", O_WRONLY);
close(STDOUT_FILENO);
dup2(STDOUT_FILENO, fd);
}
// Prepare the shared memory for io. Clear memory and initialize.
int *fd = &virt_quad_io_file_descriptor;
*fd = shm_open(VIRT_QUAD_SHARED_MEMORY, O_CREAT | O_RDWR | O_TRUNC, 0666);
ftruncate(*fd, sizeof(struct VirtQuadIO));
virt_quad_io = mmap(NULL, sizeof(struct VirtQuadIO), PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&virt_quad_io->led_lock, &attr);
pthread_mutex_init(&virt_quad_io->motors_lock, &attr);
pthread_mutex_init(&virt_quad_io->rc_lock, &attr);
return 0;
}
enum CLISubCommand parse_sub_command(char *argv[]) {
if (argv[0] == NULL) {
return USAGE;
}
else if (strcmp(argv[0], "start") == 0) {
return START;
}
else if (strcmp(argv[0], "help") == 0) {
return HELP;
}
else if (strcmp(argv[0], "get") == 0 && argv[1] != NULL) {
return GET;
}
else if (strcmp(argv[0], "set") == 0 && argv[1] != NULL && argv[2] != NULL) {
return SET;
}
else {
// parse command line arguments
return USAGE;
}
}
// Open exising shared memory for io. DO NOT CLEAR.
int *fd = &virt_quad_io_file_descriptor;
*fd = shm_open(VIRT_QUAD_SHARED_MEMORY, O_CREAT | O_RDWR, 0666);
virt_quad_io = mmap(NULL, sizeof(struct VirtQuadIO), PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
int start_virt_quad(char *argv[]) {
int fd;
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
usage(argv[0]);
exit(0);
}
else if (strcmp(argv[1], "get") == 0 && argv[2] != NULL) {
handle_io_output(argv[2]);
}
else if (strcmp(argv[1], "set") == 0 && argv[2] != NULL && argv[3] != NULL) {
handle_io_input(argv[2], argv[3]);
}
else {
puts("Error in parsing commands");
usage(argv[0]);
}
return 0;
// Allow making the quad quiet
if (argv[0] != NULL && strcmp(argv[0], "-q") == 0) {
fd = open("/dev/null", O_WRONLY);
close(STDOUT_FILENO);
dup2(STDOUT_FILENO, fd);
}
puts("Starting the quad application");
puts("Starting the virtual quad.");
puts("Open another tab to query and control the virt quad, using the get and set commands.");
quad_main(setup_hardware);
return 0;
}
void open_new_shm_io() {
// Prepare the shared memory for io. Clear memory and initialize.
int *fd = &virt_quad_io_file_descriptor;
*fd = shm_open(VIRT_QUAD_SHARED_MEMORY, O_CREAT | O_RDWR | O_TRUNC, 0666);
ftruncate(*fd, sizeof(struct VirtQuadIO));
virt_quad_io = mmap(NULL, sizeof(struct VirtQuadIO), PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&virt_quad_io->led_lock, &attr);
pthread_mutex_init(&virt_quad_io->motors_lock, &attr);
pthread_mutex_init(&virt_quad_io->rc_lock, &attr);
}
void open_existing_shm_io() {
// Open exising shared memory for io. DO NOT CLEAR.
int *fd = &virt_quad_io_file_descriptor;
*fd = shm_open(VIRT_QUAD_SHARED_MEMORY, O_CREAT | O_RDWR, 0666);
virt_quad_io = mmap(NULL, sizeof(struct VirtQuadIO), PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
}
/**
* The user wants to read an output by name. Get the output
* and print to stdout.
......@@ -203,25 +246,79 @@ void print_shm_int(int *value, pthread_mutex_t *lock) {
}
void usage(char *executable_name) {
printf("Usage: %s [ -h | --help | -q ] [ command ]\n", executable_name);
printf("Usage: %s command [ args ]\n", executable_name);
puts("Overview:");
puts(" The virtual quad emulates the behavior of the real quad in the Unix");
puts(" environment. Start the virtual quad in one tab (no arguments), and");
puts(" then control the I/O of the quad through commands.");
puts("");
puts(" For help on a particular command, pass the command name to the help command");
puts(" Example:");
printf(" %s help get\n", executable_name);
puts("");
puts("Commands:");
puts(" get output");
puts(" set input value");
puts("Outpus:");
puts(" led");
puts(" motors");
puts("Inputs:");
puts(" rc_gear");
puts(" rc_flap");
puts(" rc_throttle");
puts(" rc_pitch");
puts(" rc_roll");
puts(" rc_yaw");
puts("Examples:");
printf(" %s get led # prints 0 or 1 to stdout\n", executable_name);
printf(" in%s set rc_gear 1 # sets gear to \"on\" \n", executable_name);
puts(" help");
puts(" get");
puts(" set");
puts(" start");
puts("");
}
void help_sub_command(char *argv[]) {
if (argv[2] == NULL) {
usage(argv[0]);
}
else if (strcmp(argv[2], "help") == 0) {
puts("Really?");
}
else if (strcmp(argv[2], "get") == 0) {
printf("Usage: %s get output_name\n", argv[0]);
puts("");
puts(" Get an output on the virtual quad, specified by its output_name, and print");
puts(" to stdout");
puts("");
puts(" Possible output names");
puts(" led");
puts(" motor1");
puts(" motor2");
puts(" motor3");
puts(" motor4");
puts("");
}
else if (strcmp(argv[2], "set") == 0) {
printf("Usage: %s set input_name val\n", argv[0]);
puts("");
puts(" Set the value of an input on the quad, specified by its input_name");
puts("");
puts(" Possible input names");
puts(" rc_throttle");
puts(" rc_pitch");
puts(" rc_roll");
puts(" rc_yaw");
puts(" rc_gear");
puts(" rc_flap");
puts(" i2c_imu_x");
puts(" i2c_imu_y");
puts(" i2c_imu_z");
puts(" i2c_imu_p");
puts(" i2c_imu_q");
puts(" i2c_imu_r");
puts(" i2c_imu_mag_x");
puts(" i2c_imu_mag_y");
puts(" i2c_imu_mag_z");
puts("");
}
else if (strcmp(argv[2], "start") == 0) {
printf("Usage: %s start [ -q ]\n", argv[0]);
puts("");
puts(" Start the virtual quad. Exit using ctrl-c. In order to get and set I/O,");
puts(" you'll need to open another tab.");
puts("");
puts(" Flags");
puts(" q - Keep the quad quiet; don't print logs to the stdout");
puts("");
}
else {
usage(argv[0]);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment