Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
864111e
started on the rpi interface
mountainduu Jan 25, 2025
078eae9
[LIB] add boost
dzodkin33 Jan 29, 2025
c733592
[ADD] some basic socket design ideas
dzodkin33 Jan 29, 2025
f94e54a
hold
dzodkin33 Feb 6, 2025
d55398d
[ADD] TCP interfaces, data structs
dzodkin33 Feb 25, 2025
efe4aa1
[add] implementation files
dzodkin33 Feb 25, 2025
9d082df
[ADD] changed headers, constr and connect funcs in cpp
dzodkin33 Feb 28, 2025
8f7530f
[ADD] basic client + send function
dzodkin33 Mar 7, 2025
7d65cf6
TCP Client and Server
smhitle Apr 15, 2025
bcfdaa0
merge main
AskewParity Apr 18, 2025
6e3b256
change boost import
AskewParity Apr 18, 2025
cb845f6
added VERY INEFFICIENT way to make serialization to work
AskewParity Apr 18, 2025
a396fa6
Changes to the client. Modified interface.hpp/.cpp to match the requi…
smhitle May 6, 2025
83e9ef6
chore: remove boost:serialization
AskewParity May 7, 2025
00d6adf
Undid changes to interface.cpp. Provided skeleton code, now compiles
smhitle May 8, 2025
7548cfb
Prototypal code for the entire process
smhitle May 9, 2025
2a3b163
Testing on jetson
smhitle May 9, 2025
d5a7adf
Added log statements for debugging
smhitle May 9, 2025
d573496
Added a mock rpi server
smhitle May 9, 2025
0d12b7f
Deleted unused files, switched to UDP instead of TCP
smhitle May 15, 2025
6c68c3f
Added server mock stuff
smhitle May 16, 2025
4121c05
Changed cout's to LOG_F's
smhitle May 18, 2025
b8eb719
Can read in udp packets correctly (hopefully)
smhitle May 22, 2025
4d3f717
Updated mock udp server
smhitle May 25, 2025
6f78c76
Updated cmake for server mock
smhitle May 25, 2025
19cacc7
Mock server works for dev container purposes
smhitle May 25, 2025
b1ba268
Merge remote-tracking branch 'origin' into dev/camera/tcp-socket/tyler
AskewParity Nov 9, 2025
a9f90d7
chore: update integration/cmake
AskewParity Nov 9, 2025
d0d76d4
fix: mock camera (merge incorrect)
AskewParity Nov 9, 2025
98d302a
fix: linking issue for camera and mavlink
AskewParity Nov 14, 2025
2e1baf6
chore: removed deprecated tcp files
miyatakazuya Jan 25, 2026
43bd3ca
feat: update rpi config + plane request logic
miyatakazuya Jan 25, 2026
4140fd7
bug: fixed cmake
miyatakazuya Jan 25, 2026
ee20f3d
feat: matched client to specifications. Socket still times out sometimes
miyatakazuya Jan 25, 2026
f4cdabb
bug: compilation fixes
miyatakazuya Jan 25, 2026
a11407a
feat: added camera count and interval
miyatakazuya Jan 25, 2026
abbb74a
fix: filename collision
miyatakazuya Feb 5, 2026
cf16f78
kaz codes looky looky here
dsoto0125 Feb 20, 2026
0feb640
kaz looky looky part 2
dsoto0125 Feb 20, 2026
250d648
Merge branch 'main' into feat/pi-client
AskewParity Feb 22, 2026
5e69301
feat: added mav
miyatakazuya Feb 22, 2026
38491b3
feat: added cmake changes
miyatakazuya Feb 24, 2026
080d5ab
fix: add io_context to state
miyatakazuya Feb 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ include(${DEPS_DIRECTORY}/matplot/matplot.cmake)
include(${DEPS_DIRECTORY}/protobuf/protobuf.cmake)
include(${DEPS_DIRECTORY}/loguru/loguru.cmake)
include(${DEPS_DIRECTORY}/imagemagick/imagemagick.cmake)
include(${DEPS_DIRECTORY}/boost/boost.cmake)
# =============================

# =============================
Expand Down
2 changes: 1 addition & 1 deletion configs/dev.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
},
"camera": {
"_comment": "See CameraConfig struct in datatypes.hpp for detailed explanations",
"type": "mock",
"type": "PiCamera",
"save_dir": "/workspaces/obcpp/images/mock",
"save_images_to_file": true,
"mock": {
Expand Down
16 changes: 16 additions & 0 deletions deps/boost/boost.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
function(target_add_boost target_name)
include(FetchContent)

FetchContent_Declare(boost
URL https://github.com/boostorg/boost/releases/download/boost-1.87.0/boost-1.87.0-b2-nodocs.tar.gz
URL_HASH SHA256=d6c69e4459eb5d6ec208250291221e7ff4a2affde9af6e49c9303b89c687461f
DOWNLOAD_EXTRACT_TIMESTAMP true
)
FetchContent_MakeAvailable(boost)
# target_link_libraries(${target_name} PRIVATE
# boost
# )
target_include_directories(${target_name} PRIVATE ${boost_SOURCE_DIR})


endfunction()
2 changes: 1 addition & 1 deletion include/camera/interface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,4 @@ class CameraInterface {
std::shared_ptr<MavlinkClient> mavlinkClient) = 0;
};

#endif // INCLUDE_CAMERA_INTERFACE_HPP_
#endif // INCLUDE_CAMERA_INTERFACE_HPP_
61 changes: 61 additions & 0 deletions include/camera/rpi.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#ifndef INCLUDE_CAMERA_RPI_HPP_
#define INCLUDE_CAMERA_RPI_HPP_

#include <string>
#include <memory>
#include <optional>
#include <shared_mutex>
#include <thread>
#include <deque>
#include <vector>

#include <nlohmann/json.hpp>
#include "camera/interface.hpp"
#include "network/mavlink.hpp"
#include "network/udp_client.hpp"

using json = nlohmann::json;
using namespace std::chrono_literals; // NOLINT

namespace asio = boost::asio;

const std::uint8_t START_REQUEST = 's';
const std::uint8_t PICTURE_REQUEST = 'I';
const std::uint8_t END_REQUEST = 'e';
const std::uint8_t LOCK_REQUEST = 'l';

class RPICamera : public CameraInterface {
private:
UDPClient client;
asio::io_context io_context_;
std::atomic_bool connected;

/**
* Converts the 3-plane raw data to BGR cv::Mat, handling stride/padding
*/
std::optional<cv::Mat> imgConvert(const std::vector<std::vector<uint8_t>>& planes);

/**
* Reads the 3 planes (Y, U, V) from the camera
*/
std::vector<std::vector<uint8_t>> readImage();

public:
explicit RPICamera(CameraConfig config, asio::io_context* io_context_);
~RPICamera();

void connect() override;
bool isConnected() override;

std::optional<ImageData> getLatestImage() override {return std::nullopt;}
std::deque<ImageData> getAllImages() override {return std::deque<ImageData>();}

std::optional<ImageData> takePicture(const std::chrono::milliseconds& timeout, std::shared_ptr<MavlinkClient> mavlinkClient) override;

void startTakingPictures(const std::chrono::milliseconds& interval, std::shared_ptr<MavlinkClient> mavlinkClient) override;
void stopTakingPictures() override;
void startStreaming() override;
void ping();
};

#endif
4 changes: 4 additions & 0 deletions include/core/mission_state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <queue>
#include <unordered_set>
#include <vector>
#include <boost/asio.hpp>

#include "camera/interface.hpp"
#include "core/mission_parameters.hpp"
Expand Down Expand Up @@ -113,6 +114,7 @@ class MissionState {
OBCConfig config;

std::optional<airdrop_t> next_airdrop_to_drop;
boost::asio::io_context raspy_io;

private:
std::mutex converter_mut;
Expand Down Expand Up @@ -143,6 +145,8 @@ class MissionState {
// with the detected_target specified by the index
std::array<size_t, NUM_AIRDROPS> cv_matches;

// boost::asio::io_context io_testies;

bool mappingIsDone;

void _setTick(Tick* newTick); // does not acquire the tick_mut
Expand Down
82 changes: 82 additions & 0 deletions include/network/camera_data.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef INCLUDE_NETWORK_CAMERA_DATA_HPP_
#define INCLUDE_NETWORK_CAMERA_DATA_HPP_

#include <iostream>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>

struct ImageData_t
{
int width;
int height;
size_t imageSizeBytes;
std::vector<std::uint8_t> imgBuffer;

template<class Archive>
void serialize(Archive & ar, const unsigned int version){
ar & width;
ar & height;
ar & imageSizeBytes;
ar & imgBuffer;
}
};

// What does OBC needs from camera
enum class RequestType_t
{
SENDIMAGE
};

// TODO: unsure if these need to be in a namespace or not
template<class Archive>
void serialize(Archive & ar, RequestType_t & request, const unsigned int version) {
ar & static_cast<int>(request); // have to type cast enum class
}

// What is the status of the request (debugging + error handling)
enum class ResponseType_t
{
SUCC,
ERROR
};

// TODO: unsure if these need to be in a namespace or not
template<class Archive>
void serialize(Archive & ar, ResponseType_t & response, const unsigned int version) {
ar & static_cast<int>(response); // have to type cast enum class
}

// OBC requesting camera for something
struct CameraRequest_t
{
// device id that requests (for debugging)
int pid;

// type of request, we should figure out edge cases
RequestType_t requestType;

template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & pid;
ar & requestType;
}
};

// Response back from camera to OBC
struct CameraResponse_t
{
int pid;
ResponseType_t responseType;
ImageData_t imageData;

template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
ar & pid;
ar & responseType;
ar & imageData;
}
};

#endif
31 changes: 31 additions & 0 deletions include/network/rpi_connection.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef INCLUDE_NETWORK_RPI_CONNECTION_HPP_
#define INCLUDE_NETWORK_RPI_CONNECTION_HPP_

#include <iostream>
#pragma once
#include <cstdint>

// Image Config
inline uint32_t IMG_WIDTH = 1456;
inline uint32_t IMG_HEIGHT = 1088;
inline uint32_t IMG_BUFFER = IMG_WIDTH * IMG_HEIGHT * 3 / 2;

// Libcamera Strides/Padding
const uint32_t STRIDE_Y = 1472;
const uint32_t STRIDE_UV = 736;

// Network Config
const std::string SERVER_IP = "192.168.77.2";
const int SERVER_PORT = 25565;

const int headerSize = 12;
const uint32_t EXPECTED_MAGIC = 0x12345678;
const size_t CHUNK_SIZE = 1024;

struct Header {
uint32_t magic;
uint32_t total_chunks;
uint32_t mem_size;
};

#endif
28 changes: 28 additions & 0 deletions include/network/serialize.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef INCLUDE_NETWORK_SERIALIZE_HPP_
#define INCLUDE_NETWORK_SERIALIZE_HPP_

#include <boost/asio.hpp>

/*
Includes some reference on how to serialize and deserialize structs
*/

namespace serialh {
// TODO: make this so that it returns any struct
template <typename T>
void serialize(T* response, boost::asio::streambuf* buf) {
std::ostream os(buf);
boost::archive::binary_oarchive oa(os);
oa << *response;
}

// TODO: make this so that it returns any struct
template <typename T>
void deserialize(T* response, boost::asio::streambuf* buf) {
std::istream is(buf);
boost::archive::binary_iarchive ia(is);
ia >> *response;
}
}

#endif
4 changes: 0 additions & 4 deletions include/network/server.hpp

This file was deleted.

31 changes: 31 additions & 0 deletions include/network/udp_client.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef INCLUDE_NETWORK_UDP_CLIENT_HPP_
#define INCLUDE_NETWORK_UDP_CLIENT_HPP_

#include <iostream>
#include <boost/asio.hpp>
#include <opencv2/opencv.hpp>
#include <loguru.hpp>
#include "rpi_connection.hpp"

namespace asio = boost::asio;

class UDPClient {
private:
asio::ip::udp::socket socket_;
std::string ip;
int port;

public:
UDPClient(asio::io_context* io_context_, std::string ip, int port);

// there isnt really a notion of connect with connectionless udp sockets
bool connect();

bool send(std::uint8_t request);

Header recvHeader();

std::vector<std::uint8_t> recvBody(const int mem_size, const int total_chunks);
};

#endif
35 changes: 35 additions & 0 deletions include/network/udp_server.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef INCLUDE_NETWORK_UDP_SERVER_HPP_
#define INCLUDE_NETWORK_UDP_SERVER_HPP_

#include <iostream>
#include <boost/asio.hpp>
#include <opencv2/opencv.hpp>
#include "network/rpi_connection.hpp"

namespace asio = boost::asio;

class UDPServer {
private:
std::string ip;
int port;
asio::ip::udp::socket socket_;

cv::Mat createBGR();

cv::Mat createYUV();

public:
UDPServer(asio::io_context* io_context_, std::string ip, int port);

bool start();

void send(asio::ip::udp::endpoint & endpoint);

void recv();

void handleRequest(char request, asio::ip::udp::endpoint & endpoint);

void shutdown();
};

#endif
5 changes: 4 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ target_link_libraries(obcpp_lib_mock INTERFACE

add_executable(${PROJECT_NAME} main.cpp)
target_include_directories(${PROJECT_NAME} PRIVATE ${INCLUDE_DIRECTORY} ${GEN_PROTOS_DIRECTORY})
target_link_libraries(${PROJECT_NAME} PRIVATE obcpp_lib)
target_link_libraries(${PROJECT_NAME} PRIVATE
obcpp_lib
)
target_add_protobuf(${PROJECT_NAME})
target_add_torch(${PROJECT_NAME})
target_add_torchvision(${PROJECT_NAME})
Expand All @@ -53,6 +55,7 @@ target_add_mavsdk(${PROJECT_NAME})
target_add_opencv(${PROJECT_NAME})
target_add_httplib(${PROJECT_NAME})
target_add_loguru(${PROJECT_NAME})
target_add_boost(${PROJECT_NAME})
target_add_onnxruntime(${PROJECT_NAME})
# for some reason calling target_add_imagemagick here conflicts with, so we are including/linking without the function call
# target_add_imagemagick(${PROJECT_NAME})
Expand Down
6 changes: 4 additions & 2 deletions src/camera/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ set(LIB_NAME obcpp_camera)
set(FILES
interface.cpp
mock.cpp
rpi.cpp
picamera.cpp
)

SET(LIB_DEPS
obcpp_protos
# obcpp_network # circular dependency
obcpp_network # circular dependency - resolved at executable level
)

add_library(${LIB_NAME} STATIC
Expand All @@ -30,6 +31,7 @@ target_add_httplib(${LIB_NAME})
target_add_mavsdk(${LIB_NAME})
target_add_matplot(${LIB_NAME})
target_add_loguru(${LIB_NAME})
target_add_boost(${LIB_NAME})

target_include_directories(${LIB_NAME} PRIVATE ${ImageMagick_INCLUDE_DIRS})
target_link_libraries(${LIB_NAME} PRIVATE -Wl,--copy-dt-needed-entries ${ImageMagick_LIBRARIES})
target_link_libraries(${LIB_NAME} PRIVATE -Wl,--copy-dt-needed-entries ${ImageMagick_LIBRARIES})
Loading
Loading