[#CODING4FUN] #LegoEV3 controlled with #LeapMotion

Hello!

Probably this is the correct time to publish this… Winking smile

A small review of the video time line

  • 00: 03, visualization of the hand in the Leap Visualizer. There is a little delay by recording with Camtasia. I should possibly try another burning software that does not interfere.
  • 00: 09, change the focus to the app to control LEGO EV3 with Leap Motion.
  • 00: 20, the movements of the hand are reflected in the control box. In addition to the basic positions, there is a “Far” mode that moves the LEGO with a little more than speed. In this second option RightFar can be
  • 00: 27, click on the button to connect the Lego. Once connected the State appears in the StatusBar.
  • 00: 34, the gesture of the hand indicates that you move LEGO EV3 forward. The feed from the webcam shows the Lego table.
  • 00: 40, the gesture of the hand now indicates a right turn.
  • 00: 45, the gesture of the hand now indicates a shift to the left.
  • 00: 45, the gesture of the hand now indicates that you move LEGO EV3 backwards.
  • 00: 55, end of the video (before that the lego table tipping).

I have stopped the firing of missiles for another shot because the detail is not noticed.

Saludos @ Home

El Bruno

image image image Google

[#CODING4FUN] Lego EV3 controlled with Leap Motion

Hola!

Mira la hora en la que me acuerdo de publicar esto … Winking smile

Un pequeño repaso del script

  • 00:03, visualización de la mano en el Leap Visualizer. Hay un poco de delay por la grabación con Camtasia. Posiblemente debo probar otro software de grabación que no interfiera.
  • 00:09, cambio el foco a la app para controlar el LEGO EV3 con Leap Motion.
  • 00:20, los movimientos de la mano se reflejan en el cuadro de control. Además de las posiciones basicas hay un modo “Far” que mueve al Lego con un poco más de velocidad. En este segundo se puede ver la opción RightFar
  • 00:27, click al button para connectar el Lego. Una vez conectado aparece el estado en la StatusBar.
  • 00:34, el gesto de la mano indica que se mueva el LEGO EV3 hacia adelante. En el feed de la webcam se puede ver el Lego en la mesa.
  • 00:40, el gesto de la mano ahora indica un giro a la derecha.
  • 00:45, el gesto de la mano ahora indica un giro a la izquierda.
  • 00:45, el gesto de la mano ahora indica que se mueva el LEGO EV3 hacia atrás.
  • 00:55, fin del video (antes que se caiga el lego de la mesa).

El disparo de los misiles lo he dejado para otra oportunidad porque no se nota el detalle.

Saludos @ Home

El Bruno

image image image Google

[#LEAPMOTION] HowTo: Show the number of fingers ever the Leap

Hello!

Today is going to be a quick post, I’ll change the console app for a WPF app to work with the Leap Motion. In this app, I’ll show how a gesture is detected by the sensor in addition to the amount of active fingers over the sensor. For this example I’ve used some information from in this post of the great Iris Classon to create the following listener

   1: using System;

   2: using System.Threading.Tasks;

   3: using Leap;

   4:  

   5: namespace LeapWpf01

   6: {

   7:     public class ElBrunoListener : Listener

   8:     {

   9:         public void Sample(){}

  10:         public event Action<FingerList> OnFingersRegistered;

  11:         public event Action<GestureList> OnGestureMade;

  12:         private long _now;

  13:         private long _previous;

  14:         private long _timeDifference;

  15:  

  16:         public override void OnInit(Controller controller) { }

  17:  

  18:         public override void OnConnect(Controller controller)

  19:         {

  20:             controller.EnableGesture(Gesture.GestureType.TYPECIRCLE);

  21:             controller.EnableGesture(Gesture.GestureType.TYPEKEYTAP);

  22:             controller.EnableGesture(Gesture.GestureType.TYPESCREENTAP);

  23:             controller.EnableGesture(Gesture.GestureType.TYPESWIPE);

  24:         }

  25:  

  26:         public override void OnDisconnect(Controller controller) { }

  27:  

  28:         public override void OnExit(Controller controller) { }

  29:  

  30:         public override void OnFrame(Controller controller)

  31:         {

  32:             var frame = controller.Frame();

  33:             _now = frame.Timestamp;

  34:             _timeDifference = _now - _previous;

  35:  

  36:             if (frame.Hands.IsEmpty) return;

  37:  

  38:             _previous = frame.Timestamp;

  39:             if (_timeDifference < 1000) return;

  40:  

  41:             // Run async

  42:             if (frame.Gestures().Count > 0)

  43:                 Task.Factory.StartNew(() => OnGestureMade(frame.Gestures()));

  44:             if (frame.Fingers.Count > 0)

  45:                 Task.Factory.StartNew(() => OnFingersRegistered(frame.Fingers));

  46:         }

  47:     }

  48: }

The listener is quite simple, public an event with the information captured by the LEAP every 1 second.

In the MainWindow of my WPF app, I have the following code. The only thing that must be taken into consideration, is that the best sensor initialization in the Loaded() event, and always with care for closing the View close the controller and the listener with the sensor.

   1: using System;

   2: using System.ComponentModel;

   3: using System.Diagnostics;

   4: using System.Runtime.CompilerServices;

   5: using System.Windows;

   6: using Leap;

   7: using LeapWpf01.Annotations;

   8:  

   9: namespace LeapWpf01

  10: {

  11:     public partial class MainWindow : INotifyPropertyChanged

  12:     {

  13:         private string _gesturesText;

  14:         private Controller _controller;

  15:         private ElBrunoListener _listener;

  16:         private string _fingersText;

  17:  

  18:         public MainWindow()

  19:         {

  20:             DataContext = this;

  21:             Loaded += MainWindow_Loaded;

  22:             Closing += MainWindow_Closing;

  23:             InitializeComponent();

  24:         }

  25:  

  26:         void MainWindow_Closing(object sender, CancelEventArgs e)

  27:         {

  28:             _controller.RemoveListener(_listener);

  29:             _controller.Dispose();

  30:         }

  31:  

  32:         void MainWindow_Loaded(object sender, RoutedEventArgs e)

  33:         {

  34:             _listener = new ElBrunoListener();

  35:             _controller = new Controller();

  36:             _controller.AddListener(_listener);

  37:             _listener.OnFingersRegistered += OnFingersRegistered;

  38:             _listener.OnGestureMade += OnGestureMade;

  39:         }

  40:  

  41:         void OnGestureMade(GestureList gestures)

  42:         {

  43:             var gesturesData = string.Empty;

  44:             foreach (var gesture in gestures)

  45:             {

  46:                 gesturesData += gesture.Type + Environment.NewLine;

  47:             }

  48:             GesturesText = gesturesData;

  49:         }

  50:  

  51:         void OnFingersRegistered(FingerList fingers)

  52:         {

  53:             FingersText = "Active Fingers:" + fingers.Count;

  54:         }

  55:     }

  56: }

Then, the functionality of the app is pretty straigh forward,

 

The sensor is OK, but in order to have something up and running, you have to work a lot. The SDK gives you raw information , so you have to work with this information to get cool results

Saludos @ Home

El Bruno

image image image Google

[#LEAPMOTION] HowTo: Mostrar la cantidad de dedos sobre el Leap

Hola!

Hoy vamos con un post de esos rápidos, en el que cambio una app de Consola por una app WPF y en la misma, muestro el gesto detectado por el sensor además de la cantidad de dedos activos. Para este ejemplo me he basado en este post de la crack Iris Classon para crear el siguiente listener

   1: using System;

   2: using System.Threading.Tasks;

   3: using Leap;

   4:  

   5: namespace LeapWpf01

   6: {

   7:     public class ElBrunoListener : Listener

   8:     {

   9:         public void Sample(){}

  10:         public event Action<FingerList> OnFingersRegistered;

  11:         public event Action<GestureList> OnGestureMade;

  12:         private long _now;

  13:         private long _previous;

  14:         private long _timeDifference;

  15:  

  16:         public override void OnInit(Controller controller) { }

  17:  

  18:         public override void OnConnect(Controller controller)

  19:         {

  20:             controller.EnableGesture(Gesture.GestureType.TYPECIRCLE);

  21:             controller.EnableGesture(Gesture.GestureType.TYPEKEYTAP);

  22:             controller.EnableGesture(Gesture.GestureType.TYPESCREENTAP);

  23:             controller.EnableGesture(Gesture.GestureType.TYPESWIPE);

  24:         }

  25:  

  26:         public override void OnDisconnect(Controller controller) { }

  27:  

  28:         public override void OnExit(Controller controller) { }

  29:  

  30:         public override void OnFrame(Controller controller)

  31:         {

  32:             var frame = controller.Frame();

  33:             _now = frame.Timestamp;

  34:             _timeDifference = _now - _previous;

  35:  

  36:             if (frame.Hands.IsEmpty) return;

  37:  

  38:             _previous = frame.Timestamp;

  39:             if (_timeDifference < 1000) return;

  40:  

  41:             // Run async

  42:             if (frame.Gestures().Count > 0)

  43:                 Task.Factory.StartNew(() => OnGestureMade(frame.Gestures()));

  44:             if (frame.Fingers.Count > 0)

  45:                 Task.Factory.StartNew(() => OnFingersRegistered(frame.Fingers));

  46:         }

  47:     }

  48: }

El listener es bastante simple, publica en modo evento toda la información capturada por el LEAP cada 1 segundo.

Luego en la MainWindow de mi app WPF poseo el código del siguiente párrafo. Lo único que hay que tener en cuenta en este caso, es que en la inicialización del sensor mejor hacerla en el evento Loaded(), y siempre con cuidado en el closing de la View de cerrar el controller y el listener con el sensor.

   1: public partial class MainWindow : INotifyPropertyChanged

   2: {

   3:     private string _gesturesText;

   4:     private Controller _controller;

   5:     private ElBrunoListener _listener;

   6:     private string _fingersText;

   7:  

   8:     public MainWindow()

   9:     {

  10:         DataContext = this;

  11:         Loaded += MainWindow_Loaded;

  12:         Closing += MainWindow_Closing;

  13:         InitializeComponent();

  14:     }

  15:  

  16:     void MainWindow_Closing(object sender, CancelEventArgs e)

  17:     {

  18:         _controller.RemoveListener(_listener);

  19:         _controller.Dispose();

  20:     }

  21:  

  22:     void MainWindow_Loaded(object sender, RoutedEventArgs e)

  23:     {

  24:         _listener = new ElBrunoListener();

  25:         _controller = new Controller();

  26:         _controller.AddListener(_listener);

  27:         _listener.OnFingersRegistered += OnFingersRegistered;

  28:         _listener.OnGestureMade += OnGestureMade;

  29:     }

  30:  

  31:     void OnGestureMade(GestureList gestures)

  32:     {

  33:         var gesturesData = string.Empty;

  34:         foreach (var gesture in gestures)

  35:         {

  36:             gesturesData += gesture.Type + Environment.NewLine;

  37:         }

  38:         GesturesText = gesturesData;

  39:     }

  40:  

  41:     void OnFingersRegistered(FingerList fingers)

  42:     {

  43:         FingersText = "Active Fingers:" + fingers.Count;

  44:     }

  45: }

Luego, la funcionalidad de la app es bastante straigh forward,

 

La verdad es que como sensor está bien, ahora para poder tener algo up and running, hay que trabajar bastante. No por las capacidades, sino más bien porque el SDK te deja TODA la información en bruto, lo demás … pues a trabajarserlo

Saludos @ Home

El Bruno

image image image Google

[#MICROSOFT] Empowering us (amazing way to tell how we can use new technologies!)

Hello!

After the Super Bowl and the brand-new new CEO of Microsoft, today my office with a great video presented Sunday, and also behind the stories that accompany it

I recommend to see the detail of each story, they are impressive.

Source: http://msft.it/Empowering

Greetings @ Home

El Bruno

imageimageimageGoogle

[#MICROSOFT] Empowering us (impresionante forma de presentar como podemos usar las new technologies!)

Hola!

Después del Super Bowl y del flamante nuevo CEO de Microsoft, hoy me despacho con un video genial presentado el domingo, y además detrás las historias que lo acompañan

Recomiendo ver el detalle de cada historia, son impresionantes.

Fuente: http://msft.it/Empowering

Saludos @ Home

El Bruno

image image image Google

[#LEAP] Welcome Leap Motion! (think in axis now > XYZ!)

Hello!

People usually say that someone is mature enough when you start to be more concerned by the nobey to be spend in the dentist rather the minutes of pain and suffering. In our profession mature usually is associated to set aside the lines of code and start doing more management tasks. To many people this seems an aberration, when in reality don’t realize that it is an excellent opportunity to work with friends, learn on how to work as a team and try to have a good time with one common goal. This is team management Winking smile

Well, when you spend traveling from here to there, and you don’t open Visual Studio in a week, you have to get back the lost time in the weekend (also with family and friends!). Why is that today, already with several ideas and personal projects in my head, I start with a new one: Leap Motion time.

image

The truth is that the device is €99 , but personally I think it worth more than this amout: is a great device!. I will not explain what does the Leap do, thinks in Minority Report, or better to watch this video of Engadget.

I what I will do is to download the SDK and then:

1 Open Visual Studio 2013

2. Create a console application

3. Add the following references to the application

  • \LeapDeveloperKit\LeapSDK\lib\LeapCSharp.NET4.0.dll

4 I can now start to put some code to see the really power of the Leap Motion sensor! As always with these devices, I have to configure the app to be compiled for a specific target, in this case X86.

image

5, In the Main add the following code and already have something running. In this section, what we do is create a listener for events that Leap Motion sends and initialize it with a Controller.

   1: using System;

   2: using Leap;

   3:  

   4: namespace LeapConsole1

   5: {

   6:     class Program

   7:     {

   8:         static void Main(string[] args)

   9:         {

  10:             var listener = new ElBrunoListener();

  11:             var controller = new Controller();

  12:             controller.AddListener(listener);

  13:             Console.WriteLine("Press Enter to quit...");

  14:             Console.ReadLine();

  15:             controller.RemoveListener(listener);

  16:             controller.Dispose();

  17:         }

  18:     }

  19: }

6. The ElBrunoListener class has a little more code, since it is that is responsible for processing information that sends us the Leap. We see that you have inside

   1: using System;

   2: using System.Linq;

   3: using Leap;

   4:  

   5: namespace LeapConsole1

   6: {

   7:     class ElBrunoListener : Listener

   8:     {

   9:         private readonly Object _thisLock = new Object();

  10:  

  11:         private void SafeWriteLine(String line)

  12:         {

  13:             lock (_thisLock)

  14:             {

  15:                 Console.WriteLine(line);

  16:             }

  17:         }

  18:  

  19:         public override void OnInit(Controller controller)

  20:         {

  21:             SafeWriteLine("Initialized");

  22:         }

  23:  

  24:         public override void OnConnect(Controller controller)

  25:         {

  26:             SafeWriteLine("Connected");

  27:             controller.EnableGesture(Gesture.GestureType.TYPESWIPE);

  28:         }

  29:  

  30:         public override void OnDisconnect(Controller controller)

  31:         {

  32:             SafeWriteLine("Disconnected");

  33:         }

  34:  

  35:         public override void OnExit(Controller controller)

  36:         {

  37:             SafeWriteLine("Exited");

  38:         }

  39:  

  40:         public override void OnFrame(Controller controller)

  41:         {

  42:             var frame = controller.Frame();

  43:             var gestures = frame.Gestures();

  44:             foreach (var swipe in from gesture in gestures where gesture.Type == Gesture.GestureType.TYPESWIPE select new SwipeGesture(gesture))

  45:             {

  46:                 var gestureName = GetGestureNameFromSwipe(swipe);

  47:                 SafeWriteLine(string.Format("Swipe id: {0}, name: {1}", swipe.Id, gestureName));

  48:                 break;

  49:             }

  50:         }

  51:  

  52:         private string GetGestureNameFromSwipe(SwipeGesture swipe)

  53:         {

  54:             var gestureName = "undefined";

  55:             var direction = swipe.Direction;

  56:             if (direction.Yaw > 0)

  57:             {

  58:                 gestureName = "left to right";

  59:             }

  60:             if (direction.Yaw < 0)

  61:             {

  62:                 gestureName = "right to left";

  63:             }

  64:             return gestureName;

  65:         }

  66:     }

  67: }

7. In the first place, we can see that we can do an override of OnInit, OnConnect, OnDisconnect and OnExit to initialize the sensor. In this case, I just want that the sensor registers the SWIPE gesture.

8 Then the OnFrame method, we can process the information that returns us a FRAME. The truth is that it is impressive what has this object. In this example, we access the collection of gestures and in it, we get SWYPE type.

9. Then we have to process all the information from this SWIPE. On the one hand we know that it is a SWIPE, but we need to find out the direction of the same. To do this, I’ll work with the SwipeGesture object and I’ll try to identify if the swipe has been left to right processing the Direction property.

image

Note: Direction is a vector. A vector has a lot of information, such as the start position and end, always associated with the axes, X, and y Z. With this information and thinking of the vector in the 3 axes, we could identify swipes from left to right, top to bottom, bottom-left, etc.

In this case, and to summarize much we can do with the LEAP, I’ve decided to process the YAW property. It gives us an integer value with the difference in angles from the negative Z axis and the positive X axis.

api/../../../images/Math_Yaw_Angle.png

Thus if the angle is greater that 90 degrees will be a SWIPE LEFT TO RIGHT and if it is less than 90 degrees is a RIGHT TO LEFT SWIPE.

Note: This always thinking that you’re not Terminator and make gestures of swipe in a direction straight unchanged.

10 As well, now already we can launch the app and see how the console shows the gestures that we are doing on the Leap Motion!

By the way, I will have to get some Google Glases or a sports camera because the film stock in 1st person with the mobile phone… because it is not well Open-mouthed smile

Greetings @ Home

El Bruno

imageimageimageGoogle

[#LEAP] Welcome Leap Motion !!! (empezando a pensar en XYZ!)

Hola!

Dicen que madurar es preocuparse más por lo que te va a cobrar el dentista que por los minutos de dolor y sufrimiento. En nuestra profesión madurar se asocia a dejar de lado las líneas de código y comenzar a hacer tareas más de gestión. A muchas personas esto les parece una aberracion, cuando en realidad no se dan cuenta de que es una excelente oportunidad para poder programar con amigos, trabajar en equipo e intentar pasar un buen rato con un objetivo en común entre varios. Esto es gestión de equipos Winking smile

Ahora bien, cuando te pasas viajando de aqui y no abres el Visual Studio en una semana, pues te queda el mono para el fin de semana. Por eso es que hoy, ya con varias ideas en la cabeza, me pongo de lleno con el juguetito nuevo de estos días: un Leap Motion.

image

La verdad es que por los €99 que cuesta, vale la pena con creces. No me voy a enrollar explicando lo que hace, piensa en Minority Report, o mejor mira este video de Engadget.

Yo lo que haré es descargar el SDK y después:

1. Abrir Visual Studio 2013

2. Crear una applicación de consola

3. Agregar las siguientes referencias a la applicación

  • \LeapDeveloperKit\LeapSDK\lib\LeapCSharp.NET4.0.dll

4. Listo! ya puedo empezar a meter código para ver que nos da el Leap Motion! Antes como siempre con estos devices, tengo que configurar la app para que se compile para un target específico, en este caso X86.

image

5,  En el Main agrego el siguiente código y ya tebgo algo funcionando. En esta sección, lo que hacemos es crear un listener para los eventos que envía el Leap Motion e inicializarlo con un Controller.

   1: using System;

   2: using Leap;

   3:  

   4: namespace LeapConsole1

   5: {

   6:     class Program

   7:     {

   8:         static void Main(string[] args)

   9:         {

  10:             var listener = new ElBrunoListener();

  11:             var controller = new Controller();

  12:             controller.AddListener(listener);

  13:             Console.WriteLine("Press Enter to quit...");

  14:             Console.ReadLine();

  15:             controller.RemoveListener(listener);

  16:             controller.Dispose();

  17:         }

  18:     }

  19: }

6. La clase ElBrunoListener tiene un poco más de código, ya que es la que se encarga de procesar la información que nos envía el Leap. Veamos que tiene dentro

   1: class ElBrunoListener : Listener

   2: {

   3:     private readonly Object _thisLock = new Object();

   4:  

   5:     private void SafeWriteLine(String line)

   6:     {

   7:         lock (_thisLock)

   8:         {

   9:             Console.WriteLine(line);

  10:         }

  11:     }

  12:  

  13:     public override void OnInit(Controller controller)

  14:     {

  15:         SafeWriteLine("Initialized");

  16:     }

  17:  

  18:     public override void OnConnect(Controller controller)

  19:     {

  20:         SafeWriteLine("Connected");

  21:         controller.EnableGesture(Gesture.GestureType.TYPESWIPE);

  22:     }

  23:  

  24:     public override void OnDisconnect(Controller controller)

  25:     {

  26:         SafeWriteLine("Disconnected");

  27:     }

  28:  

  29:     public override void OnExit(Controller controller)

  30:     {

  31:         SafeWriteLine("Exited");

  32:     }

  33:  

  34:     public override void OnFrame(Controller controller)

  35:     {

  36:         var frame = controller.Frame();

  37:         var gestures = frame.Gestures();

  38:         foreach (var swipe in from gesture in gestures where gesture.Type == Gesture.GestureType.TYPESWIPE select new SwipeGesture(gesture))

  39:         {

  40:             var gestureName = GetGestureNameFromSwipe(swipe);

  41:             SafeWriteLine(string.Format("Swipe id: {0}, name: {1}", swipe.Id, gestureName));

  42:             break;

  43:         }

  44:     }

  45:  

  46:     private string GetGestureNameFromSwipe(SwipeGesture swipe)

  47:     {

  48:         var gestureName = "undefined";

  49:         var direction = swipe.Direction;

  50:         if (direction.Yaw > 0)

  51:         {

  52:             gestureName = "left to right";

  53:         }

  54:         if (direction.Yaw < 0)

  55:         {

  56:             gestureName = "right to left";

  57:         }

  58:         return gestureName;

  59:     }

  60: }

7. En primer lugar podemos ver que podemos hacer un override de OnInit, OnConnect, OnDisconnect y OnExit para inicializar el sensor. En este caso, solo quiero que el sensor registre el gesto SWIPE.

8. Luego en el OnFrame, podemos procesar la información que nos retorna un FRAME. La verdad es que es impresionante todo lo que tiene este objeto. En este ejemplo, accedemos a la colección de gestos y en la misma, obtenemos los de tipo SWYPE.

9. Luego tenemos que procesar toda la información de este SWIPE. Por un lado sabemos que es un SWIPE, pero necesitamos averiguar la dirección del mismo. Para esto trabajamos con el objeto SwipeGesture y resumiendo un poco el tema, dentro del mismo identifico si el swipe ha sido de izquierda a derecha procesando la propiedad Direction.

image

Direction es un vector. Un vector tiene mucha información, como la posición inicial y final, siempre asociado a los ejes, X, Y y Z. Con esta información y pensando en el vector en los 3 ejess, podríamos identificar swipes de izquierda a derecha, de arriba hacia abajo, de abajo a izquierda, etc.

En este caso, y para resumir mucho lo que podemos hacer con el LEAP, he decido procesar la propiedad YAW. La misma nos da un valor entero con la diferencia en ángulos desde el eje Z negativo y el eje X positivo.

api/../../../images/Math_Yaw_Angle.png

De esta forma si el ángulo es mayor que 90º será un SWIPE LEFT TO RIGHT y si es menor que 90º será un SWIPE RIGHT TO LEFT.

Nota: Esto siempre pensando en que no seas Terminator y hagas los gestos de swipe en una dirección recta sin variaciones.

10. Pues bien, ahora ya podemos lanzar la app y ver como la consola nos muestra los gestos que vamos realizando sobre el Leap Motion!

Por cierto, me tendré que conseguir unas Google Glases o una cámara deportiva porque lo de filmar acciones en 1ra persona con el mobile phone … pues no queda bien Open-mouthed smile

Saludos @ Home

El Bruno

image image image Google

[#KINECTSDK] Camp:Introduccion development with Kinect (sold out!)

Hello!!!

Thanks to Cristina (my MVP Lead) and to Rafa Ansino, I’ve the cnace to participate and lead a DevCamp with focus in the development with Kinect for Windows SDK. the date for this Camp is March 8, from 09:00 to 14:00. In this session I’ll share an overview of what we can do with Kinect for Windows and the SDK V1. The sad part is … we sold out! I’ve a have full House. The good news is that you have the chance to request a Second Edition, so if we get enough quota we’ll probably do another.

And we’re very freak, so I’ll also share some of the capabilities of the new Kinect for Windows V2 (which is simply amazing!) and why not, some that another development environment not Microsoft to create games with Kinect and C#.

By the way if you want to see the posts of Kinect SDK V2, them can be found here.

Registration (or almost) http://www.eventbrite.es/e/entradas-campintroduccion-al-desarrollo-con-kinect-10100142799

Greetings @ Home

El Bruno

imageimageimageGoogle