Skip to content

Commit

Permalink
Merge pull request #876 from paparazzi/digital_cam_uart
Browse files Browse the repository at this point in the history
Digital cam uart

This module communicates with a linux computer (e.g. beagle board etc) which can then talk to any canon camera supported by chdk
  • Loading branch information
flixr committed Oct 27, 2014
2 parents 8a5729e + 708315e commit b8ca357
Show file tree
Hide file tree
Showing 17 changed files with 1,081 additions and 0 deletions.
44 changes: 44 additions & 0 deletions conf/modules/digital_cam_uart.xml
@@ -0,0 +1,44 @@
<!DOCTYPE module SYSTEM "module.dtd">
<module name="uart_cam_ctrl" dir="digital_cam">
<doc>
<description>
Digital Camera Triggering over UART link.
Send attitude and other relevant data to a computer based photocamera after a shootphoto command is given. And in return get certain value back from the computerbased photocamera to be able to intercat with the flightplan.</description>
<define name="DC_AUTOSHOOT_QUARTERSEC_PERIOD" value="6" description="quarter_second"/>
<define name="DC_AUTOSHOOT_METER_GRID" value="50" description="grid in meters"/>
</doc>
<settings>
<dl_settings name="control">
<dl_settings name="tb">
<dl_setting max="2" min="0" step="1" var="ticket_thumbnails" shortname="thumbs">
<strip_button name="DL Thumbs High" icon="on.png" value="2" group="ticket"/>
<strip_button name="DL Thumbs Low" icon="on.png" value="1" group="ticket"/>
<strip_button name="DL Thumbs STOP" icon="off.png" value="0" group="ticket"/>
</dl_setting>
<dl_setting max="2" min="0" step="1" var="ticket_status" shortname="status" />
</dl_settings>
</dl_settings>
</settings>
<header>
<file name="uart_cam_ctrl.h"/>
</header>
<init fun="digital_cam_uart_init()"/>
<periodic fun="digital_cam_uart_periodic()" freq="4" autorun="TRUE"/>
<event fun="digital_cam_uart_event()"/>
<makefile target="sim">
<file name="catia/serial.c"/>
</makefile>
<makefile>
<define name="DIGITAL_CAM" />
<file name="uart_cam_ctrl.c"/>
<file name="catia/protocol.c"/>
<file name="dc.c"/>
<define name="SENSOR_SYNC_SEND" value="1"/>
<raw>
$(TARGET).CFLAGS += -DCAMERA_LINK=$(CAMERA_PORT)
$(TARGET).CFLAGS += -DUSE_$(CAMERA_PORT)
$(TARGET).CFLAGS += -D$(CAMERA_PORT)_BAUD=B115200
</raw>
</makefile>
</module>

1 change: 1 addition & 0 deletions sw/airborne/modules/digital_cam/catia/.gitignore
@@ -0,0 +1 @@
catia
18 changes: 18 additions & 0 deletions sw/airborne/modules/digital_cam/catia/Makefile
@@ -0,0 +1,18 @@


CFLAGS = -static
LINK = -lpthread
CFILES = serial.c \
chdk_pipe.c \
socket.c \
protocol.c
HFILES = $(CFILES:.c=.h)


all: catia

catia: $(CFILES) $(HFILES) catia.c
gcc $(CFLAGS) $(CFILES) catia.c -o catia $(LINK)

clean:
rm -rf ./catia
5 changes: 5 additions & 0 deletions sw/airborne/modules/digital_cam/catia/README.md
@@ -0,0 +1,5 @@
# CATIA

**C** amera **A** application **T** triggering **I** mage **A** nalysis

Application to capture camera images, store GPS and attitude information, trigger the processing of the image and return the results.
183 changes: 183 additions & 0 deletions sw/airborne/modules/digital_cam/catia/catia.c
@@ -0,0 +1,183 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>

#include "serial.h"
#include "chdk_pipe.h"
#include "protocol.h"

#define MAX_FILENAME 512
#define MAX_PROCESSING_THREADS 8
#define MAX_IMAGE_BUFFERS 25
#define IMAGE_SIZE 70
// Search&Rescue Onboard Detection Application
#define SODA "/root/develop/allthings_obc2014/src/soda/soda"

static void* handle_msg_shoot(void* ptr);
static inline void send_msg_image_buffer(void);
static inline void send_msg_status(void);

static volatile int is_shooting, image_idx, image_count, shooting_idx, shooting_count, shooting_thread_count;
static char image_buffer[MAX_IMAGE_BUFFERS][IMAGE_SIZE];
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;

int main(int argc, char* argv[])
{
pthread_t shooting_threads[MAX_PROCESSING_THREADS];
char c;
int i;

// Initialization
printf("CATIA:\tStarting Camera Application Triggering Image Analysis\n");
chdk_pipe_init();
int ret = serial_init("/dev/ttySAC0");
if (ret < 0) {
printf("CATIA:\tfailed to open /dev/ttySAC0\n");
return -1;
}
pthread_mutex_init(&mut, NULL);
socket_init(1);

// Initial settings
is_shooting = 0;
mora_protocol.status = 0;
image_idx = 0;
image_count = 0;
shooting_idx = 0;
shooting_count = 0;
shooting_thread_count = 0;

// MAIN loop
while (1) {

// Read the serial
if (read(fd, &c, 1) > 0) {
parse_mora(&mora_protocol, c);
} else if (errno != 11) {
printf("CATIA:\nSerial error: %d\n" , errno);
}

// Parse serial commands
if (mora_protocol.msg_received) {
// Process Only Once
mora_protocol.msg_received = FALSE;

// Shoot an image if not busy
if (mora_protocol.msg_id == MORA_SHOOT) {
// Parse the shoot message
union dc_shot_union* shoot = (union dc_shot_union*) malloc(sizeof(union dc_shot_union));
for (i = 0; i < MORA_SHOOT_MSG_SIZE; i++) {
shoot->bin[i] = mora_protocol.payload[i];
}
printf("CATIA:\tSHOT %d,%d\n", shoot->data.nr, shoot->data.phi);

pthread_create(&shooting_threads[(shooting_idx++ % MAX_PROCESSING_THREADS)], NULL, handle_msg_shoot, (void*)shoot);
send_msg_status();
}

// Fill the image buffer (happens busy because needs fd anyway)
if (mora_protocol.msg_id == MORA_BUFFER_EMPTY) {
send_msg_image_buffer();
}
}

// Read the socket
if (socket_recv(image_buffer[image_idx], IMAGE_SIZE) == IMAGE_SIZE) {
image_idx = (image_idx + 1) % MAX_IMAGE_BUFFERS;

if (image_count < MAX_IMAGE_BUFFERS) {
image_count++;
}
}

}

// Close
close(fd);
chdk_pipe_deinit();

printf("CATIA:\tShutdown\n");
return 0;
}

static void* handle_msg_shoot(void* ptr)
{
char filename[MAX_FILENAME], soda_call[512];
union dc_shot_union* shoot = (union dc_shot_union*) ptr;

// Test if can shoot
pthread_mutex_lock(&mut);
if (is_shooting) {
pthread_mutex_unlock(&mut);
printf("CATIA-%d:\tShooting: too fast\n", shoot->data.nr);

free(shoot);
return NULL;
}

is_shooting = 1;
shooting_count++;
shooting_thread_count++;
pthread_mutex_unlock(&mut);

printf("CATIA-%d:\tShooting: start\n", shoot->data.nr);
chdk_pipe_shoot(filename);
printf("CATIA-%d:\tShooting: got image %s\n", shoot->data.nr, filename);

pthread_mutex_lock(&mut);
is_shooting = 0;
pthread_mutex_unlock(&mut);

//Parse the image
sprintf(soda_call, "%s %s %d %d %d %d %d %d %d %d %d %d", SODA, filename,
shoot->data.nr, shoot->data.lat, shoot->data.lon, shoot->data.alt, shoot->data.phi, shoot->data.theta, shoot->data.psi, shoot->data.vground, shoot->data.course, shoot->data.groundalt);
printf("CATIA-%d:\tCalling '%s'\n", shoot->data.nr, soda_call);
short int ret = system(soda_call);
printf("CATIA-%d:\tShooting: soda return %d of image %s\n", shoot->data.nr, ret, filename);

pthread_mutex_lock(&mut);
shooting_thread_count--;
pthread_mutex_unlock(&mut);

free(shoot);
}

static inline void send_msg_image_buffer(void)
{
int i;

// Check if image is available
if (image_count > 0) {
printf("CATIA:\thandle_msg_buffer: Send %d\n", image_idx);
// Send the image
image_idx = (MAX_IMAGE_BUFFERS + image_idx - 1) % MAX_IMAGE_BUFFERS;
image_count--;

MoraHeader(MORA_PAYLOAD, MORA_PAYLOAD_MSG_SIZE);
for (i = 0; i < IMAGE_SIZE; i++) {
MoraPutUint8(image_buffer[image_idx][i]);
}
MoraTrailer();
}
}

static inline void send_msg_status(void)
{
int i;
struct mora_status_struct status_msg;
char* buffer = (char*) &status_msg;

pthread_mutex_lock(&mut);
status_msg.cpu = 0;
status_msg.threads = shooting_thread_count;
status_msg.shots = shooting_count;
status_msg.extra = 0;
pthread_mutex_unlock(&mut);

MoraHeader(MORA_STATUS, MORA_STATUS_MSG_SIZE);
for (i = 0; i < MORA_STATUS_MSG_SIZE; i++) {
MoraPutUint8(buffer[i]);
}
MoraTrailer();
}

0 comments on commit b8ca357

Please sign in to comment.