Slide 1

Slide 1 text

Embedded  Linux  applications   for  autonomous  UAVs Flying Penguins

Slide 2

Slide 2 text

Clay McClure github.com/claymation twitter.com/claymcclure

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

autopilots

Slide 10

Slide 10 text

RC input motor mixing stabilization telemetry missions failsafes

Slide 11

Slide 11 text

autopilots

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

≠ AUTO PILOT AUTO NOMOUS

Slide 14

Slide 14 text

where to go how to get there what to do next “finds its own goal positions”

Slide 15

Slide 15 text

SO MANY ALGORITHMS, SO LITTLE COMPUTER http://ra3ndy.deviantart.com/art/Sad-Panda-69204875

Slide 16

Slide 16 text

+

Slide 17

Slide 17 text

Autopilot runs on Linux

Slide 18

Slide 18 text

Autopilot talks to Linux

Slide 19

Slide 19 text

ODROID-XU3 Lite • Samsung Exynos5422 octa core • 4x Cortex™-A15 2.0GHz • 4x Cortex™-A7 1.4GHz • 2 GB RAM • 32+ GB flash • 4x USB 2.0 + 1x USB 3.0

Slide 20

Slide 20 text

UAV Your App Linux ? Auto Pilot Architecture

Slide 21

Slide 21 text

UAV MAV Link Your App Linux Auto Pilot Architecture

Slide 22

Slide 22 text

MAVLink is the HTTP of drones

Slide 23

Slide 23 text

(it’s also the libcurl)

Slide 24

Slide 24 text

MAVLink

Slide 25

Slide 25 text

status configuration position / attitude setpoints missions

Slide 26

Slide 26 text

UAV MAV Link Your App Linux ? Auto Pilot Architecture

Slide 27

Slide 27 text

UAV MAV Link Your App Linux Middle ware Auto Pilot Architecture

Slide 28

Slide 28 text

Middleware DroneAPI • Python • Go to Kevin Hester’s talk tomorrow mavros • Python, C++, Lisp (really) • Access to a wealth of robotics research and tools

Slide 29

Slide 29 text

UAV MAV Link mavros Your App ROS Linux Auto Pilot Architecture

Slide 30

Slide 30 text

ROS Crash Course

Slide 31

Slide 31 text

Robot Operating System “ROS is an open-source, meta-operating system for your robot.”

Slide 32

Slide 32 text

“ROS is an open-source, meta-operating system for your robot.” Robot Operating System

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Nodes Node Node Node Node Node Node Node Node Node

Slide 35

Slide 35 text

Topics Node Node Node Node Topic

Slide 36

Slide 36 text

Services Node Node

Slide 37

Slide 37 text

but wait, that’s not all… parameters dynamic reconfig coordinate frames transformations record/playback visualization logging

Slide 38

Slide 38 text

UAV MAV Link mavros Your App ROS Linux Auto Pilot Architecture

Slide 39

Slide 39 text

mavros is the Babel fish of drones

Slide 40

Slide 40 text

Mavros Node Topic Topic Topic Auto Pilot

Slide 41

Slide 41 text

Topics /mavros/state /mavros/imu/data /mavros/global_position/global /mavros/local_position/local /mavros/setpoint_position/local_position /mavros/setpoint_velocity/cmd_vel

Slide 42

Slide 42 text

Services /mavros/cmd/arming /mavros/cmd/land /mavros/cmd/takeoff /mavros/set_mode /mavros/set_stream_rate

Slide 43

Slide 43 text

• FCU • MAVLink • mavros • ROS • Application nodes PX4 + ROS Credit: Kabir Mohammed MAVROS

Slide 44

Slide 44 text

UAV MAV Link mavros Your App ROS Linux Auto Pilot Architecture

Slide 45

Slide 45 text

Event-driven programming • “Don’t call me, I’ll call you” • Your application code responds to events • Message arrival • “vehicle position is (x, y, z)” • Timer expiry • “it’s time to run the control loop”

Slide 46

Slide 46 text

YAPL Yet Another Precision Lander

Slide 47

Slide 47 text

Nodes • Tracker • Processes video stream, looks for landing pad • Publishes target position/velocity messages • Commander • Subscribes to vehicle state and position messages • Subscribes to target tracker messages • Controls vehicle velocity

Slide 48

Slide 48 text

Tracker

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

class  TrackerNode(object):   !        def  __init__(self):                  rospy.init_node("tracker")   !                camera_matrix  =  rospy.get_param("~camera_matrix")                  use_sim  =  rospy.get_param("~use_sim",  False)   !              self.image_publisher  =  \                          rospy.Publisher("tracker/image",                                  sensor_msgs.msg.Image,  queue_size=1)   !                self.track_publisher  =  \                          rospy.Publisher("tracker/track",                                  Track,  queue_size=1)

Slide 52

Slide 52 text

class  TrackerNode(object):   !        def  run(self):                  """                  Capture  frames  from  the  camera  and  publish  them.                  """                  self.wait_for_position()   !                while  not  rospy.is_shutdown():                          frame  =  self.camera.get_frame()                          if  frame  is  not  None:                                  position,  velocity  =  \                                          self.process_frame(frame)                                  self.publish_track(position,  velocity)

Slide 53

Slide 53 text

       def  publish_track(self,  position,  velocity):                  """                  Publish  Track  messages  for  the  commander  node.                  """                  msg  =  Track()                  msg.track.is_tracking.data  =  self.is_tracking   !                if  self.is_tracking:                          msg.track.position.x  =  position[0]                          msg.track.position.y  =  position[1]                          msg.track.position.z  =  position[2]                          msg.track.velocity.x  =  velocity[0]                          msg.track.velocity.y  =  velocity[1]                          msg.track.velocity.z  =  velocity[2]   !                self.track_publisher.publish(msg)  

Slide 54

Slide 54 text

       def  publish_track(self,  position,  velocity):                  """                  Publish  Track  messages  for  the  commander  node.                  """                  msg  =  Track()                  msg.track.is_tracking.data  =  self.is_tracking   !                if  self.is_tracking:                          msg.track.position.x  =  position[0]                          msg.track.position.y  =  position[1]                          msg.track.position.z  =  position[2]                          msg.track.velocity.x  =  velocity[0]                          msg.track.velocity.y  =  velocity[1]                          msg.track.velocity.z  =  velocity[2]   !                self.track_publisher.publish(msg)  

Slide 55

Slide 55 text

$  cat  msg/Track.msg     #  Whether  we're  tracking  an  object   std_msgs/Bool  is_tracking   ! #  Relative  position  and  velocity  of  the  tracked  object   geometry_msgs/Vector3  position   geometry_msgs/Vector3  velocity  

Slide 56

Slide 56 text

       def  publish_image(self,  image):                  """                  Publish  processed  tracker  images  for  telemetry.                  """                  msg  =  self.image_bridge.cv2_to_imgmsg(image,  "bgr8")                  self.image_publisher.publish(msg)  

Slide 57

Slide 57 text

Commander

Slide 58

Slide 58 text

PENDING SEEK APPROACH DESCEND LAND LANDED

Slide 59

Slide 59 text

class  CommanderNode(object):        def  __init__(self,  vehicle):                rospy.init_node("commander")   !                #  Initialize  flight  controllers                  self.controllers  =  {                          FlightState.PENDING    :  PendingController(),                          FlightState.SEEK          :  SeekController(),                          FlightState.APPROACH  :  ApproachController(),                          FlightState.DESCEND    :  DescendController(),                          FlightState.LAND          :  LandController(),                  }   !                #  ...

Slide 60

Slide 60 text

               #  Initialize  the  control  loop                  control_loop_rate  =  \                                  rospy.get_param("~control_loop_rate",                                  DEFAULT_CONTROL_LOOP_RATE)                  self.control_loop_rate  =  \                                  rospy.Rate(control_loop_rate)   !                rospy.Subscriber("/mavros/state",                                  mavros.msg.State,                                  self.handle_state_message)                  rospy.Subscriber("/tracker/track",                                  Track,  self.handle_track_message)   !                #  Initialize  state  machine                  self.controller  =  None                  self.state  =  FlightState.INIT                  self.transition_to_state(FlightState.PENDING)

Slide 61

Slide 61 text

       def  run(self):                  """                  Spin  the  ROS  event  loop,  running  the  active                  flight  controller  on  each  iteration.                  """                  while  not  rospy.is_shutdown():                          self.controller.run()                          self.control_loop_rate.sleep()

Slide 62

