gobot.io/x/gobot/v2@v2.1.0/examples/tello_opencv.go (about)

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