gobot.io/x/gobot@v1.16.0/examples/tello_opencv.go (about)

     1  // +build example
     2  //
     3  // Do not build by default.
     4  
     5  /*
     6  You must have ffmpeg and OpenCV installed in order to run this code. It will connect to the Tello
     7  and then open a window using OpenCV showing the streaming video.
     8  
     9  How to run
    10  
    11  	go run examples/tello_opencv.go
    12  */
    13  
    14  package main
    15  
    16  import (
    17  	"fmt"
    18  	"io"
    19  	"os/exec"
    20  	"strconv"
    21  	"time"
    22  
    23  	"gobot.io/x/gobot"
    24  	"gobot.io/x/gobot/platforms/dji/tello"
    25  	"gocv.io/x/gocv"
    26  )
    27  
    28  const (
    29  	frameX    = 960
    30  	frameY    = 720
    31  	frameSize = frameX * frameY * 3
    32  )
    33  
    34  func main() {
    35  	drone := tello.NewDriver("8890")
    36  	window := gocv.NewWindow("Tello")
    37  
    38  	ffmpeg := exec.Command("ffmpeg", "-hwaccel", "auto", "-hwaccel_device", "opencl", "-i", "pipe:0",
    39  		"-pix_fmt", "bgr24", "-s", strconv.Itoa(frameX)+"x"+strconv.Itoa(frameY), "-f", "rawvideo", "pipe:1")
    40  	ffmpegIn, _ := ffmpeg.StdinPipe()
    41  	ffmpegOut, _ := ffmpeg.StdoutPipe()
    42  
    43  	work := func() {
    44  		if err := ffmpeg.Start(); err != nil {
    45  			fmt.Println(err)
    46  			return
    47  		}
    48  
    49  		drone.On(tello.ConnectedEvent, func(data interface{}) {
    50  			fmt.Println("Connected")
    51  			drone.StartVideo()
    52  			drone.SetVideoEncoderRate(tello.VideoBitRateAuto)
    53  			drone.SetExposure(0)
    54  
    55  			gobot.Every(100*time.Millisecond, func() {
    56  				drone.StartVideo()
    57  			})
    58  		})
    59  
    60  		drone.On(tello.VideoFrameEvent, func(data interface{}) {
    61  			pkt := data.([]byte)
    62  			if _, err := ffmpegIn.Write(pkt); err != nil {
    63  				fmt.Println(err)
    64  			}
    65  		})
    66  	}
    67  
    68  	robot := gobot.NewRobot("tello",
    69  		[]gobot.Connection{},
    70  		[]gobot.Device{drone},
    71  		work,
    72  	)
    73  
    74  	// calling Start(false) lets the Start routine return immediately without an additional blocking goroutine
    75  	robot.Start(false)
    76  
    77  	// now handle video frames from ffmpeg stream in main thread, to be macOS/Windows friendly
    78  	for {
    79  		buf := make([]byte, frameSize)
    80  		if _, err := io.ReadFull(ffmpegOut, buf); err != nil {
    81  			fmt.Println(err)
    82  			continue
    83  		}
    84  		img, _ := gocv.NewMatFromBytes(frameY, frameX, gocv.MatTypeCV8UC3, buf)
    85  		if img.Empty() {
    86  			continue
    87  		}
    88  
    89  		window.IMShow(img)
    90  		if window.WaitKey(1) >= 0 {
    91  			break
    92  		}
    93  	}
    94  }