<< return to Pixycam.com

Detect multiple objects

What I am having troubles is modifying the mp_object_chasing.py program to recognize more than a single signature. For now two signatures is good enough for testing. Eventually would need more signatures. I have been changing the value of sig =1 for the first signature to sig = 2 for the second signature. What I would like is for the program to track/recognize both signatures. But, for instance chase the first signature but avoid the second signature.

The link in a previous similar topic does not work — http://cmucam.org/projects/cmucam5/wiki/Teach_Pixy_an_Object_2

Hello,
For Python, getBlocks will always get the detected blocks for all signatures. I’m not sure what you mean by sig=1 sig=2. Perhaps you could post your code.

Edward

Hello Edward:

I am using the sample code mp_object_chasing.py I copied the whole program below. At lines 52 and 53 you have

# Signatures we're interested in (SIG1)
sig = 1

What do I need to do to get this code to see both objects and act based on which object is seen? Or, do I have to create a loop that first checks for object 1 (sig = 1) and then object 2 (sig = 2) that would cause a bit of a time delay as the program gets longer and more complex. I was thinking somewhere after the while statement at line 78

while not ts.pressed():
    # Request block
    nr_blocks, block = pixy2.get_blocks(1, 1)
    # Extract data
    if nr_blocks > 0:
        # SIG1 detected, control motors
        x = block[0].x_center         # X-centrois of object
        y = block[0].y_center         # Y-centroid of object

Hope this clears up what I am inquiring about? Do you have a different sample python code I could try? Maybe something that says what colour object is detected?
Mike,

#!/usr/bin/env pybricks-micropython
“”" Sample application for pixycamev3

Use this example on LEGO EV3 brick running pybricks-micropython.

This Python3 example shows how to chase a detected object.

On the wiki you’ll find an explanation how chasing an object works.
Have a look at:
https://docs.pixycam.com/wiki/doku.php?id=wiki:v2:lego_chase_demo

If your robot drives in the wrong direction you need to change
the polarity of the motors: set argument positive_direction
to Direction.CLOCKWISE. If your robot seems to turn to the
wrong direction (turn away from the object instead of facing it),
you probable need to switch ports for the motors.

This example uses a PID-controller. You may have to adjust the
values for the PID-constants for your robot.

Building instructions:

  • LEGO EV3 brick running pybricks-micropython
  • Connect Pixy2 to port 1
  • Set I2C address to 0x54
  • Set signature 1 for the object you like to follow
  • Connect LEGO TouchSensor to port 4
  • Connect two LEGO LargeMotors to ports A and D

Author : Kees Smit
Date : December 29 2021
Version : 1.00
License : GNU General Public License v2

Charmed Labs, www.charmedlabs.com
“”"
from pybricks.ev3devices import Motor, TouchSensor
from pybricks.parameters import Port, Direction
from pixycamev3.pixy2 import Pixy2

def limit_speed(speed):
“”" Limit speed in range [-1000,1000] “”"
if speed > 1000:
speed = 1000
elif speed < -1000:
speed = -1000
return speed

def main():
# Connect Pixy2
pixy2 = Pixy2(port=1, i2c_address=0x54)

# Signatures we're interested in (SIG1)
sig = 1

# Connect TouchSensor (to stop script)
ts = TouchSensor(Port.S4)

# Connect LargeMotors
rmotor = Motor(Port.A, positive_direction=Direction.COUNTERCLOCKWISE)
lmotor = Motor(Port.D, positive_direction=Direction.COUNTERCLOCKWISE)

# Defining constants
X_REF = 158  # X-coordinate of referencepoint
Y_REF = 150  # Y-coordinate of referencepoint
KP = 0.4     # Proportional constant PID-controller
KI = 0.01    # Integral constant PID-controller
KD = 0.05    # Derivative constant PID-controller
GAIN = 10    # Gain for motorspeed

# Initializing PID variables
integral_x = 0
derivative_x = 0
last_dx = 0
integral_y = 0
derivative_y = 0
last_dy = 0

while not ts.pressed():
    # Request block
    nr_blocks, block = pixy2.get_blocks(1, 1)
    # Extract data
    if nr_blocks > 0:
        # SIG1 detected, control motors
        x = block[0].x_center         # X-centrois of object
        y = block[0].y_center         # Y-centroid of object
        dx = X_REF - x                # Error in reference to X_REF
        integral_x = integral_x + dx  # Calculate integral for PID
        derivative_x = dx - last_dx   # Calculate derivative for PID
        speed_x = KP*dx + KI*integral_x + KD*derivative_x  # Speed X-direction
        dy = Y_REF - y                # Error in reference to Y_REF
        integral_y = integral_y + dy  # Calculate integral for PID
        derivative_y = dy - last_dy   # Calculate derivative for PID
        speed_y = KP*dy + KI*integral_y + KD*derivative_y  # Speed Y-direction
        # Calculate motorspeed out of speed_x and speed_y
        # Use GAIN otherwise speed will be to slow,
        # but limit in range [-1000,1000]
        rspeed = limit_speed(GAIN*(speed_y - speed_x))
        lspeed = limit_speed(GAIN*(speed_y + speed_x))
        rmotor.run(speed = round(rspeed))
        lmotor.run(speed = round(lspeed))
        last_dx = dx                  # Set last error for x
        last_dy = dy                  # Set last error for y
    else:
        # SIG1 not detected, stop motors
        rmotor.stop()
        lmotor.stop()
        last_dx = 0
        last_dy = 0

# TouchSensor pressed, stop motors
rmotor.stop()
lmotor.stop()

if name == ‘main’:
main()

Hello,
You will get all detected blocks from get_blocks(). You can then look at each block in the array and see which signature the block belongs to by looking at m_signature. You don’t need perform separate checks (sig=1, sig=2).

Hope this helps.

Edward