Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AP_Camera: Add Camera Tracking functionality (WIP) #27773

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

khanasif786
Copy link
Contributor

@khanasif786 khanasif786 commented Aug 7, 2024

This adds support for a companion computer to perform image tracking using any of the backends

}
}

void AP_Camera_Backend::handle_message_camera_information(mavlink_channel_t chan, const mavlink_message_t &msg) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we will face conflicts when using a mavlink enabled camera (e.g. CAMx_TYPE = MavlinkCamV2) because we will also receive a camera_information message from these cameras.

Copy link
Contributor Author

@khanasif786 khanasif786 Aug 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. now what will happen is if the message is coming from a camera, the camera's handle message will be called and if the message is from the tracking device it will forward it to base class's handle message.

@rmackay9
Copy link
Contributor

rmackay9 commented Aug 7, 2024

Could you rebase this and also clarify what testing has been done?

libraries/AP_Camera/AP_Camera_Backend.cpp Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Backend.cpp Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Backend.cpp Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Backend.cpp Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Backend.cpp Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Tracking.cpp Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Tracking.h Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Tracking.h Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Tracking.h Outdated Show resolved Hide resolved
libraries/AP_Camera/AP_Camera_Tracking.h Outdated Show resolved Hide resolved
@rmackay9
Copy link
Contributor

rmackay9 commented Aug 7, 2024

Could you create a separate PR with the python script in a new directory AP_Camera/examples?

@rmackay9
Copy link
Contributor

rmackay9 commented Aug 7, 2024

We should also consume the CAMERA_TRACKING_IMAGE_STATUS message and update the user

import math
from ultralytics import YOLO

master = mavutil.mavlink_connection('127.0.0.1:14560')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should allow the caller to specify the video source as an argument to the script.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instructions on how to install would be good. E.g. what packages are required and how can they be installed? (e.g. pip)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need something like requirements.txt, i actually added a comment on top just for now.

# faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(30, 30))
faces= [final_list]
if len(faces) == 0:
# Do something if no faces were detected
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be sending the CAMERA_TRACKING_IMAGE_STATUS message at regular intervals (1hz?) so that AP knows if we can't track the object any more

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should support MAV_CMD_CAMERA_STOP_TRACKING

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isnt that should be sent by the FC ? i.e.
CAMERA_TRACKING_IMAGE_STATUS

@rmackay9
Copy link
Contributor

rmackay9 commented Aug 7, 2024

We should implement MAV_CMD_CAMERA_STOP_TRACKING

center_x = (x + w) // 2
center_y = (y + h) // 2
cv2.circle(frame, (center_x, center_y), 3, (0, 255, 0), -1)
#print("Center of the face: ({}, {})".format(center_x, center_y))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of commented out lines, perhaps put a debug definition at the top to allow turning on/off debug


# gst-launch-1.0 -v udpsrc port=5600 caps='application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264' ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false

