Close

WEEDINATOR navigating using Pixy2 line tracking camera

A project log for Autonomous Agri-robot Control System

Controlling autonomous robots the size of a small tractor for planting, weeding and harvesting

capt-flatus-oflahertyCapt. Flatus O'Flaherty ☠ 06/10/2018 at 13:470 Comments


The WEEDINATOR uses advanced, super accurate GPS to navigate along farm tracks to the start of the beds of vegetables with an accuracy of about plus/minus 20 mm. Once on the bed, accuracy needs to be even greater - at least plus/minus 5 mm. 

Here, we can use object recognition cameras such as the Pixy2 which can perform 'on chip' line recognition without taxing our lowly Arduinos etc.

This test was done in ideal, cloudy conditions and eventually the lighting would need to be 100% controlled by extending the glass fibre body of the machine over the camera's field of view and using LEDs to illuminate the rope. Other improvements include changing the rope colour to white and moving the camera slightly closer to the rope.

The Pixy2 is incredibly easy to code:

#include <Pixy2.h>
#include <PIDLoop.h>

#define X_CENTER         (pixy.frameWidth/2)
Pixy2 pixy;
PIDLoop headingLoop(5000, 0, 0, false);
int32_t panError; 
int32_t flagValue; 
////////////////////////////////////////////////////////////////////////////

void initPixy()
{
  digitalWrite(PIXY_PROCESSING,HIGH);
  pixy.init();
  pixy.changeProg("line");
}

////////////////////////////////////////////////////////////////////////////
/* LINE_MODE_MANUAL_SELECT_VECTOR
    Normally, the line tracking algorithm will choose what it thinks is the best Vector line automatically. 
 *  Setting LINE_MODE_MANUAL_SELECT_VECTOR will prevent the line tracking algorithm from choosing the Vector automatically. 
 *  Instead, your program will need to set the Vector by calling setVector(). _MODE_MANUAL_SELECT_VECTOR
 *  uint8_t m_flags. This variable contains various flags that might be useful.
 *  uint8_t m_x0. This variable contains the x location of the tail of the Vector or line. The value ranges between 0 and frameWidth (79) 3) 
 *  int16_t m_angle . This variable contains the angle in degrees of the line.
*/
void pixyModule()
{
  if (not usePixy)
    return;
  int8_t res;
  int left, right;
  char buf[96];
  // Get latest data from Pixy, including main vector, new intersections and new barcodes.
  res = pixy.line.getMainFeatures();
  // We found the vector...
  if (res&LINE_VECTOR)
  {
    // Calculate heading error with respect to m_x1, which is the far-end (head) of the vector,
    // the part of the vector we're heading toward.
    panError = (int32_t)pixy.line.vectors->m_x1 - (int32_t)X_CENTER;
    flagValue = (int32_t)pixy.line.vectors->m_flags;
    DEBUG_PORT.print( F("Flag Value:       ") );DEBUG_PORT.println(flagValue);
    panError =  panError + 188;  // Cant send negative values.Lower value makes machine go anti clockwise.
    pixy.line.vectors->print();

    // Perform PID calcs on heading error.
    //headingLoop.update(panError);
  }
  //DEBUG_PORT.print( F("PAN POS:       ") );DEBUG_PORT.println(panError);

} // pixyModule

Discussions