Slide 62 text

       def  handle_state_message(self,  msg):                  """                  Handle  mavros/State  messages,  published  by  the                  FCU  at  ~1  Hz.                  """                  mode  =  msg.mode   !                if  (mode  in  GUIDED_MODES  and                          self.state  ==  FlightState.PENDING):                                  self.transition_to_state(FlightState.SEEK)   !                elif  (mode  not  in  GUIDED_MODES  and                          self.state  !=  FlightState.PENDING):                                  self.transition_to_state(FlightState.PENDING)

Slide 63

Slide 63 text

#  Guided  modes  differ  between  ArduCopter  and  PX4  native   GUIDED_MODES  =  ("GUIDED",  "OFFBOARD")

Slide 64

Slide 64 text

Vehicle

Slide 65

Slide 65 text

class  Vehicle(object,  PositionMixin):          """          Simple  model  of  an  aerial  vehicle.          """          def  __init__(self):                self.location_setpoint_publisher  =  \                          rospy.Publisher(                                  "/mavros/setpoint_position/local_position",                                  geometry_msgs.msg.PoseStamped,                                  queue_size=1)   !                self.velocity_setpoint_publisher  =  \                          rospy.Publisher(                                  "/mavros/setpoint_velocity/cmd_vel",                                  geometry_msgs.msg.TwistStamped,                                  queue_size=1)

Slide 66

Slide 66 text

class  Vehicle(object,  PositionMixin):   !        #  ...                  def  set_location_setpoint(self,  setpoint):                  """                  Publish  a  SET_POSITION_TARGET_LOCAL_NED  message                  with  position  x,  y,  z  and  yaw.                  """                  x,  y,  z,  yaw  =  setpoint   !                msg  =  geometry_msgs.msg.PoseStamped()                  msg.pose.position.x  =  x                  msg.pose.position.y  =  y                  msg.pose.position.z  =  z                  msg.pose.orientation.z  =  yaw   !                self.location_setpoint_publisher.publish(msg)

Slide 67

Slide 67 text

class  Vehicle(object,  PositionMixin):   !        #  ...                  def  set_armed_state(self,  state):                  set_armed_state  =  rospy.ServiceProxy(                                  "/mavros/cmd/arming",                                  CommandBool)                  set_armed_state(value=state)   !        def  arm(self):                  self.set_armed_state(True)   !        def  disarm(self):                  self.set_armed_state(False)

Slide 68

Slide 68 text

Simulation

Slide 69

Slide 69 text

HITL • Hardware in the loop • Flight software runs on flight hardware • Simulated sensor and control inputs

Slide 70

Slide 70 text

SITL • Software in the loop • Flight software runs on (Linux) desktop • Simulated sensor and control inputs and HAL

Slide 71

Slide 71 text

No content

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

–Johnny Appleseed “Type a quote here.” “In theory there is no difference between theory and practice. 
 In practice there is.” ! ~ Yogi Berra

Slide 75

Slide 75 text

Practical Considerations

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

No content

Slide 79

Slide 79 text

Connections • UART recommended • Requires 6-pin DF-13, possibly a level shifter • USB works for me • Use hot glue gun • sudo  apt-­‐get  remove  modemmanager

Slide 80

Slide 80 text

Power 5V 5A UBEC ! ODROID + USB camera + WiFi = 5 hours

Slide 81

Slide 81 text

Launch files • ROS feature that makes it easy to start and manage multiple nodes and their parameters • roslaunch  lander  lander.launch

Slide 82

Slide 82 text

Startup • Use ubuntu’s upstart to launch ROS + mavros + application nodes • rosrun  robot_upstart  install  \
        lander/launch/lander.launch

Slide 83

Slide 83 text

Telemetry • WiFi • Ad-Hoc mode (man  wireless) • Need high-gain antenna and an antenna tracker
 (a.k.a. unsuspecting friend or bystander) • sudo  apt-­‐get  remove  wpasupplicant   • GSM? • Use image_transport to transmit compressed images

Slide 84

Slide 84 text

Coordinate Frames • Global / Local • NED (UAV) • ENU (ROS) • Body-fixed • tf library

Slide 85

Slide 85 text

In closing…

Slide 86

Slide 86 text

What will you make?

Slide 87

Slide 87 text

Thanks

Slide 88

Slide 88 text

For more information… ros.org ardupilot.com pixhawk.org/start pixhawk.ethz.ch/mavlink github.com/mavlink/mavros github.com/claymation/lander