gst_pipeline = (
Copy link
Contributor

@rmackay9 rmackay9 Aug 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's get a pipeline for at least the siyi camera gimbals using an ethernet connection to the companion computer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should move this definition to the top to make it easier to find and possibly we should try and create this pipe line based on arguments input by the caller

libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
connection.wait_heartbeat()
print("Heartbeat received from system (system %u component %u)" % (connection.target_system, connection.target_component))
# Send a heartbeat back to register the device
connection.mav.heartbeat_send(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heartbeats must be sent regularly - at, say, 1Hz

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a separate thread right ?

libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
libraries/AP_Camera/examples/tracking.py Outdated Show resolved Hide resolved
libraries/AP_Camera/examples/tracking.py Outdated Show resolved Hide resolved
#print("Gimbal manager pitch and yaw angles message sent.")
send_gimbal_manager_pitch_yaw_angles(0, 0, 0, 0, 0, 0, float("NaN"),float("NaN"))
def send_command():
global centre_x, center_y
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks odd

libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
Comment on lines 135 to 136
except:
pass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't acceptable in any Python script. You'd be surprised at how painful this can be.

Catch the exceptions you know about.

Copy link
Collaborator

@Hwurzburg Hwurzburg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs exclusion in minimize include file and build options/extract features files added


# Start listening for MAVLink messages
while True:
msg = connection.recv_match(type='COMMAND_LONG', blocking=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the call need to be blocking here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont you think it should be ?

"rtph264depay ! h264parse ! queue ! avdec_h264 ! videoconvert ! appsink"
)

cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default versions of opencv-python and opencv-contrib-python do not have gstreamer support enabled. A custom build of the Python packages from source is required for this (at least this is the case on macOS). To reduce the complexity it may be easier to use the gstreamer Python bindings to capture the video stream and then make this available to opencv. The BlueROV docs have a guide for this: https://www.ardusub.com/developers/opencv.html.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you're right.

# Main function
def main():
# Send camera information message
send_camera_information(connection)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There seems to be two ways to ensure that the MAV_CMD_CAMERA_TRACK_POINT response expected below is triggered when sending the camera info. One is in AP_Camera::handle_command(const mavlink_command_int_t &packet) and requires a MAV_CMD_CAMERA_TRACK_POINT message be sent. The other is to use an aux switch to enable camera image tracking. This is the setup I used for testing.

RC13_OPTION      174.0       # Camera Image Tracking

Along with

param set CAM1_TRK_ENABLE 1
param set CAM1_TRK_SYSID 245
param set CAM1_TRK_COMPID 0

then run the script, enable tracking with

MANUAL> rc 13 1900

and check the output.

Either way all of this needs to be documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good way actually, the thing is RC switch based tracking will tell only to start tracking anything in the frame. atlast we need to send the CAMERA_TRACKING messages to work with specific objects

@Hwurzburg Hwurzburg added the WikiNeeded needs wiki update label Aug 18, 2024
@khanasif786 khanasif786 marked this pull request as draft August 20, 2024 21:44
@khanasif786 khanasif786 changed the title AP_Camera: Add Camera Tracking functionality AP_Camera: Add Camera Tracking functionality (WIP) Aug 20, 2024
Copy link
Contributor Author

@khanasif786 khanasif786 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
connection.wait_heartbeat()
print("Heartbeat received from system (system %u component %u)" % (connection.target_system, connection.target_component))
# Send a heartbeat back to register the device
connection.mav.heartbeat_send(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a separate thread right ?

libraries/AP_Camera/examples/send_camera_information.py Outdated Show resolved Hide resolved
import math
from ultralytics import YOLO

master = mavutil.mavlink_connection('127.0.0.1:14560')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need something like requirements.txt, i actually added a comment on top just for now.

libraries/AP_Camera/examples/tracking.py Outdated Show resolved Hide resolved
libraries/AP_Camera/examples/tracking.py Outdated Show resolved Hide resolved
"rtph264depay ! h264parse ! queue ! avdec_h264 ! videoconvert ! appsink"
)

cap = cv2.VideoCapture(gst_pipeline, cv2.CAP_GSTREAMER)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you're right.

# faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5, minSize=(30, 30))
faces= [final_list]
if len(faces) == 0:
# Do something if no faces were detected
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isnt that should be sent by the FC ? i.e.
CAMERA_TRACKING_IMAGE_STATUS

@rmackay9
Copy link
Contributor

rmackay9 commented Aug 21, 2024

@khanasif786, thanks for all your efforts on this. Could you rebase this on master too?

Let's also make it "ready for review" instead of "WIP"

@khanasif786 khanasif786 marked this pull request as ready for review August 21, 2024 05:16
@khanasif786 khanasif786 changed the title AP_Camera: Add Camera Tracking functionality (WIP) AP_Camera: Add Camera Tracking functionality Aug 21, 2024
@khanasif786 khanasif786 force-pushed the mav_cmd_camera_final branch 2 times, most recently from 8c94c12 to 7dd51ed Compare August 22, 2024 20:10
@khanasif786 khanasif786 force-pushed the mav_cmd_camera_final branch from 7dd51ed to 766f08a Compare August 30, 2024 05:53
@amilcarlucas
Copy link
Contributor

 Binary Name      Text [B]         Data [B]     BSS (B)        Total Flash Change [B] (%)      Flash Free After PR (B)
---------------  ---------------  -----------  -------------  ----------------------------  -------------------------
antennatracker   916 (+0.0688%)   0 (0.0000%)  -4 (-0.0015%)  916 (+0.0687%)                                   631372
arduplane        1048 (+0.0583%)  0 (0.0000%)  0 (0.0000%)    1048 (+0.0582%)                                  164728
blimp            916 (+0.0677%)   0 (0.0000%)  4 (+0.0015%)   916 (+0.0675%)                                   609112
arducopter-heli  1076 (+0.0598%)  0 (0.0000%)  4 (+0.0015%)   1076 (+0.0597%)                                  162656
arducopter       1072 (+0.0596%)  0 (0.0000%)  0 (0.0000%)    1072 (+0.0594%)                                  161680
ardusub          1088 (+0.0684%)  0 (0.0000%)  0 (0.0000%)    1088 (+0.0683%)                                  371252
ardurover        1060 (+0.0643%)  0 (0.0000%)  4 (+0.0015%)   1060 (+0.0642%)                                  313360

Copy link
Collaborator

@Hwurzburg Hwurzburg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still needs the changes I requested

@khanasif786 khanasif786 changed the title AP_Camera: Add Camera Tracking functionality AP_Camera: Add Camera Tracking functionality (WIP) Sep 11, 2024
const uint8_t fw_ver_build = (camera_settings._cam_info.firmware_version & 0xFF000000) >> 24;

// display camera info to user
gcs().send_text(MAV_SEVERITY_INFO, "Camera: %s.32 %s.32 fw:%u.%u.%u.%u",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be %.32s instead, probably carried over from the code before #27562

}

_link->send_message(MAVLINK_MSG_ID_COMMAND_LONG, (const char*)&pkt);
GCS_SEND_TEXT(MAV_SEVERITY_WARNING,"sent message to device sysid %d and comp %d",tracking_device_sysid,tracking_device_compid);
Copy link
Contributor

@srmainwaring srmainwaring Oct 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be removed (or should be MAV_SEVERITY_INFO) , and the sysid, compid info added to the Tracking: New Tracking request message on L28

@srmainwaring
Copy link
Contributor

srmainwaring commented Oct 7, 2024

@khanasif786, I think perhaps the follow-functionality should be split into a separate PR, with this one focussing on the core camera tracking changes.

The addition of MSG_CAMERA_TRACKING_IMAGE_STATUS is needed though if we are to run the tracker on a companion computer and want to send the GCS information about the current bounding box so it can be displayed in the GUI. I'm running into just this issue in testing.

I've written a MAVProxy module (camtrack) to test this PR in simulation and on hardware. There's a mavproxy GUI module to engage / disengage the tracker, and a separate headless module that may run on either the GCS computer, or on the companion computer.

It's working in simulation, still having a few issues setting up correct sys_id and component_id for all components on hardware (CubeOrangePlus with RPi4 companion). AFAICT the RPi4 copes with the cv2.legacy.TrackerCSTR tracker.

The MAVProxy code is here: https://github.com/srmainwaring/MAVProxy/tree/wips/wip-camera-tracking. It is a WIP with a lot of debug message code included that will eventually be pruned. Let me know if you'd like a walk through.

A rebase of this PR on master here: https://github.com/srmainwaring/ardupilot/tree/mav_cmd_camera_final_rebased. I'd force push, but don't have access. There are a few conflicts resolved.

break;
}

GCS_SEND_TEXT(MAV_SEVERITY_INFO,"Tracking: New Tracking request");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Message prefix should be consistent: AP_Camera: is used elsewhere.

Perhaps add sysid, compid here as this is useful information when setting up the system, and if they are not correct the function returns early (so the message including them below is not reported).

Comment on lines +229 to +233
enum CAMERA_TRACKING_STATUS_FLAGS : uint8_t {
CAMERA_TRACKING_STATUS_FLAGS_IDLE,
CAMERA_TRACKING_STATUS_FLAGS_ACTIVE,
CAMERA_TRACKING_STATUS_FLAGS_ERROR
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shadows

#define HAVE_ENUM_CAMERA_TRACKING_STATUS_FLAGS
typedef enum CAMERA_TRACKING_STATUS_FLAGS
{
   CAMERA_TRACKING_STATUS_FLAGS_IDLE=0, /* Camera is not tracking | */
   CAMERA_TRACKING_STATUS_FLAGS_ACTIVE=1, /* Camera is tracking | */
   CAMERA_TRACKING_STATUS_FLAGS_ERROR=2, /* Camera tracking in error state | */
   CAMERA_TRACKING_STATUS_FLAGS_ENUM_END=3, /*  | */
} CAMERA_TRACKING_STATUS_FLAGS;
#endif

in mavlink/v2.0/common/common.h

handle_message_camera_information(chan,msg);
break;
case MAVLINK_MSG_ID_CAMERA_TRACKING_IMAGE_STATUS:
handle_message_camera_tracking_image_status(chan,msg);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing break. Compilation with clang fails.

@@ -86,6 +86,14 @@ class AP_Camera_Backend
// p1,p2 are in range 0 to 1. 0 is left or top, 1 is right or bottom
bool set_tracking(TrackingType tracking_type, const Vector2f& top_left, const Vector2f& bottom_right);

// returns true if the objkect to be tracked is visible in the frame
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sp. objkect -> object

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WikiNeeded needs wiki update
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants