package main import ( "fmt" "log" "douglasthrift.net/dtrobots/gamepad" "github.com/ev3go/ev3dev" ) // drive modes const ( tank = iota joystick ) const driveModeCount = 2 type driveMode int func (d driveMode) String() string { switch d { case tank: return "tank" case joystick: return "joystick" default: return "unknown" } } func (d *driveMode) Set(value string) error { switch value { case "tank": *d = tank case "joystick": *d = joystick default: return fmt.Errorf("unknown drive mode: %v", value) } return nil } func control(mode driveMode, g *gamepad.Gamepad, leftMotor, rightMotor *ev3dev.TachoMotor) error { log.Printf("control loop started (drive mode: %v)", mode) if err := setPolarity(ev3dev.Normal, leftMotor, rightMotor); err != nil { return err } gamepadMotors := false var leftCruise, rightCruise int for { select { case e := <-g.LeftAnalog: if gamepadMotors { switch mode { case tank: if err := tankAnalogControl(e, leftMotor, &leftCruise); err != nil { return err } } } case e := <-g.RightAnalog: if gamepadMotors { switch mode { case tank: if err := tankAnalogControl(e, rightMotor, &rightCruise); err != nil { return err } } } case e := <-g.DPad: log.Println("dpad", e) case e := <-g.A: if e.IsButtonPress() { gamepadMotors = true log.Print("gamepad motor control enabled") } case e := <-g.B: if e.IsButtonPress() { gamepadMotors = false log.Print("gamepad motor control disabled") if err := stop(leftMotor, rightMotor); err != nil { return err } leftCruise, rightCruise = 0, 0 } case e := <-g.X: log.Println("x", e) case e := <-g.Y: log.Println("y", e) case e := <-g.Left: if e.IsButtonPress() && gamepadMotors { var err error leftCruise, err = leftMotor.Speed() if err != nil { return err } log.Printf("left cruise set: %v", leftCruise) } case e := <-g.Right: if e.IsButtonPress() && gamepadMotors { var err error rightCruise, err = rightMotor.Speed() if err != nil { return err } log.Printf("right cruise set: %v", rightCruise) } case e := <-g.Back: log.Println("back", e) case e := <-g.Start: log.Println("start", e) case e := <-g.Logitech: if e.IsButtonPress() { mode++ mode %= driveModeCount log.Printf("switched drive mode: %v", mode) } } } } func setPolarity(polarity ev3dev.Polarity, motors ...*ev3dev.TachoMotor) error { for _, motor := range motors { p, err := motor.Polarity() if err != nil { return err } if p != polarity { motor.SetPolarity(polarity) } if err := motor.Err(); err != nil { return err } } return nil } func stop(motors ...*ev3dev.TachoMotor) error { for _, motor := range motors { motor.SetSpeedSetpoint(0) motor.Command("stop") if err := motor.Err(); err != nil { return err } } return nil } func tankAnalogControl(e gamepad.Event, motor *ev3dev.TachoMotor, cruise *int) error { if e.IsAxisY() { speed := -int(float64(motor.MaxSpeed()) * e.Fraction()) currentSpeed, err := motor.Speed() if err != nil { return err } if speed != currentSpeed { motor.SetSpeedSetpoint(speed) if speed == 0 { motor.Command("stop") } else { motor.Command("run-forever") } if err := motor.Err(); err != nil { return err } } } return nil }