이 가이드는 인류와 AI가 함께 만드는 지식입니다.
이 콘텐츠는 Human + AI Partnership 철학 아래 모든 사람이 로봇·AI를 배울 수 있도록 무료로 제공됩니다. 당신의 질문과 기여가 다음 학생의 미래를 바꿉니다.
ROS 2 Agricultural Robotics Guide 2026
Agriculture is one of the fastest-growing robotics markets. This guide covers the ROS 2 stack for field robots: centimeter-accurate RTK-GPS navigation, vision-based crop-row following, precision spraying, and autonomous harvesting.
1. The Ag-Robot Stack
Field robots combine GNSS, vision, and implement control:
sudo apt-get install -y ros-humble-nav2-bringup ros-humble-robot-localization ros-humble-nmea-navsat-driver ros-humble-mavros # for ArduPilot rovers
# Layers (bottom -> top):
# 1. RTK-GPS + IMU fusion (robot_localization EKF)
# 2. Crop-row perception (vision line detection)
# 3. Coverage path planner (boustrophedon / headland turns)
# 4. Implement control (sprayer / seeder / cutter)2. RTK-GPS: Centimeter Accuracy
Standard GPS drifts meters; RTK corrects to ~2cm — essential for crop rows:
# ublox ZED-F9P RTK rover with NTRIP corrections
ros2 launch ublox_gps ublox_gps_node.launch.py device:=/dev/ttyACM0 frame_id:=gps_link
# Feed NTRIP base-station corrections for RTK fix
ros2 run ntrip_client ntrip_ros --ros-args -p host:=rtk.example.com -p port:=2101 -p mountpoint:=NEAR -p username:=user
# Verify a FIXED solution (not FLOAT):
ros2 topic echo /ublox_gps_node/fix --field status.status
# 2 = GBAS/RTK fixed <- required for row-level precision3. GPS + IMU Fusion
Fuse RTK-GPS with wheel odometry and IMU using robot_localization:
# ekf_ag.yaml — navsat_transform + EKF
navsat_transform_node:
ros__parameters:
frequency: 30.0
magnetic_declination_radians: 0.0
yaw_offset: 0.0
zero_altitude: true
broadcast_utm_transform: true
publish_filtered_gps: true
ekf_filter_node:
ros__parameters:
frequency: 30.0
two_d_mode: true
odom0: /wheel/odometry
odom0_config: [false,false,false, false,false,false,
true,true,false, false,false,true, false,false,false]
imu0: /imu/data
imu0_config: [false,false,false, true,true,true,
false,false,false, true,true,true, true,true,true]4. Vision-Based Crop-Row Following
Between GPS waypoints, follow the actual crop rows with vision — plants never grow exactly on the GPS line:
import cv2, numpy as np
def detect_crop_row(frame):
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# Excess-green segmentation for vegetation
green = cv2.inRange(hsv, (35, 40, 40), (85, 255, 255))
# Column-wise vegetation histogram -> row centers
hist = np.sum(green[green.shape[0]//2:], axis=0)
row_center = int(np.argmax(np.convolve(hist, np.ones(40)/40, 'same')))
error = (row_center - frame.shape[1] / 2) / (frame.shape[1] / 2)
return error # -1..1 steering error to stay centered on the row5. Coverage Path Planning
Fields need full coverage, not point-to-point. Generate a boustrophedon (back-and-forth) pattern:
def boustrophedon(field_polygon, swath_width, heading):
"""Back-and-forth coverage aligned to the field heading."""
lanes = slice_polygon_into_lanes(field_polygon, swath_width, heading)
path, flip = [], False
for lane in lanes:
pts = lane if not flip else lane[::-1]
path.extend(pts)
flip = not flip # alternate direction each lane
return add_headland_turns(path) # smooth U-turns at field ends
# Feed the coverage path to Nav2 as an ordered waypoint follower.6. Precision Spraying
Actuate nozzles only over detected weeds/plants — cuts chemical use dramatically:
class PrecisionSprayer(Node):
def __init__(self):
super().__init__('precision_sprayer')
self.create_subscription(Detection2DArray, '/weed_detections',
self.spray, 10)
self.nozzle_pub = self.create_publisher(UInt8, '/nozzle_bank', 10)
def spray(self, msg):
# Map each detection's x-position to one of N boom nozzles
active = 0
for det in msg.detections:
nozzle = int(det.bbox.center.position.x / self.px_per_nozzle)
active |= (1 << nozzle) # bitmask of nozzles to fire
self.nozzle_pub.publish(UInt8(data=active))
# Only spray where weeds are -> 60-90% less herbicide7. Autonomous Harvesting
Harvesting couples fruit detection, ripeness classification, and arm picking:
# Harvest decision pipeline
for fruit in detect_fruits(rgbd_frame):
if classify_ripeness(fruit) < RIPE_THRESHOLD:
continue # leave unripe fruit
point3d = pixel_to_3d(fruit.u, fruit.v, depth, camera_info)
if point3d is None:
continue
grasp = plan_grasp(point3d, approach='side')
if moveit.plan_and_execute(grasp):
actuate_cutter() # snip stem
place_in_bin()8. Safety in the Field
- Bystander detection: stop for humans/animals in the path (ISO 18497 ag-robot safety).
- Geofencing: hard boundary so the robot never leaves the field onto a road.
- Remote e-stop: cellular/RF kill switch for unattended operation.
- Slope limits: monitor IMU roll/pitch to prevent rollover on terraces.
- Implement lockout: disable sprayer/cutter whenever navigation faults.
9. Connectivity & Fleet
- Intermittent networks: fields have poor coverage — buffer telemetry, sync opportunistically.
- Store-and-forward: log coverage maps locally, upload at the barn.
- Multi-robot: partition the field so several robots cover it without overlap.
- Season data: yield/weed maps feed next season's prescription plans.
10. Real Platforms
- Naio Oz/Dino: commercial weeding robots with autonomous navigation.
- AgBot / Amiga (farm-ng): open, ROS 2-friendly ag platforms.
- John Deere autonomy: retrofit tractors with GPS + vision autonomy.
- DIY: a skid-steer base + ZED-F9P + depth camera runs the full stack above.
Key Takeaways
Precision agriculture runs on RTK-GPS for centimeter accuracy, fused with IMU/odometry in an EKF, corrected by vision-based crop-row following. Cover fields with boustrophedon planning, spray only where weeds are detected to slash chemical use, and couple fruit detection with arm control for harvesting. Design for field safety, poor connectivity, and multi-season data — that is what turns an ag-robot into real farm ROI.