AYUDA GoPro HD + Ardupilot Mega = Fotos en cada waypoint georreferenciadas!

Tema en 'R/C TELEMETRÍA y UAV PROYECTOS' iniciado por boby, 13 Nov 2011.

  1. boby Miembro

    boby
    Registrado:
    12 May 2009
    Mensajes:
    115
    Me Gusta recibidos:
    0
    Hola a todos,

    Llevo algún tiempo mirando cómo poder conectar mi Go Pro HD al relay (relé) del Ardupilot Mega y finalmente lo conseguí a través de este post:

    http://benlo.com/msp430/GoProController.html

    Ahora mi problema es el siguiente: Quiero hacer este algoritmo con la función millis() que tiene arduino, ya que la función delay() crea una larga parada en el desarrollo de los procesos del APM. La idea es que la GoPro HD tome una foto cuando el avión pase por los puntos (waypoints) de cada misión.
    El esquema sería el siguiente:

    / / Cuando se alcance cada waypoint de la misión:
    / / Necesito encender la cámara (lo mismo que presionar dos segundos el botón de encendido)
    relay_on ();
    delay (2000);
    relay_off ();
    / / La cámara toma una foto (GoPro HD en modo "one button mode")
    delay (2500);
    / / Necesito apagar la cámara (lo mismo que presionar 3 segundos el botón de encendido)
    relay_on ();
    delay (3000);
    relay_off;

    Con esta función y el GPS_LOG en "ENABLE" podemos comparar el tiempo (hora) en el que se alcanza un waypoint y la fecha impresa por la GoPro HD en la foto para georreferenciar nuestras fotos con este software:

    http://code.google.com/p/gpicsync

    Nunca había usado antes la función millis() ya que los tiempos de espera que siempre he usado son unos pocos milisegundos.

    Este esquema usando la función delay va bien:


    static void take_picture()
    {
    relay_on();
    delay(2000);
    relay_off();
    delay(2500);
    relay_on();
    delay(3000);
    relay_off();
    }


    Pero claro, cuando se ejecuta este sketch el Ardupilot se tira varios segundos en espera sin más que hacer que contar segundos. Y ello conlleva lo evidente...castaña al canto...

    En la simulación con Xplane esto funciona pero esos 6,5 segundos que el Ardupilot se tira esperando llevan al avión al desastre...

    A ver si me podéis hechar una mano con esto que me está llevando por la calle de la amargura..., creo que es porque la función millis() sólo se puede ejecutar dentro del void loop() y no como una función static void (estática).

    Os dejo una foto de mi GoPro HD conectada al Ardupilot Mega:

    [​IMG]


    Saludos desde León,
    Darío
     
  2. guaglianoneott Nuevo Miembro

    guaglianoneott
    Registrado:
    26 Ene 2012
    Mensajes:
    6
    Me Gusta recibidos:
    0
    Estimado amigo como conectaste la camara go pro a la placa ardu pilot, necesito saber la ubicacion de los conectores en la ficha que va en la camara, con dos cables y esos dos cables en que ubicacion los conecto en la camara.
    Gracias
     
  3. ASRASR Gurú FPV

    ASRASR
    Registrado:
    30 May 2008
    Mensajes:
    3.659
    Me Gusta recibidos:
    0
    Boby nosotros estuvimos haciendo pruebas con la funcion one button y ardupilot pero tuvimos muchos problemas hasta desentimarlo pq entre el tiempo de recuperacion de la camara mas encendido apagado y demas pasaba un tiempo excesivo. Ahora hacemos fotos cada 2s y contrastamos tiempos y posiciones para la georeferenciacion. De todas formas habla con Scastillo1117 q es nuestro experto en arduopilot.
     
  4. boby Miembro

    boby
    Registrado:
    12 May 2009
    Mensajes:
    115
    Me Gusta recibidos:
    0
    Hola a todos,

    @guaglianoneott: El conector es el mismo que el del Iphone, en el primer post tienes el enlace a la página de donde saqué la información. También tienes un código en C++ que sirve como referencia. Está en inglés, pero se entiende muy bien.

    @asrasr: Si, yo también tenía el problema del tiempo, así que lo que hago ahora es ejecutar dos acciones, cada una con un relé independiente. Un relé enciende la cámara cuando el sistema es alimentado. El otro relé, el del Ardupilot, lo único que hace es tirar fotos. Así se realiza una foto por cada waypoint que hemos marcado, grabando además un evento en el LOG que muestra las coordenadas en las que fue realizada (cuando se activa el relé, se indica el número de foto y las coordenadas).

    Al final para estos menesteres he cambiado la Go Pro HD por una cámara construida por mí con autoestabilización y autoalimentada, que aunque no tiene mucha resolución y calidad (3,2 mpx 45º FOV) sólo pesa 32g y tiene justo la mitad del tamaño de la Go Pro HD.

    Podéis verla aquí:
    http://www.aeromodelismovirtual.com/showthread.php?t=14574

    Saludos a todos,
    Darío.
     
  5. scastillop1117 Nuevo Miembro

    scastillop1117
    Registrado:
    20 Oct 2010
    Mensajes:
    72
    Me Gusta recibidos:
    0

    Hola Boby,

    Como te ha dicho asrasr, nosotros también hemos georeferenciado las fotos hechas por arduino.

    Viendo tu codigo, cuando usas la función delay haces que ardupilot deje de ejecutar el código, se quede parado durante todo el tiempo que pones en la función, haces una parada síncrona. Tienes que hacer que el código sea más asíncrono. Lo idea sería hacerlo por multithreads, pero claro, arduino no soporta nada de esto.

    La función principal de ardupilot hace llamadas a varias subfunciones, unas se ejecutan con más frecuencia, otras con menos, etc. No debes hacer paradas, lo que tienes que hacer en cada ejecución de APM comprobar en qué estado se encuentra la cámara, y en función de esto actuar sobre el relay; en otras palabras, en vez de realizar paradas, tienes que definir estados en los que estás un determinado tiempo, tras el cual pasas a otro estado.

    Lo que yo hice fue más o menos esto:

    Una clase, que denominé APM_GoPro, que representa a la gopro, y esta clase es la que hace todo lo que tenga que ver con la gopro. Así, aislo el funcionamiento de la gopro del código original de APM lo más posible.

    Un atributo de la clase representa el estado de la cámara: apagada, encendiéndose, apagandose, encendida. Dentro de la clase, defino los tiempos como constantes, de manera que si pones otra version en la que los tiempos son diferentes, solo tienes que tocar en la clase.

    En el programa principal del ardupilot, cuando quiero encender la cámara, hago una llamada a una funcion de la clase. Esta funcion comprueba que la variable de estado toma el valor apagada, de lo contrario se sale. Hay otra funcion en el programa principal que se ejecuta siempre y veremos más adelante.

    En caso de que el valor de la variable sea apagada, cambia el valor de la variable a encendiendose, y continua la ejecución.

    Ahora hablaremos de la función que se ejecuta siempre en el programa principal, que te mencioné antes. Esta función no hac emás que lo suguiente: comprueba si el estado de la camara es diferente a apagada. En caso de que sea así, comprueba si ha pasado el tiempo necesario para pasar al siguiente estado, y en caso afirmativo, actua sobre el relay y cambia el valor de la variable estado, y continua la ejecución.

    Te lo he descrito muy muy resumido para que te hagas una idea, ya que al final nosotros no usamos este código, merece la pena hacerlo con otro enfoque, porque necesitamos tomar fotos cada 2 segundos como mínimo, y de esta forma el tiempo entre foto y foto es demasiado elevado (unos 8 segundos).

    Además, no controlas completamente cuándo se ha terminado de tomar la foto: ¿Cuando la cámara se está encendiendo, cuando se está apagando, justo cuando han pasado los 2 seg o cuando han pasado los 2.5 posteriores? Imagina que enciendes la cámara, esperas 2 segundos, y cuando pasan otros 2.5 es cuando has terminado de tomar la foto y ese es el EXIF: entonces tendrás que empezar el proceso antes de que el avión llegue al WP, y estimar cuándo debes empezar para que tras 4.5 el avión esté encima del WP, no sé si me explico.

    Otra segundo enfoque más práctico es dejar que la gopro tome fotos contínuamente, a la vez que enviamos la salida live por video inalámbrico, con la información georeferenciada incrustada en el video a través del OSD. Esto generará un montón de datos, y luego deberás saber cuáles tienes que descartar, pero merece la pena.

    Una vez en casa, tomas un frame del video, localizas de todas las fotos de la tarjeta de la gopro con cuál se corresponde. Una vez tengas el frame y la foto, busca en el log de telemetria la línea que tengas las coordenadas que te salen en el frame, y su t asociado.

    Después, tomas la información EXIF de la foto, y calculas el desfase temporal entre ese t y el EXIF de la foto. Después, para cada foto buscas en el log su linea asociada usando el desfase temporal.

    Una vez acabes, ya tienes todas las fotos georeferenciadas. Ahora, tomando todas estas fotos, y los puntos en los que debes haber hecho fotos, calculas qué fotos son las que están más cerca de esos puntos, y ya está. La práctica nos demuestra que haciendo que el avión siga los WPs que te den, y la cámara continuamente haciendo fotos, prácticamente siempre hace una en el WP que te piden. Es más, nosotros damos 2 ó 3 pasadas para asegurarnos que ocurra así, y por si alguna foto sale movida, o el avión está inclinado, etc.

    En caso de que el tiempo entre foto y foto puedas ser mayor de 10 segundos, se podría hacer como tu dices, lo malo es que si por cualquier motivo una foto sale mal, tendrás que volver a repetir el vuelo. Nosotros, como tomamos un montón de fotos, si sale alguna mal, siempre hay otra que puede servirnos, podemos descartar automáticamente aquellas en las que la actitud del avión no estaba dentro de unos límites impuestos (es decir, buscar las que sean más cenitales), o aquellas en las que iba muy rápido, etc.

    La idea es generar tantos datos como sea posible estando en el campo, ya que este es el trabajo "pesado" y que más tiempo lleva, ir al campo (en nuestro caso, el 80% del tiempo es en el campo y el 20% es trabajo posterior de "gabinete"); ya que vas, merece la pena repetir vuelos, tomar montones y montones de fotos, volar a diferentes horas del día para probar distintos tipos de iluminación, en ontras palabras, ya que has encontrado un día con buena meteorología, sin viento, no llueve, y vas a invertir un mínimo de medio día (al menos en nuestro caso), interesa estar 1 ó 2 horas más y asegurarte que no tendrás que volver a repetir nada. Luego en casa usamos un software que hemos desarrollado para ver con qué subconjunto de fotos nos interesa trabajar, y el descarte se produce de forma automática.
     
  6. boby Miembro

    boby
    Registrado:
    12 May 2009
    Mensajes:
    115
    Me Gusta recibidos:
    0
    Hola scastillop1117,

    Muchas gracias por tu respuesta y comentarios, me ha servido para confirmar que voy por buen camino. No sabía muy bien cómo solucionar el problema del tiempo ya que desconocía las posibilidades de ciertas subrutinas y funciones de arduino como la función millis() y la microseconds(). Después de esto, tal y como me comentas, cree una subrutina dentro de la función void_loop() y las pertinentes funciones y declaraciones de variables. Así conseguí hacer lo que me proponía sin ejecutar la función relay (con lo que ello conlleva).

    Lo que sí he observado (no sé si a vosotros os pasa) es que cuando se ejecuta la función relay_on(); o relay_off(); se produce una gran carga de cpu y parte de la cadena de funciones que se ejecutan en el medium_loop se colapsan (por ejemplo la anotación del LOG que empleo para georreferenciar las imágenes). Ahora estoy mirando las librerías del Ardupilot porque me parece que el MAVLINK está constantemente comprobando si el relé está encendido o apagado y cuando se ejecuta la función que he escrito se colapasan la una con la otra.

    Gracias por tomarte un tiempo en atender mis dudas. A ver si algún día tengo la suerte de conoceros en persona (con algunos ya he tenido el placer de charlar un rato).

    Saludos desde León,
    Darío.
     
  7. scastillop1117 Nuevo Miembro

    scastillop1117
    Registrado:
    20 Oct 2010
    Mensajes:
    72
    Me Gusta recibidos:
    0
    Hola Boby,

    De nada hombre. En cuanto al colapso del que hablas, a nosotros no nos pasa eso. También te digo que no trabajamos con la última versión del ardupilot, y no controlamos el relay con la función que comentas, sino con
    PORTL |= B00000100; y
    PORTL ^= B00000100;

    como viene en
    http://code.google.com/p/ardupilot-mega/wiki/Relay

    Tampoco usamos el protocolo MAVLINK, más que nada por el tema
    del duty cycle del xbee: hemos añadido varias funciones propias
    al ardupilot (plataforma autoestabilizadora de la cámara,
    seguimiento automático de un punto geográfico, añadir
    temperatura y presión en el fichero de telemetría, etc); Gran parte de estas nuevas funciones las controlamos en tiempo
    real con el avión en vuelo, y procuramos que el tráfico
    avion-ordenador sea lo más simple y corto posible, por lo que necesitamos saltarnos algunos campos/flags que usa MAVLINK; no estoy muy contento con esto, pero ahora hay otras cosas prioritarias que arreglar, más adelante veremos como solucionar esto.

    Es posible que en el futuro pasemos de ardupilot-xbee a otro
    sistema más robusto, potente y estable.

    Pues sí, igualmente, a ver si coincidimos en algún momento!
     
  8. scastillop1117 Nuevo Miembro

    scastillop1117
    Registrado:
    20 Oct 2010
    Mensajes:
    72
    Me Gusta recibidos:
    0
    He visto tu proyecto de 4 años, está muy interesante!

    Nosotros también trabajamos con algo parecido. Hemos desarrollado sotfware para hacer que la cámara siga un punto continuamente:

    http://www.aeromodelismovirtual.com/showpost.php?p=175022&postcount=36

    y estabilización de camara por software para que sea cenital continuamente:

    http://www.youtube.com/watch?feature=endscreen&NR=1&v=9mtXJ7DID28
     
  9. devta Nuevo Miembro

    devta
    Registrado:
    18 Feb 2012
    Mensajes:
    1
    Me Gusta recibidos:
    0
    Control por tiempo de un relay (relé)

    Bueno, me presento en el foro, mi nombre es Devta, soy nuevo, y todavía no he volado, pero estoy haciendo experimentos con arduino.

    Respondo al mensaje para ver si ayuda.

    Cuando Arduino ejecuta la instrucción delay(1000) espera un segundo, pero todo lo demás se queda detenido. Es decir no hace nada más.

    Deberíasmo evitar esto, y para ello podemos usar la funcion loop() y ahí controlar el valor de una variable que podemos establecer e ir comprobando.

    La secuencia sería:
    Al recibir la orde de tomar foto
    Tomamos el número de milisegundos con millis() y lo almacenamos en una variable que hemos establecido en el setup

    Luego en loop echamos un vistazo a los milisegundos y seguimso haciendo lo que haya que hacer (resto del código) pero cuando la resta de los milisegundos del tiempo actual y de los que almacenamos al inicio sea mayor de 1000 o 3000 o lo que establezcamos, cambiamos el estado de ese pinout del arduino / ardupilot

    de esa forma no tenemos tanta exactitud en el tiempo que esperamos, pero podemos seguir haciendo cosas.

    Yo lo estoy usando en las pruebas para una impresora 3D y al menos los motores paso a paso que controlo reaccionan bien.
    Le digo, muevelo 2000 pasos, y los va contando, hasta que llega, miesntras tanto puedo hacer otras cosas.

    En este caso no me importa tanto la duración como el número de pasos del motor.

    Espero que sirva, si necesitas algo más específico, lo codifico...

    Un saludo a todos.
     

Compartir esta página