Skip to content

New Thread for Picture Taking#364

Open
Vidyuth2 wants to merge 5 commits into
mainfrom
fix_race_condition_Vidhu
Open

New Thread for Picture Taking#364
Vidyuth2 wants to merge 5 commits into
mainfrom
fix_race_condition_Vidhu

Conversation

@Vidyuth2

Copy link
Copy Markdown

Added a thread to take pictures over search zone and run cv pipeline in cvloiter and fly_search

@Vidyuth2 Vidyuth2 requested a review from AskewParity May 15, 2026 00:24
@AskewParity AskewParity changed the title Fix race condition vidhu New Thread for Picture Taking May 15, 2026

@AskewParity AskewParity left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for doing this. This will go towards rearchitecting our codebase to be more modular.

I think the code would be better if you checked for the negative condition.

e.g.

if (condition) {
  a lot of code here
  a lot of code here
  a lot of code here
  a lot of code here
}

becomes

if (!condition) {
  continue;
}

a lot of code here
a lot of code here
a lot of code here
a lot of code here

Comment thread src/core/mission_state.cpp Outdated
Comment thread src/core/mission_state.cpp Outdated
Comment thread src/core/mission_state.cpp Outdated
bool in_zone = Environment::isPointInPolygon(airdrop_boundary, current_xyz);
if(in_zone){
auto now = getUnixTime_ms();
if ((now - last_photo_time) >= 300ms) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this magic number should be a config option.

Comment thread src/ticks/fly_search.cpp
this->state->setCVStatus(MissionState::CVStatus::None);
return new AirdropPrepTick(this->state);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

delete extra line

Comment thread src/ticks/fly_search.cpp
Comment on lines +60 to +99
auto [lat_deg, lng_deg] = state->getMav()->latlng_deg();
double altitude_agl_m = state->getMav()->altitude_agl_m();
GPSCoord current_pos = makeGPSCoord(lat_deg, lng_deg, altitude_agl_m);
auto converter = state->getCartesianConverter();

// IMPORTANT: currently hardcoded to assume hover search pathing, so it
// takes photos whenever it gets to a new waypoint (loiter position)
// if we were doing forward pathing would probably want to make it
// take photos at an interval but only when over the zone
auto curr_waypoint = this->state->getMav()->curr_waypoint();

if (this->curr_mission_item != curr_waypoint) {
LOG_F(INFO, "FlySearch Area reached (%zu, %d)", this->curr_mission_item, curr_waypoint);
for (int i = 0; i < this->state->config.pathing.coverage.hover.pictures_per_stop; i++) {
auto photo = this->state->getCamera()->takePicture(500ms, this->state->getMav());
if (state->config.camera.save_images_to_file) {
photo->saveToFile(state->config.camera.save_dir);
}

if (photo.has_value()) {
// Update the last photo time
this->last_photo_time = getUnixTime_ms();
// Run the pipeline on the photo
this->state->getCV()->runPipeline(photo.value());
// Convert GPS to local XYZ coords
if(converter){
XYZCoord current_xyz = converter->toXYZ(current_pos);
// Get the airdrop boundary polygon
Polygon airdrop_boundary = state->mission_params.getAirdropBoundary();
// Check if we're inside the airdrop zone
bool in_zone = Environment::isPointInPolygon(airdrop_boundary, current_xyz);

if(in_zone){
auto curr_waypoint = this->state->getMav()->curr_waypoint();

if (this->curr_mission_item != curr_waypoint) {
LOG_F(INFO, "FlySearch Area reached (%zu, %d)", this->curr_mission_item, curr_waypoint);
/*
for (int i = 0; i < this->state->config.pathing.coverage.hover.pictures_per_stop; i++) {
auto photo = this->state->getCamera()->takePicture(500ms, this->state->getMav());
if (state->config.camera.save_images_to_file) {
photo->saveToFile(state->config.camera.save_dir);
}

if (photo.has_value()) {
// Update the last photo time
this->last_photo_time = getUnixTime_ms();
// Run the pipeline on the photo
this->state->getCV()->runPipeline(photo.value());
}
}
*/
this->curr_mission_item = curr_waypoint;

return nullptr;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This code should be deleted/moved to the camera thread (it should take picture on waypoint for hover mode).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This still needs to be done (i.e. if it is migrated, delete the current code)

Comment thread src/ticks/fly_waypoints.cpp Outdated
Comment thread include/core/mission_state.hpp Outdated
Comment on lines +59 to +63
void zoneHandler(const std::chrono::milliseconds& interval,
std::shared_ptr<MavlinkClient> mavlinkClient);
void initThread(const std::chrono::milliseconds& interval,
std::shared_ptr<MavlinkClient> mavlinkClient);
void stopThread();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These names are very ambiguous. The camera is not the only separate thread that is running, nor is the aridrop_zone the only zone (or at least in years past).

@AskewParity AskewParity self-requested a review May 26, 2026 21:54

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  1. There are 3 new items in the config, only one new item in obc_config
  2. These aren't initialized

Comment thread src/core/mission_state.cpp
Comment thread src/ticks/fly_search.cpp
Comment on lines +60 to +99
auto [lat_deg, lng_deg] = state->getMav()->latlng_deg();
double altitude_agl_m = state->getMav()->altitude_agl_m();
GPSCoord current_pos = makeGPSCoord(lat_deg, lng_deg, altitude_agl_m);
auto converter = state->getCartesianConverter();

// IMPORTANT: currently hardcoded to assume hover search pathing, so it
// takes photos whenever it gets to a new waypoint (loiter position)
// if we were doing forward pathing would probably want to make it
// take photos at an interval but only when over the zone
auto curr_waypoint = this->state->getMav()->curr_waypoint();

if (this->curr_mission_item != curr_waypoint) {
LOG_F(INFO, "FlySearch Area reached (%zu, %d)", this->curr_mission_item, curr_waypoint);
for (int i = 0; i < this->state->config.pathing.coverage.hover.pictures_per_stop; i++) {
auto photo = this->state->getCamera()->takePicture(500ms, this->state->getMav());
if (state->config.camera.save_images_to_file) {
photo->saveToFile(state->config.camera.save_dir);
}

if (photo.has_value()) {
// Update the last photo time
this->last_photo_time = getUnixTime_ms();
// Run the pipeline on the photo
this->state->getCV()->runPipeline(photo.value());
// Convert GPS to local XYZ coords
if(converter){
XYZCoord current_xyz = converter->toXYZ(current_pos);
// Get the airdrop boundary polygon
Polygon airdrop_boundary = state->mission_params.getAirdropBoundary();
// Check if we're inside the airdrop zone
bool in_zone = Environment::isPointInPolygon(airdrop_boundary, current_xyz);

if(in_zone){
auto curr_waypoint = this->state->getMav()->curr_waypoint();

if (this->curr_mission_item != curr_waypoint) {
LOG_F(INFO, "FlySearch Area reached (%zu, %d)", this->curr_mission_item, curr_waypoint);
/*
for (int i = 0; i < this->state->config.pathing.coverage.hover.pictures_per_stop; i++) {
auto photo = this->state->getCamera()->takePicture(500ms, this->state->getMav());
if (state->config.camera.save_images_to_file) {
photo->saveToFile(state->config.camera.save_dir);
}

if (photo.has_value()) {
// Update the last photo time
this->last_photo_time = getUnixTime_ms();
// Run the pipeline on the photo
this->state->getCV()->runPipeline(photo.value());
}
}
*/
this->curr_mission_item = curr_waypoint;

return nullptr;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This still needs to be done (i.e. if it is migrated, delete the current code)

Comment on lines +123 to +139
auto curr_waypoint = this->getMav()->curr_waypoint();
if (this->curr_mission_item != curr_waypoint) {
LOG_F(INFO, "FlySearch Area reached (%zu, %d)",
this->curr_mission_item, curr_waypoint);
for (int i = 0; i < this->config.pathing.coverage.hover.pictures_per_stop; i++) {
auto photo = this->getCamera()->takePicture(500ms, this->getMav());
if (this->config.camera.save_images_to_file) {
photo->saveToFile(this->config.camera.save_dir);
}

if (photo.has_value()) {
last_photo_time = getUnixTime_ms();
this->getCV()->runPipeline(photo.value());
}
}
this->curr_mission_item = curr_waypoint;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should only be the case if we are doing coverage by hover

Comment on lines +141 to +151
if ((now - last_photo_time) >= std::chrono::milliseconds(this->config.camera.photo_delay)) {
auto photo = this->getCamera()->takePicture(100ms, this->getMav());
if (this->config.camera.save_images_to_file) {
photo->saveToFile(this->config.camera.save_dir);
}

if (photo.has_value()&&((this->getTickID() == TickID::FlySearch)||
(this->getTickID() == TickID::CVLoiter))) {
this->getCV()->runPipeline(photo.value());
}
last_photo_time = getUnixTime_ms();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same with this and forward

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants