Skip to content

Commit

Permalink
Implement Flysearch + CVLoiter Tick (#191)
Browse files Browse the repository at this point in the history
* Added function prototype

* Modified TODOs

* added prototype annotations for CVLoiter

* Added CVLoiter constructor

* Added CV Aggregator

* Moved inits to header file

* fixed header, added comments

* stashed changes before merge main

* Fixed some constructor references

* Added Saliency model path

* Made hierachy changes (Moved CV setup to mission_prep)

* added flysearch fixes

* Added Bottle comparison prototype

* Finalized Both ticks

* Fixed some compiling errors

* added more comments, removed redundent inits

* code review & misc fixes

* fixes for lint

* fix test and lint

---------

Co-authored-by: Tyler Lentz <[email protected]>
  • Loading branch information
miyatakazuya and Tyler-Lentz authored Jun 10, 2024
1 parent 7aae933 commit 07a3f7a
Show file tree
Hide file tree
Showing 28 changed files with 266 additions and 131 deletions.
6 changes: 3 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

// Enable network mode host if on Linux and testing airdrop connectivity
// "appPort": [ "45906:45906/udp", "45907:45907/udp" ], // port forward airdrop ports for local testing
// "runArgs": [
// "--network=host"
// ],
"runArgs": [
"--network=host"
],

"extensions.verifySignature": false,

Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ if(CPPLINT)
# Do not require licenses, TODO assignment, Google versions of C++ libs
# also don't check for runtime/references since Google's public style guidelines are behind https://github.com/cpplint/cpplint/issues/148
--exclude=../include/udp_squared
--exclude=../src/utilities/base64.cpp
--filter=-legal,-readability/todo,-build/c++11,-runtime/references
--linelength=100
--recursive
Expand Down
7 changes: 6 additions & 1 deletion configs/config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"logging": {
"dir": "/workspaces/obcpp/logs"
"dir": "/obcpp/logs"
},
"network": {
"mavlink": {
Expand Down Expand Up @@ -37,6 +37,11 @@
"unguided_drop_distance_m": 50.0
}
},
"cv": {
"matching_model_dir": "/obcpp/models/target_siamese_1.pt",
"segmentation_model_dir": "/obcpp/models/fcn.pth",
"saliency_model_dir": "/obcpp/models/torchscript_19.pth"
},
"camera": {
"_comment": "See CameraConfig struct in datatypes.hpp for detailed explanations",
"type": "lucid",
Expand Down
5 changes: 5 additions & 0 deletions configs/dev-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
"unguided_drop_distance_m": 50.0
}
},
"cv": {
"matching_model_dir": "/workspaces/obcpp/models/target_siamese_1.pt",
"segmentation_model_dir": "/workspaces/obcpp/models/fcn.pth",
"saliency_model_dir": "/workspaces/obcpp/models/torchscript_19.pth"
},
"camera": {
"_comment": "See CameraConfig struct in datatypes.hpp for detailed explanations",
"type": "mock",
Expand Down
1 change: 1 addition & 0 deletions include/camera/lucid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class LucidCamera : public CameraInterface {
*/
std::optional<ImageData> takePicture(const std::chrono::milliseconds& timeout,
std::shared_ptr<MavlinkClient> mavlinkClient) override;

void startStreaming() override;

private:
Expand Down
13 changes: 8 additions & 5 deletions include/core/mission_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Tick;

class MissionState {
public:
MissionState();
explicit MissionState(OBCConfig config);
~MissionState();

const std::optional<CartesianConverter<GPSProtoVec>>& getCartesianConverter();
Expand All @@ -44,6 +44,9 @@ class MissionState {
void setInitPath(std::vector<GPSCoord> init_path);
const std::vector<GPSCoord>& getInitPath();

void setSearchPath(std::vector<GPSCoord> search_path);
const std::vector<GPSCoord>& getSearchPath();

/*
* Gets a locking reference to the underlying tick for the given tick subclass T.
*
Expand Down Expand Up @@ -93,10 +96,8 @@ class MissionState {
void setCamera(std::shared_ptr<CameraInterface> camera);

MissionParameters mission_params; // has its own mutex
RRTConfig rrt_config;
AirdropSearchConfig coverage_pathing_config;
CameraConfig camera_config;
float takeoff_alt_m;

OBCConfig config;

private:
std::mutex converter_mut;
Expand All @@ -106,7 +107,9 @@ class MissionState {
std::shared_ptr<Tick> tick;

std::mutex init_path_mut; // for reading/writing the initial path
std::mutex search_path_mut; // for reading/writing the search path
std::vector<GPSCoord> init_path;
std::vector<GPSCoord> search_path;

std::shared_ptr<MavlinkClient> mav;
std::shared_ptr<AirdropClient> airdrop;
Expand Down
5 changes: 4 additions & 1 deletion include/cv/aggregator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ struct CVResults {
std::unordered_map<BottleDropIndex, size_t> matches;
};



class CVAggregator {
public:
explicit CVAggregator(Pipeline p);
explicit CVAggregator(Pipeline&& p);

~CVAggregator();

void runPipeline(const ImageData& image);
Expand Down
12 changes: 12 additions & 0 deletions include/network/gcs_routes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,16 @@ DEF_GCS_HANDLE(Post, takeoff, manual);
*/
DEF_GCS_HANDLE(Post, takeoff, autonomous);

/**
* POST /targets/validate
* ---
*/
DEF_GCS_HANDLE(Post, targets, validate);

/**
* POST /targets/reject
* ---
*/
DEF_GCS_HANDLE(Post, targets, reject);

#endif // INCLUDE_NETWORK_GCS_ROUTES_HPP_
27 changes: 24 additions & 3 deletions include/ticks/cv_loiter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,41 @@
#include <chrono>

#include "ticks/tick.hpp"
#include <opencv2/opencv.hpp>
#include <loguru.hpp>

#include "cv/pipeline.hpp"
#include "cv/aggregator.hpp"
#include "protos/obc.pb.h"


/*
* Stop taking photos, loiter away from the search zone
* and wait until CV processing is done.
* loiter away from the search zone and wait until CV processing is done.
* If CV Results are validated, proceed to Airdrop Prep.
*
* See https://tritonuas.github.io/wiki/software/obc/tick_architecture/ticks/cvloiter/
*/

class CVLoiterTick : public Tick {
public:
explicit CVLoiterTick(std::shared_ptr<MissionState> state);
/*
* Status of the CV processing
* (Will be) Modified through GCS Manual Control
*/
enum class Status {
None = 0,
Validated = 1,
Rejected = 2,
};

explicit CVLoiterTick(std::shared_ptr<MissionState> state);
std::chrono::milliseconds getWait() const override;

void setStatus(Status status);
Tick* tick() override;

private:
Status status;
};

#endif // INCLUDE_TICKS_CV_LOITER_HPP_
7 changes: 6 additions & 1 deletion include/ticks/fly_search.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,24 @@

#include "ticks/tick.hpp"


/*
* Take photos and run CV pipeline while flying over
* search region
*
* See https://tritonuas.github.io/wiki/software/obc/tick_architecture/ticks/flysearch/
*/

class FlySearchTick : public Tick {
public:
explicit FlySearchTick(std::shared_ptr<MissionState> state);

std::chrono::milliseconds getWait() const override;

Tick* tick() override;

private:
Polygon airdrop_boundary;
std::chrono::milliseconds last_photo_time;
};

#endif // INCLUDE_TICKS_FLY_SEARCH_HPP_
4 changes: 4 additions & 0 deletions include/ticks/mission_prep.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
#include <string>

#include "ticks/tick.hpp"
#include "cv/pipeline.hpp"
#include "cv/aggregator.hpp"

#define NUMBOTTLES 5

/*
* Checks every second whether or not a valid mission has been uploaded.
Expand Down
9 changes: 6 additions & 3 deletions include/utilities/obc_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ struct OBCConfig {
float altitude_m;
} takeoff;

struct {
std::string matching_model_dir;
std::string segmentation_model_dir;
std::string saliency_model_dir;
} cv;

RRTConfig rrt_config;
AirdropSearchConfig coverage_pathing_config;
AirdropApproachConfig airdrop_pathing_config;
CameraConfig camera_config;

// Load user specified config json, or make a new one
OBCConfig(int argc, char* argv[]);

private:
void makeDefault();
};

#endif // INCLUDE_UTILITIES_OBC_CONFIG_HPP_
34 changes: 17 additions & 17 deletions src/camera/lucid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,15 @@ void LucidCamera::connect() {
}

LucidCamera::~LucidCamera() {
// aquire locks to Arena System and Device
WriteLock systemLock(this->arenaSystemLock);
WriteLock deviceLock(this->arenaDeviceLock);
CATCH_ARENA_EXCEPTION("closing Arena System",
this->system->DestroyDevice(this->device);
Arena::CloseSystem(this->system););
}

void LucidCamera::startStreaming() {
if (!this->isConnected()) {
LOG_F(ERROR, "LUCID Camera not connected. Cannot start streaming");
return;
}
// aquire locks to Arena System and Device
WriteLock systemLock(this->arenaSystemLock);
WriteLock deviceLock(this->arenaDeviceLock);

WriteLock lock(this->arenaDeviceLock);
CATCH_ARENA_EXCEPTION("starting stream",
this->device->StartStream(););
CATCH_ARENA_EXCEPTION("closing Arena System",
this->system->DestroyDevice(this->device);
Arena::CloseSystem(this->system););
}


void LucidCamera::startTakingPictures(const std::chrono::milliseconds& interval,
std::shared_ptr<MavlinkClient> mavlinkClient) {
if (this->isTakingPictures) {
Expand Down Expand Up @@ -328,6 +317,17 @@ std::optional<ImageData> LucidCamera::takePicture(const std::chrono::millisecond
return {};
}

void LucidCamera::startStreaming() {
if (!this->isConnected()) {
LOG_F(ERROR, "LUCID Camera not connected. Cannot start streaming");
return;
}

WriteLock lock(this->arenaDeviceLock);
CATCH_ARENA_EXCEPTION("starting stream",
this->device->StartStream(););
}

std::optional<cv::Mat> LucidCamera::imgConvert(Arena::IImage* pImage) {
CATCH_ARENA_EXCEPTION("converting Arena Image to OpenCV",
// convert original image to BGR8 which is what opencv expects.
Expand Down
14 changes: 11 additions & 3 deletions src/core/mission_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
#include "utilities/logging.hpp"
#include "utilities/obc_config.hpp"

// in future might add to this
MissionState::MissionState() {
}
MissionState::MissionState(OBCConfig config): config(config) {}

// Need to explicitly define now that Tick is no longer an incomplete class
// See:
Expand Down Expand Up @@ -78,6 +76,16 @@ const std::vector<GPSCoord>& MissionState::getInitPath() {
return this->init_path;
}

void MissionState::setSearchPath(std::vector<GPSCoord> search_path) {
Lock lock(this->search_path_mut);
this->search_path = search_path;
}

const std::vector<GPSCoord>& MissionState::getSearchPath() {
Lock lock(this->search_path_mut);
return this->search_path;
}

std::shared_ptr<MavlinkClient> MissionState::getMav() { return this->mav; }

void MissionState::setMav(std::shared_ptr<MavlinkClient> mav) { this->mav = mav; }
Expand Down
22 changes: 12 additions & 10 deletions src/core/obc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cstdint>
#include <future>

#include "camera/mock.hpp"
#include "camera/lucid.hpp"
#include "core/obc.hpp"
#include "core/mission_state.hpp"
Expand All @@ -22,12 +23,9 @@ extern "C" {
OBC::OBC(OBCConfig config) {
int gcs_port = config.network.gcs.port;

this->state = std::make_shared<MissionState>();
this->state = std::make_shared<MissionState>(config);
this->state->setTick(new MissionPrepTick(this->state));
this->state->rrt_config = config.rrt_config;
this->state->camera_config = config.camera_config;
this->state->takeoff_alt_m = config.takeoff.altitude_m;
this->state->coverage_pathing_config = config.coverage_pathing_config;
this->state->config = config;
this->gcs_server = std::make_unique<GCSServer>(gcs_port, this->state);

// Don't need to look at these futures at all because the connect functions
Expand All @@ -37,13 +35,17 @@ OBC::OBC(OBCConfig config) {
{this->connectMavlink(config.network.mavlink.connect);});
this->connectAirdropThread = std::thread([this]{this->connectAirdrop();});

if (this->state->camera_config.type == "mock") {
this->state->setCamera(std::make_shared<MockCamera>(this->state->camera_config));
} else if (this->state->camera_config.type == "lucid") {
this->state->setCamera(std::make_shared<LucidCamera>(this->state->camera_config));
if (this->state->config.camera_config.type == "mock") {
this->state->setCamera(std::make_shared<MockCamera>(this->state->config.camera_config));
} else if (this->state->config.camera_config.type == "lucid") {
#ifdef ARENA_SDK_INSTALLED
this->state->setCamera(std::make_shared<LucidCamera>(this->state->config.camera_config)); //NOLINT
#else
LOG_F(FATAL, "Attempting to create Lucid Camera without having ArenaSDK installed.");
#endif
} else {
// default to mock if it's neither "mock" or "lucid"
this->state->setCamera(std::make_shared<MockCamera>(this->state->camera_config));
this->state->setCamera(std::make_shared<MockCamera>(this->state->config.camera_config));
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/cv/aggregator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "utilities/logging.hpp"
#include "utilities/lockptr.hpp"

CVAggregator::CVAggregator(Pipeline p): pipeline{p} {
CVAggregator::CVAggregator(Pipeline&& p): pipeline{p} {
this->num_worker_threads = 0;
this->results = std::make_shared<CVResults>();
this->results->matches[BottleDropIndex::A] = -1;
Expand Down
Loading

0 comments on commit 07a3f7a

Please sign in to comment.