After much deliberation and focus, and one late night where i told myself I just need to stop procrastinating and get thing finished the turret is working!
As a reminder, I’ve had the visual spotting code working for a while, but I needed to work on moving the motors, which proved a harder challenge than I had wanted. The camera sees a person and gets the center location of the bounding box, then calculates the difference between the center of the frame and the bbox center. The next step is to get the left-right motor to just move a fixed distance, to keep things simple I’m skipping vertical adjustments at this stage.
As a review, I have tried several approaches. The motors are driven with two inputs each, a DIRECTION pin, and a STEP pin. The voltage HIGH or LOW on the direction pin sets the direction the motor steps towards, and the STEP pin pulses the motor one step(or micro-step).
- I initially tried driving the motors though the jetson using python and the jetson.gpio library. Realtime hardware control in python… didn’t work. I tried using threading, but turns out even using threading wasn’t enough. I started looking into having a separate process going, and just realized it was becoming too complicated, and this was not what i wanted to focus on. I was able to drive the motors, but there too much stuttering.
- Next I tried what I should have done in the first place – have a embedded system control the motors – ie an Arduino. I choose a Seeeduino Xiao – low cost, the only real downside is the compile time in the Arduino IDE. I started by sending serial data from the Python sketch to the Arduino with a test sketch where I was parsing and creating the motor drive signals myself, but that quickly ballooned in complexity, and I looked around again for a library. I had looked for an off the shelf library for multi-motor stepper control, but didn’t find one. There was some frustration controlling the motors with my homemade sketch, I ran into the same problems as the python sketch: the handoff to read and parse the serial commands was taking too long and the motors were not moving smoothly.
- After trying to briefly roll my own motor driver, I finally found the AccelStepper library and it worked like a dream. Velocity and acceleration threshold settings, move by velocity or position, multiple motors support with multiple speeds, this library was perfect. In 10minutes I had made a demo sketch and was kicking myself for not looking a little more previously. After all, I don’t care as much about this step, my real goal is to make a motion platform for reinforcement learning.
After getting the motors working I had the turret tracking in a few minutes. The whole code flow is as follows:
- Look for a object with a specific ClassID in view of the camera. Otherwise do nothing
- If found, calculate error between person and and center of the camera view.
- If the error is below a certain threshold zone, fire. The threshold zone is the “dead-zone” where the motors do not move
- If the error is above the theshold, move at a fixed distance and speed.
If the distance and speed is too low, the turrent won’t follow quick enough to stay on target. If the distance and/or speed is too high, you get oscillations. What is needed next is a PID loop to set the distance to move. For now I’ll just move at max speed all the time, the motor library takes care of the ramping up to the max speed and the acceleration is adjustable.
Check out the Arduino code here: