Skip to content

Commit d9b1080

Browse files
Ackimixsmodelec
andauthored
Develop strat 7 (#32)
Co-authored-by: modelec <modelec-isen@gmail.com>
1 parent a8be82c commit d9b1080

80 files changed

Lines changed: 1571 additions & 1160 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Desktop/cam.desktop

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[Desktop Entry]
2+
Type=Application
3+
Name=Cam
4+
Comment=Cam
5+
Exec=/home/modelec/Modelec-ROS2/start_cam_ros2.sh
6+
Icon=utilities-terminal
7+
Terminal=true
8+
Categories=Utility;

build.rasp.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/bin/bash
2-
MAKEFLAGS="-j1" colcon build --symlink-install --executor sequential # --cmake-args -DCMAKE_BUILD_TYPE=Debug
2+
MAKEFLAGS="-j1" colcon build --symlink-install --executor sequential --cmake-args -DBUILD_FOR_RPI=ON --no-warn-unused-cli
33

44
source install/setup.bash

install.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ sudo apt upgrade -y
2121

2222
sudo apt install ros-dev-tools ros-jazzy-desktop -y
2323

24-
sudo apt-get install qt6-base-dev qt6-svg-dev libxml2-dev socat -y
24+
sudo apt-get install qt6-base-dev qt6-svg-dev qt6-multimedia-dev libxml2-dev socat -y
2525

2626
git submodule init
2727
git submodule update
@@ -45,4 +45,4 @@ gio set ~/Desktop/no_lidar.joy.ros2_launch_marcel.desktop "metadata::trusted" tr
4545
gio set ~/Desktop/no_lidar.ros2_launch_marcel.desktop "metadata::trusted" true
4646
gio set ~/Desktop/joy.ros2_launch_marcel.desktop "metadata::trusted" true
4747
gio set ~/Desktop/ros2_launch_marcel.desktop "metadata::trusted" true
48-
gio set ~/Desktop/no-gui.ros2_launch_marcel.desktop "metadata::trusted" true
48+
gio set ~/Desktop/no-gui.ros2_launch_marcel.desktop "metadata::trusted" true

simulated_pcb/serial.modelec.py

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,19 @@ def read_serial(ser, log_lines, log_lock):
3535
log_lines.append(f"[Serial Error] {e}")
3636
time.sleep(0.05)
3737

38-
def curses_main(stdscr, port, baudrate):
38+
def curses_main(stdscr, port, baudrate, filter_start=None):
3939
global stop_thread
4040
curses.curs_set(1)
4141
stdscr.nodelay(True)
4242
stdscr.timeout(100)
4343

44+
if filter_start is None:
45+
filter_start = ["SET;POS"]
46+
4447
log_lines = []
4548
log_lock = threading.Lock()
4649
cmd_history = []
47-
history_index = -1 # For navigating command history
50+
history_index = -1
4851

4952
with serial.Serial(port, baudrate, timeout=1) as ser:
5053
time.sleep(2)
@@ -57,24 +60,36 @@ def curses_main(stdscr, port, baudrate):
5760
stdscr.clear()
5861
h, w = stdscr.getmaxyx()
5962

60-
# Split screen horizontally (70% logs, 30% command history)
61-
split_x = int(w * 0.7)
63+
# --- Split into 3 vertical columns ---
64+
col_width = w // 3
65+
col1_x = 0
66+
col2_x = col_width
67+
col3_x = 2 * col_width
68+
6269
log_height = h - 2
6370

64-
# --- Left panel: logs ---
71+
# --- Separate logs into filtered and others ---
6572
with log_lock:
66-
visible_logs = log_lines[-log_height:]
67-
for i, line in enumerate(visible_logs):
68-
stdscr.addnstr(i, 0, line, split_x - 1)
69-
70-
# --- Right panel: command history ---
71-
stdscr.vline(0, split_x, "|", log_height)
72-
history_start_x = split_x + 2
73-
stdscr.addstr(0, history_start_x, "Command History:")
74-
75-
visible_history = cmd_history[-(log_height - 2):]
73+
filtered_logs = [line for line in log_lines if any(line.startswith(p) for p in filter_start)]
74+
other_logs = [line for line in log_lines if not any(line.startswith(p) for p in filter_start)]
75+
visible_filtered = filtered_logs[-log_height:]
76+
visible_other = other_logs[-log_height:]
77+
visible_history = cmd_history[-log_height:]
78+
79+
# --- Column 1: Filtered serial output ---
80+
stdscr.addstr(0, col1_x, f"Filtered ({', '.join(filter_start)}):")
81+
for i, line in enumerate(visible_filtered):
82+
stdscr.addnstr(i + 1, col1_x, line, col_width - 1)
83+
84+
# --- Column 2: Other serial output ---
85+
stdscr.addstr(0, col2_x, "Other Logs:")
86+
for i, line in enumerate(visible_other):
87+
stdscr.addnstr(i + 1, col2_x, line, col_width - 1)
88+
89+
# --- Column 3: Command history ---
90+
stdscr.addstr(0, col3_x, "Command History:")
7691
for i, cmd in enumerate(visible_history):
77-
stdscr.addnstr(i + 1, history_start_x, cmd, w - history_start_x - 1)
92+
stdscr.addnstr(i + 1, col3_x, cmd, col_width - 1)
7893

7994
# --- Input line ---
8095
stdscr.addstr(log_height, 0, "-" * (w - 1))

src/modelec_com/CMakeLists.txt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
55
add_compile_options(-Wall -Wextra -Wpedantic)
66
endif()
77

8+
option(BUILD_FOR_RPI "Build with Raspberry Pi libcamera support" OFF)
9+
810
# find dependencies
911
find_package(ament_cmake REQUIRED)
1012
find_package(rclcpp REQUIRED)
@@ -16,6 +18,18 @@ find_package(ament_index_cpp REQUIRED)
1618
find_package(fmt)
1719

1820
find_package(OpenCV REQUIRED)
21+
find_package(PkgConfig REQUIRED)
22+
23+
if(BUILD_FOR_RPI)
24+
message(STATUS "Configuring for Raspberry Pi Hardware...")
25+
add_definitions(-DRPI_BUILD)
26+
pkg_check_modules(LIBCAMERA REQUIRED libcamera libcamera-base)
27+
include_directories(${LIBCAMERA_INCLUDE_DIRS})
28+
link_directories(${LIBCAMERA_LIBRARY_DIRS} /usr/local/lib/aarch64-linux-gnu)
29+
add_definitions(${LIBCAMERA_CFLAGS_OTHER})
30+
else()
31+
message(STATUS "Configuring for PC (standard OpenCV)...")
32+
endif()
1933

2034
find_package(modelec_interfaces REQUIRED)
2135
find_package(modelec_utils REQUIRED)
@@ -57,6 +71,16 @@ target_link_libraries(color_detector
5771
modelec_utils::config
5872
)
5973

74+
if(BUILD_FOR_RPI)
75+
target_link_libraries(color_detector
76+
-Wl,--no-as-needed
77+
"/usr/local/lib/aarch64-linux-gnu/libcamera.so"
78+
"/usr/local/lib/aarch64-linux-gnu/libcamera-base.so"
79+
-Wl,--as-needed
80+
cam2opencv
81+
)
82+
endif()
83+
6084
target_include_directories(color_detector PUBLIC
6185
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
6286
$<INSTALL_INTERFACE:include>

src/modelec_com/include/modelec_com/color_detector.hpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,18 @@
55
#include <std_srvs/srv/trigger.hpp>
66
#include <std_msgs/msg/empty.hpp>
77
#include <std_msgs/msg/string.hpp>
8+
#include <modelec_utils/config.hpp>
9+
#include <mutex>
10+
#include <memory>
11+
12+
#ifdef RPI_BUILD
13+
#include <libcam2opencv.h>
14+
#endif
815

916
namespace Modelec
1017
{
18+
struct CamCallback;
19+
1120
struct ColorSetting
1221
{
1322
std::string name;
@@ -34,6 +43,17 @@ namespace Modelec
3443

3544
std::string generateImagePath() const;
3645

46+
#ifdef RPI_BUILD
47+
Libcam2OpenCV camera_;
48+
std::unique_ptr<CamCallback> my_callback_;
49+
#else
50+
cv::VideoCapture pc_cap_;
51+
#endif
52+
53+
cv::Mat latest_frame_;
54+
55+
std::mutex frame_mutex_;
56+
3757
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr service_;
3858

3959
rclcpp::Subscription<std_msgs::msg::Empty>::SharedPtr ask_sub_;
@@ -49,4 +69,45 @@ namespace Modelec
4969

5070
std::vector<ColorSetting> color_configs_;
5171
};
72+
73+
template<>
74+
inline std::vector<ColorSetting>
75+
Config::get<std::vector<ColorSetting>>(
76+
const std::string& prefix,
77+
const std::vector<ColorSetting>& default_value, bool)
78+
{
79+
auto result = Config::getArray<ColorSetting>(
80+
prefix,
81+
[](const std::string& base)
82+
{
83+
return ColorSetting{
84+
Config::get<std::string>(base + "@name"),
85+
Config::get<double>(base + "@hue_min"),
86+
Config::get<double>(base + "@hue_max")
87+
};
88+
});
89+
90+
return result.empty() ? default_value : result;
91+
}
92+
93+
template<>
94+
inline std::vector<cv::Rect>
95+
Config::get<std::vector<cv::Rect>>(
96+
const std::string& prefix,
97+
const std::vector<cv::Rect>& default_value, bool)
98+
{
99+
auto result = Config::getArray<cv::Rect>(
100+
prefix,
101+
[](const std::string& base)
102+
{
103+
return cv::Rect(
104+
Config::get<int>(base + "@x", 0),
105+
Config::get<int>(base + "@y", 0),
106+
Config::get<int>(base + "@w", 100),
107+
Config::get<int>(base + "@h", 100)
108+
);
109+
});
110+
111+
return result.empty() ? default_value : result;
112+
}
52113
}

src/modelec_com/include/modelec_com/pcb_action_interface.hpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <modelec_interfaces/msg/action_servo_timed_array.hpp>
1313
#include <modelec_interfaces/msg/action_servo_timed.hpp>
1414

15+
#include "modelec_utils/config.hpp"
16+
1517
#define TIMER_SERVO_TIMED_MS 10 // 100 Hz
1618

1719
namespace Modelec
@@ -37,10 +39,10 @@ namespace Modelec
3739
std::map<int, int> asc_value_mapper_;
3840

3941
int asc_state_ = 0;
40-
std::map<int, double> servo_value_;
41-
std::map<int, bool> relay_value_;
42+
std::unordered_map<int, double> servo_value_;
43+
std::unordered_map<int, bool> relay_value_;
4244

43-
std::map<int, ServoTimedSet> servo_timed_buffer_;
45+
std::vector<ServoTimedSet> servo_timed_buffer_;
4446

4547
rclcpp::TimerBase::SharedPtr servo_timed_timer_;
4648

@@ -82,10 +84,29 @@ namespace Modelec
8284
void SendToPCB(const std::string& order, const std::string& elem,
8385
const std::vector<std::string>& data = {});
8486

85-
// TODO redo thos func to accept arrays, poc without them atm
8687
void GetData(const std::string& elem, const std::vector<std::string>& data = {});
8788
void SendOrder(const std::string& elem, const std::vector<std::string>& data = {});
8889
void SendMove(const std::string& elem, const std::vector<std::string>& data = {});
8990
void RespondEvent(const std::string& elem, const std::vector<std::string>& data = {});
9091
};
92+
93+
template<>
94+
inline std::unordered_map<int, double>
95+
Config::get<std::unordered_map<int, double>>(
96+
const std::string& prefix,
97+
const std::unordered_map<int, double>& default_value, bool)
98+
{
99+
auto result = Config::getMap<int, double>(
100+
prefix,
101+
[](const std::string& base)
102+
{
103+
return std::make_pair(
104+
Config::get<int>(base + "@id"),
105+
Config::get<double>(base + "@angle")
106+
);
107+
});
108+
109+
return result.empty() ? default_value : result;
110+
}
111+
91112
}

src/modelec_com/include/modelec_com/pcb_odo_interface.hpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include <sensor_msgs/msg/joy.hpp>
2121

22+
#include "modelec_utils/config.hpp"
23+
2224
namespace Modelec
2325
{
2426
class PCBOdoInterface : public rclcpp::Node, public SerialListener
@@ -37,9 +39,11 @@ namespace Modelec
3739

3840
struct PIDData
3941
{
40-
float p;
41-
float i;
42-
float d;
42+
float p = 0.0f;
43+
float i = 0.0f;
44+
float d = 0.0f;
45+
std::optional<float> min;
46+
std::optional<float> max;
4347
};
4448

4549
private:
@@ -95,7 +99,26 @@ namespace Modelec
9599
void GetPID();
96100
void SetPID(const modelec_interfaces::msg::OdometryPid::SharedPtr msg);
97101
void SetPID(std::string name, float p, float i, float d, std::optional<float> min = std::nullopt, std::optional<float> max = std::nullopt);
102+
void SetPID(std::string name, const PIDData& pid_data);
98103

99104
void SetMotor(int left, int right);
100105
};
106+
107+
template<>
108+
inline PCBOdoInterface::PIDData
109+
Config::get<PCBOdoInterface::PIDData>(
110+
const std::string& prefix,
111+
const PCBOdoInterface::PIDData& default_value, bool)
112+
{
113+
PCBOdoInterface::PIDData result;
114+
result.p = Config::get<float>(prefix + "@p", default_value.p);
115+
result.i = Config::get<float>(prefix + "@i", default_value.i);
116+
result.d = Config::get<float>(prefix + "@d", default_value.d);
117+
if (Config::has(prefix + "@min"))
118+
result.min = Config::get<float>(prefix + "@min");
119+
if (Config::has(prefix + "@max"))
120+
result.max = Config::get<float>(prefix + "@max");
121+
return result;
122+
}
123+
101124
} // namespace Modelec

0 commit comments

Comments
 (0)