From b41ceb51eea398b42ff37efcf79421688d35f8cc Mon Sep 17 00:00:00 2001 From: Pimpest <82343504+Pimpest@users.noreply.github.com> Date: Sun, 23 Mar 2025 13:21:23 +0100 Subject: [PATCH] Added robot and things --- .clang-format | 68 + .clang-tidy | 34 + .clangd | 6 + CMakeLists.txt | 14 + include/rqt_demo_plugin/lineItem.hpp | 44 +- include/rqt_demo_plugin/rqt_demo_plugin.hpp | 132 +- mg_msgs/CMakeLists.txt | 23 + mg_msgs/action/LookAt.action | 25 + mg_msgs/action/MovePoint.action | 25 + mg_msgs/action/MoveStraight.action | 24 + mg_msgs/action/Rotate.action | 25 + mg_msgs/msg/Point2d.msg | 2 + mg_msgs/msg/TEdit.msg | 4 + mg_msgs/msg/TEditCycle.msg | 8 + mg_msgs/package.xml | 19 + mg_msgs/srv/SetWidth.srv | 2 + package.xml | 4 + resources/playmat_grid_v1.svg | 27739 ++++++++++++++++++ resources/qml/helloworld.qml | 130 +- resources/res.qrc | 2 + resources/robot.jpg | Bin 0 -> 14645 bytes src/lineItem.cpp | 128 +- src/rqt_demo_plugin.cpp | 83 +- 23 files changed, 28380 insertions(+), 161 deletions(-) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .clangd create mode 100644 mg_msgs/CMakeLists.txt create mode 100644 mg_msgs/action/LookAt.action create mode 100644 mg_msgs/action/MovePoint.action create mode 100644 mg_msgs/action/MoveStraight.action create mode 100644 mg_msgs/action/Rotate.action create mode 100644 mg_msgs/msg/Point2d.msg create mode 100644 mg_msgs/msg/TEdit.msg create mode 100644 mg_msgs/msg/TEditCycle.msg create mode 100644 mg_msgs/package.xml create mode 100644 mg_msgs/srv/SetWidth.srv create mode 100644 resources/playmat_grid_v1.svg create mode 100644 resources/robot.jpg diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..5ffc498 --- /dev/null +++ b/.clang-format @@ -0,0 +1,68 @@ +--- +Language: Cpp +BasedOnStyle: Mozilla + +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: true +AlignEscapedNewlines: Right +AlignOperands: false +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: true +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BreakBeforeBinaryOperators: true +BreakBeforeBraces: Attach +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: AfterColon +ColumnLimit: 120 +CompactNamespaces: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +IncludeBlocks: Preserve +IndentCaseLabels: true +IndentWidth: 4 +PointerAlignment: Left +PackConstructorInitializers: NextLine +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Auto +TabWidth: 4 +UseTab: Never + +AllowShortEnumsOnASingleLine: false + +BraceWrapping: + AfterEnum: false + +AlignConsecutiveDeclarations: + Enabled: true + +NamespaceIndentation: All \ No newline at end of file diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..fa92005 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,34 @@ +--- +Checks: " + *, + -abseil-*, + -altera-*, + -android-*, + -fuchsia-*, + -google-*, + -llvm*, + -modernize-use-trailing-return-type, + -zircon-*, + -readability-else-after-return, + -readability-static-accessed-through-instance, + -readability-avoid-const-params-in-decls, + -cppcoreguidelines-non-private-member-variables-in-classes, + -misc-non-private-member-variables-in-classes, + -misc-non-private-member-variables-in-classes, + -readability-identifier-length, + -misc-include-cleaner, + -modernize-avoid-bind, + -hicpp-*, + -bugprone-easily-swappable-parameters, + -readability-function-cognitive-complexity, + -readability-named-parameter, + -cppcoreguidelines-pro-type-union-access, + -cppcoreguidelines-owning-memory, + -cppcoreguidelines-macro-usage, + -performance-unnecessary-value-param, + -modernize-use-nodiscard, + -cppcoreguidelines-pro-bounds-constant-array-index, + " +WarningsAsErrors: '' +HeaderFilterRegex: '' +FormatStyle: none \ No newline at end of file diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..68e449a --- /dev/null +++ b/.clangd @@ -0,0 +1,6 @@ +--- +Diagnostics: + UnusedIncludes: None + MissingIncludes: None + ClangTidy: + FastCheckFilter: Loose \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b072ac..815ccc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,10 +12,17 @@ find_package(pluginlib REQUIRED) pluginlib_export_plugin_description_file(rqt_gui "plugin.xml") find_package(rqt_gui_cpp REQUIRED) find_package(qt_gui_cpp REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_ros REQUIRED) +find_package(tf2_geometry_msgs REQUIRED) find_package(Qt5 COMPONENTS Core REQUIRED) find_package(Qt5 COMPONENTS Widgets REQUIRED) +find_package(Qt5 COMPONENTS Svg REQUIRED) find_package(Qt5 COMPONENTS Qml REQUIRED) find_package(Qt5 COMPONENTS Quick REQUIRED) +find_package(Qt5 COMPONENTS QuickControls2 REQUIRED) +find_package(mg_msgs REQUIRED) find_package(Qt5QuickCompiler) set(CMAKE_AUTOMOC ON) @@ -50,10 +57,17 @@ ament_target_dependencies( pluginlib rqt_gui_cpp qt_gui_cpp + geometry_msgs + tf2 + tf2_ros + tf2_geometry_msgs Qt5Core Qt5Widgets + Qt5Svg Qt5Qml Qt5Quick + Qt5QuickControls2 + mg_msgs ) install( diff --git a/include/rqt_demo_plugin/lineItem.hpp b/include/rqt_demo_plugin/lineItem.hpp index aaa9ae3..c2a3dae 100644 --- a/include/rqt_demo_plugin/lineItem.hpp +++ b/include/rqt_demo_plugin/lineItem.hpp @@ -1,45 +1,35 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -class LineItem : public QQuickItem -{ +#include + +class LineItem : public QQuickItem { Q_OBJECT Q_PROPERTY(float scale READ scale WRITE setScale NOTIFY scaleChanged) Q_PROPERTY(QString stupid READ stupid WRITE setStupid NOTIFY stupidChanged) Q_PROPERTY(QObject* handler READ handler WRITE setHandler NOTIFY handlerChanged) - QML_ELEMENT -public: - LineItem(QQuickItem *parent = nullptr); + public: + LineItem(QQuickItem* parent = nullptr); ~LineItem(); - QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override; + QSGNode* updatePaintNode(QSGNode*, UpdatePaintNodeData*) override; - QString stupid() const {return stupid_;} - QObject* handler() const {return handler_;} + QString stupid() const { return stupid_; } + QObject* handler() const { return handler_; } - void setStupid(const QString &str) {stupid_ = str;} - void setScale(const float scale) {scale_ = scale;} - void setHandler(QObject* const obj) {handler_ = obj;} + void setStupid(const QString& str) { stupid_ = str; } + void setScale(const float scale) { scale_ = scale; } + void setHandler(QObject* const obj); -signals: - void stupidChanged(const QString &str); + signals: + void stupidChanged(const QString& str); void handlerChanged(QObject* const obj); - - -private: - float scale_; - QString stupid_; + private: + float scale_; + QString stupid_; QObject* handler_; - int prev_size=0; + int prev_size = 0; }; \ No newline at end of file diff --git a/include/rqt_demo_plugin/rqt_demo_plugin.hpp b/include/rqt_demo_plugin/rqt_demo_plugin.hpp index edc4b3d..cc517c8 100644 --- a/include/rqt_demo_plugin/rqt_demo_plugin.hpp +++ b/include/rqt_demo_plugin/rqt_demo_plugin.hpp @@ -1,70 +1,112 @@ #pragma once +#include "geometry_msgs/msg/point.hpp" #include "rqt_gui_cpp/plugin.h" +#include "mg_msgs/msg/t_edit_cycle.hpp" +#include "geometry_msgs/msg/point_stamped.hpp" +#include "tf2_ros/buffer.h" +#include "tf2_ros/transform_listener.h" #include #include +#include + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include inline void initResources() { Q_INIT_RESOURCE(res); } inline void cleanupResources() { Q_CLEANUP_RESOURCE(res); } namespace mg { -class DemoPluginMg : public rqt_gui_cpp::Plugin { - Q_OBJECT - Q_PROPERTY(QObject* demoPlugin READ demoPlugin NOTIFY demoPluginChanged) -public: - DemoPluginMg(); + class DemoPluginMg : public rqt_gui_cpp::Plugin { + Q_OBJECT + Q_PROPERTY(QObject* demoPlugin READ demoPlugin NOTIFY demoPluginChanged) + Q_PROPERTY(QPointF robotPos READ robotPos NOTIFY robotPosChanged) + Q_PROPERTY(qreal robotTheta READ robotTheta NOTIFY robotThetaChanged) - virtual void shutdownPlugin() { - cleanupResources(); - } + public: + std::mutex tree_mut_; + bool children_dirty; + bool points_dirty; - virtual void initPlugin(qt_gui_cpp::PluginContext &); + DemoPluginMg(); - QObject * demoPlugin() const { - return (QObject *)(this); - } + void initPlugin(qt_gui_cpp::PluginContext&) override; + void shutdownPlugin() override { cleanupResources(); } - const QSGGeometry::Point2D hello[8] = { - {0.2,0.2}, {0.8,0.2}, - {0.2,0.2}, {0.2,0.8}, - {0.2,0.4}, {0.4,0.8}, - {0.2,0.4}, {0.1,0.1}, - }; + Q_INVOKABLE void postPoint(qreal x, qreal y); - const int hello_c = 8; + QObject* demoPlugin() const { return (QObject*)(this); } + QPointF robotPos() const { return robotPos_; } + float robotTheta() const { return robotTheta_; } -signals: + const std::vector>& children() const { return children_; } + const std::vector>& points() const { return points_; } - void demoPluginChanged(QObject * const); + int cchildren() const { return cchildren_; }; -}; + signals: -inline void DemoPluginMg::initPlugin(qt_gui_cpp::PluginContext &pc) { - initResources(); - const QUrl qrl("qrc:/qml/helloworld.qml"); - QQuickView *qv = new QQuickView(); - qv->rootContext()->setContextProperty("DemoPlug", this); - qv->setSource(qrl); - qv->setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView); - QSurfaceFormat format = qv->format(); - format.setSamples(4); - qv->setFormat(format); - QWidget *qw_ = QWidget::createWindowContainer(qv); - pc.addWidget(qw_); -} + void demoPluginChanged(QObject* const); + void robotPosChanged(QPointF const); + void robotThetaChanged(float const); + void treeChanged(); + + private: + std::shared_ptr> editcycle_sub_; + + std::vector> children_; + std::vector> points_; + + std::shared_ptr tf_timer_; + std::shared_ptr tf_buffer_; + std::shared_ptr tf_listener_; + + rclcpp::Publisher::SharedPtr pub_point_; + + QPointF robotPos_; + qreal robotTheta_; + + int cchildren_; + + void cb_GraphEdits(mg_msgs::msg::TEditCycle::ConstSharedPtr msg); + void cb_tf_timer(); + }; + + inline void DemoPluginMg::initPlugin(qt_gui_cpp::PluginContext& pc) { + initResources(); + + tf_buffer_ = std::make_shared(node_->get_clock()); + tf_listener_ = std::make_shared(*tf_buffer_); + + tf_timer_ = node_->create_timer(std::chrono::milliseconds(15), [this]() { this->cb_tf_timer(); }); + pub_point_ = node_->create_publisher("/clicked_point", rclcpp::QoS(1)); + + QQuickStyle::setStyle("fusion"); + + const QUrl qrl("qrc:/qml/helloworld.qml"); + auto* qv = new QQuickView(); + + auto editcycle_cb = std::bind(&DemoPluginMg::cb_GraphEdits, this, std::placeholders::_1); + editcycle_sub_ = node_->create_subscription( + "GraphEdits", rclcpp::QoS(1000).transient_local(), editcycle_cb); + + qv->rootContext()->setContextProperty("DemoPlug", this); + qv->setSource(qrl); + qv->setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView); + QSurfaceFormat format = qv->format(); + format.setSamples(4); + qv->setFormat(format); + QWidget* qw_ = QWidget::createWindowContainer(qv); + pc.addWidget(qw_); + } }; // namespace mg diff --git a/mg_msgs/CMakeLists.txt b/mg_msgs/CMakeLists.txt new file mode 100644 index 0000000..df9a589 --- /dev/null +++ b/mg_msgs/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.8) +project(mg_msgs) + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(rosidl_default_generators REQUIRED) + +rosidl_generate_interfaces(${PROJECT_NAME} + "msg/Point2d.msg" + "msg/TEdit.msg" + "msg/TEditCycle.msg" + "action/MoveStraight.action" + "action/MovePoint.action" + "action/LookAt.action" + "action/Rotate.action" + "srv/SetWidth.srv" +) + +ament_package() \ No newline at end of file diff --git a/mg_msgs/action/LookAt.action b/mg_msgs/action/LookAt.action new file mode 100644 index 0000000..3537aef --- /dev/null +++ b/mg_msgs/action/LookAt.action @@ -0,0 +1,25 @@ +float64 x +float64 y + +float64 step 0.01 +float64 tolerance 0.001 +float64 max_wheel_speed 3 +float64 max_angular 3.14 +float64 max_vel 2 +float64 pos_mult 15 +float64 ornt_mult 4 +float64 t_ornt_mult 0.1 +float64 obst_mult_a -5 +float64 obst_mult_b -30 +float64 obst_mult_c -9 +string[] ignore_tags [] +--- +uint8 SUCCESS=0 +uint8 BLOCKED=1 +uint8 TIMEOUT=2 +uint8 MISALIGNED=3 +uint8 UNKNOWN=254 + +uint8 error +--- +float64 distance_passed \ No newline at end of file diff --git a/mg_msgs/action/MovePoint.action b/mg_msgs/action/MovePoint.action new file mode 100644 index 0000000..9912d7b --- /dev/null +++ b/mg_msgs/action/MovePoint.action @@ -0,0 +1,25 @@ +float64 x +float64 y + +float64 step 0.01 +float64 tolerance 0.001 +float64 max_wheel_speed 3 +float64 max_angular 3.14 +float64 max_vel 2 +float64 pos_mult 15 +float64 ornt_mult 4 +float64 t_ornt_mult 0.1 +float64 obst_mult_a -5 +float64 obst_mult_b -30 +float64 obst_mult_c -9 +string[] ignore_tags [] +--- +uint8 SUCCESS=0 +uint8 BLOCKED=1 +uint8 TIMEOUT=2 +uint8 MISALIGNED=3 +uint8 UNKNOWN=254 + +uint8 error +--- +float64 distance_passed \ No newline at end of file diff --git a/mg_msgs/action/MoveStraight.action b/mg_msgs/action/MoveStraight.action new file mode 100644 index 0000000..1921291 --- /dev/null +++ b/mg_msgs/action/MoveStraight.action @@ -0,0 +1,24 @@ +float64 distance + +float64 step 0.01 +float64 tolerance 0.001 +float64 max_wheel_speed 3 +float64 max_angular 3.14 +float64 max_vel 2 +float64 pos_mult 15 +float64 ornt_mult 4 +float64 t_ornt_mult 0.1 +float64 obst_mult_a -5 +float64 obst_mult_b -30 +float64 obst_mult_c -9 +string[] ignore_tags [] +--- +uint8 SUCCESS=0 +uint8 BLOCKED=1 +uint8 TIMEOUT=2 +uint8 MISALIGNED=3 +uint8 UNKNOWN=254 + +uint8 error +--- +float64 distance_passed \ No newline at end of file diff --git a/mg_msgs/action/Rotate.action b/mg_msgs/action/Rotate.action new file mode 100644 index 0000000..3948fa3 --- /dev/null +++ b/mg_msgs/action/Rotate.action @@ -0,0 +1,25 @@ + +float64 angle + +float64 step 0.01 +float64 tolerance 0.001 +float64 max_wheel_speed 3 +float64 max_angular 3.14 +float64 max_vel 2 +float64 pos_mult 15 +float64 ornt_mult 4 +float64 t_ornt_mult 0.1 +float64 obst_mult_a -5 +float64 obst_mult_b -30 +float64 obst_mult_c -9 +string[] ignore_tags [] +--- +uint8 SUCCESS=0 +uint8 BLOCKED=1 +uint8 TIMEOUT=2 +uint8 MISALIGNED=3 +uint8 UNKNOWN=254 + +uint8 error +--- +float64 distance_passed \ No newline at end of file diff --git a/mg_msgs/msg/Point2d.msg b/mg_msgs/msg/Point2d.msg new file mode 100644 index 0000000..125c004 --- /dev/null +++ b/mg_msgs/msg/Point2d.msg @@ -0,0 +1,2 @@ +float64 x +float64 y \ No newline at end of file diff --git a/mg_msgs/msg/TEdit.msg b/mg_msgs/msg/TEdit.msg new file mode 100644 index 0000000..4ef056d --- /dev/null +++ b/mg_msgs/msg/TEdit.msg @@ -0,0 +1,4 @@ + +uint8 type +uint16 idx +uint16 idy diff --git a/mg_msgs/msg/TEditCycle.msg b/mg_msgs/msg/TEditCycle.msg new file mode 100644 index 0000000..e9af1cc --- /dev/null +++ b/mg_msgs/msg/TEditCycle.msg @@ -0,0 +1,8 @@ + +mg_msgs/TEdit[100] modifications +mg_msgs/Point2d[100] new_points +uint8 cmodifications 0 +uint8 cnew_points 0 + +uint8 DELETE=1 +uint8 ADD=0 \ No newline at end of file diff --git a/mg_msgs/package.xml b/mg_msgs/package.xml new file mode 100644 index 0000000..b396373 --- /dev/null +++ b/mg_msgs/package.xml @@ -0,0 +1,19 @@ + + + + mg_msgs + 0.0.0 + This contains various msg/action used within the project + Pimpest + MIT + + ament_cmake + + rosidl_default_generators + rosidl_default_runtime + rosidl_interface_packages + + + ament_cmake + + diff --git a/mg_msgs/srv/SetWidth.srv b/mg_msgs/srv/SetWidth.srv new file mode 100644 index 0000000..7e44f9a --- /dev/null +++ b/mg_msgs/srv/SetWidth.srv @@ -0,0 +1,2 @@ +float64 width +--- \ No newline at end of file diff --git a/package.xml b/package.xml index 2049575..763cfcc 100644 --- a/package.xml +++ b/package.xml @@ -14,6 +14,10 @@ rqt rqt_gui_cpp rqt_image_view + tf2 + tf2_ros + + mg_msgs ament_cmake diff --git a/resources/playmat_grid_v1.svg b/resources/playmat_grid_v1.svg new file mode 100644 index 0000000..53b2b1e --- /dev/null +++ b/resources/playmat_grid_v1.svg @@ -0,0 +1,27739 @@ + +image/svg+xml0°90°-90°180°45°30°60°120°135°150°-45°-135°ππ/2-π/20°90°-90°180°45°30°60°120°135°150°-45°-135°ππ/2-π/20°90°-90°180°45°30°60°120°135°150°-45°-135°ππ/2-π/20°90°-90°180°45°30°60°120°135°150°-45°-135°ππ/2-π/210020030040050060070080090010001100120013001400150016001700180019002000210022002300240025002600270028002900x10020030040050060070080090010001100120013001400150016001700180019002000210022002300240025002600270028002900190018001700160015001400130012001100100090080070060050040030020010019001800170016001500140013001200110010009008007006005004003002001000yyy190018001700160015001400130012001100100090080070060050040030020010010020030040050060070080090010001100120013001400150016001700180019002000210022002300240025002600270028002900123456DCBADCBADCBA123456123456yxxx diff --git a/resources/qml/helloworld.qml b/resources/qml/helloworld.qml index 075739e..2987d83 100644 --- a/resources/qml/helloworld.qml +++ b/resources/qml/helloworld.qml @@ -1,42 +1,116 @@ import QtQuick 2.3 +import QtQuick.Controls 2.0 import LineItem 1.0 import DemoPlugin 1.0 -Rectangle { - id: rr - color: "gray" - property var scale: 0.4 - Flickable { - width: parent.width; - height: parent.height - contentWidth: 3000*rr.scale; contentHeight: 2000*rr.scale - flickDeceleration: 10000 - leftMargin: Math.max((width - contentWidth)/2,0) - topMargin: Math.max((height - contentHeight)/2,0) - clip: true +Item { +id: root +Column { + Row { + id: topbar + Button { + id: targetMode + text: "Target" + flat: false + checkable: true + onClicked: function() {} + } + } - Rectangle { - color: "white" - id: contentRect - anchors.top: parent.top - anchors.left: parent.left - width: parent.width/rr.scale - height: parent.height/rr.scale + Rectangle { + height: root.height - topbar.height + width: root.width + id: rr + color: "dimgrey" + property var scale: 0.5 + + Flickable { + id: viewport + width: parent.width; + height: parent.height + contentWidth: 3000; contentHeight: 2000 + flickDeceleration: 10000 + leftMargin: Math.max((width - contentWidth)/2,0) + topMargin: Math.max((height - contentHeight)/2,0) - transform: Scale {yScale: rr.scale; xScale: rr.scale} - transformOrigin: Item.TopLeft + clip: true - Row { - x:0 - y:0 - - LineItem { + Rectangle { + color: "lightgrey" + id: contentRect + anchors.top: parent.top + anchors.left: parent.left + width: parent.width/rr.scale + height: parent.height/rr.scale + + transform: Scale {yScale: rr.scale; xScale: rr.scale} + transformOrigin: Item.TopLeft + Image { + x: 0;y: 0 height: 2000 width: 3000 - scale: rr.scale - handler: DemoPlug.demoPlugin + source: "../playmat_grid_v1.svg" + antialiasing: false + } + + Row { + x:0 + y:0 + + LineItem { + height: 2000 + width: 3000 + scale: rr.scale + handler: DemoPlug.demoPlugin + } + } + Image { + x: DemoPlug.robotPos.x * 1000 - 140 + y: (2.0 - DemoPlug.robotPos.y) * 1000 - 160 + height: 320; + width: 280; + transform: [Rotation {angle: -DemoPlug.robotTheta/( Math.PI/180 ); origin.x: 140; origin.y: 160}] + source: "../robot.jpg" + } + } + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + + onPressed: (e)=> { + e.accepted = targetMode.checked + console.log("onPressed") + } + + onClicked: (e)=> { + DemoPlug.postPoint(e.x/rr.scale/1000,2.0 - e.y/rr.scale/1000) + e.accepted = true + console.log("onClicked") + } + + onWheel: (e) => { + if (e.modifiers & Qt.ControlModifier) { + rr.scale+=(e.angleDelta.y / 1080); + rr.scale = Math.min(Math.max(rr.scale,0.5),10.0) + + viewport.resizeContent(3000*rr.scale, 2000*rr.scale, Qt.point(e.x,e.y)) + } else { + e.accepted = false + } } } } + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + + onPressed: (e)=> { + e.accepted = false + } + + + } + } +} } \ No newline at end of file diff --git a/resources/res.qrc b/resources/res.qrc index 3b1d222..5e98866 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -1,5 +1,7 @@ qml/helloworld.qml + robot.jpg + playmat_grid_v1.svg \ No newline at end of file diff --git a/resources/robot.jpg b/resources/robot.jpg new file mode 100644 index 0000000000000000000000000000000000000000..da588d8891e9d9bc397e345b27225f140784bd0e GIT binary patch literal 14645 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 BPPYI6 literal 0 HcmV?d00001 diff --git a/src/lineItem.cpp b/src/lineItem.cpp index 8613722..b63a4ac 100644 --- a/src/lineItem.cpp +++ b/src/lineItem.cpp @@ -1,71 +1,99 @@ #include "rqt_demo_plugin/lineItem.hpp" #include "rqt_demo_plugin/rqt_demo_plugin.hpp" +#include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include -LineItem::LineItem(QQuickItem *parent) - : QQuickItem(parent) - , scale_(1) - , stupid_("") - , handler_(nullptr) -{ +LineItem::LineItem(QQuickItem* parent) : QQuickItem(parent), scale_(1), stupid_(""), handler_(nullptr) { setFlag(ItemHasContents, true); } LineItem::~LineItem() = default; +void LineItem::setHandler(QObject* const obj) { + handler_ = obj; + auto* plugin = dynamic_cast(handler_); + connect(plugin, SIGNAL(treeChanged()), this, SLOT(update())); + emit handlerChanged(obj); + update(); +} -QSGNode *LineItem::updatePaintNode(QSGNode *old, UpdatePaintNodeData *) -{ - QSGGeometryNode *node = nullptr; - QSGGeometry *geometry = nullptr; - mg::DemoPluginMg *plugin = static_cast(handler_); - if(!plugin) { +QSGNode* LineItem::updatePaintNode(QSGNode* old, UpdatePaintNodeData*) { + QSGGeometryNode* node = nullptr; + QSGGeometry* geometry = nullptr; + auto* plugin = dynamic_cast(handler_); + + if (!plugin) { qmlEngine(this)->throwError("Handler plugin was not provided"); return old; } - - const int hello_c = plugin->hello_c; - - if(!old) { - node = new QSGGeometryNode; - geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), hello_c); - geometry->setLineWidth(3*scale_); - geometry->setDrawingMode(QSGGeometry::DrawLines); - geometry->setVertexDataPattern(QSGGeometry::DynamicPattern); - geometry->setIndexDataPattern(QSGGeometry::DynamicPattern); - node->setGeometry(geometry); - node->setFlag(QSGNode::OwnsGeometry); - auto *material = new QSGFlatColorMaterial; - material->setColor(QColor(255,0,0)); - node->setMaterial(material); - node->setFlag(QSGNode::OwnsMaterial); - - } else { - node = static_cast(old); - geometry = node->geometry(); - if(hello_c != prev_size) { - geometry->allocate(prev_size); - } + if (plugin->cchildren() == 0) { + return nullptr; } + std::lock_guard lock(plugin->tree_mut_); - if(hello_c != prev_size) { + if (!old) { + geometry + = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), plugin->points().size(), 2 * plugin->cchildren()); + + node = new QSGGeometryNode; + auto* material = new QSGFlatColorMaterial; + + geometry->setDrawingMode(QSGGeometry::DrawLines); + + geometry->setVertexDataPattern(QSGGeometry::StaticPattern); + geometry->setIndexDataPattern(QSGGeometry::DynamicPattern); + material->setColor(QColor(255, 0, 0)); + + node->setGeometry(geometry); + node->setMaterial(material); + node->setFlag(QSGNode::OwnsGeometry); + node->setFlag(QSGNode::OwnsMaterial); + } else { + node = dynamic_cast(old); + geometry = node->geometry(); + + geometry->allocate(plugin->points().size(), 2 * plugin->cchildren()); + } + + if (plugin->points_dirty || plugin->children_dirty) { const QSizeF s = size(); - QSGGeometry::Point2D *verticies = geometry->vertexDataAsPoint2D(); - for(int i = 0; ihello[i].x * s.width(); - verticies[i].y = plugin->hello[i].y * s.height(); + + const std::vector>& points = plugin->points(); + QSGGeometry::Point2D* verticies = geometry->vertexDataAsPoint2D(); + + int i = 0; + for (const auto& p : points) { + verticies[i].x = p.first * s.width(); + verticies[i].y = p.second * s.height(); + i++; } geometry->markVertexDataDirty(); - node->markDirty(QSGNode::DirtyGeometry); - prev_size = hello_c; + plugin->points_dirty = false; } - - return node; + + if (plugin->children_dirty) { + const std::vector>& children = plugin->children(); + ushort* indicies = geometry->indexDataAsUShort(); + + int i = 0; + int j = 0; + for (const auto& cset : children) { + for (const auto& child : cset) { + indicies[j++] = i; + indicies[j++] = child; + } + i++; + } + geometry->markIndexDataDirty(); + plugin->children_dirty = false; + } + + geometry->setLineWidth(3 * scale_); + node->markDirty(QSGNode::DirtyGeometry); + + return node; } \ No newline at end of file diff --git a/src/rqt_demo_plugin.cpp b/src/rqt_demo_plugin.cpp index b0dcdbd..be320f0 100644 --- a/src/rqt_demo_plugin.cpp +++ b/src/rqt_demo_plugin.cpp @@ -1,21 +1,82 @@ #include "rqt_demo_plugin/rqt_demo_plugin.hpp" +#include "geometry_msgs/msg/point_stamped.hpp" +#include "mg_msgs/msg/t_edit.hpp" +#include "mg_msgs/msg/t_edit_cycle.hpp" #include "rqt_demo_plugin/lineItem.hpp" +#include "tf2_geometry_msgs/tf2_geometry_msgs.hpp" +#include "tf2/LinearMath/Transform.h" +#include "tf2/convert.h" + #include "pluginlib/class_list_macros.hpp" +#include #include #include #include + PLUGINLIB_EXPORT_CLASS(mg::DemoPluginMg, rqt_gui_cpp::Plugin) -mg::DemoPluginMg::DemoPluginMg() : Plugin() { - QSurfaceFormat fmt; - fmt.setSwapInterval(0); - fmt.setRenderableType(QSurfaceFormat::OpenGLES); - QSurfaceFormat::setDefaultFormat(fmt); - static bool typesRegistered = 0; - if(!typesRegistered) { - qmlRegisterType("LineItem", 1, 0, "LineItem"); - qmlRegisterAnonymousType("DemoPlugin", 1); - typesRegistered = 1; - } +mg::DemoPluginMg::DemoPluginMg() : + children_dirty(false), points_dirty(false), robotPos_(0, 0), robotTheta_(0), cchildren_(0) { + QSurfaceFormat fmt; + fmt.setSwapInterval(0); + fmt.setRenderableType(QSurfaceFormat::OpenGLES); + QSurfaceFormat::setDefaultFormat(fmt); + static bool typesRegistered = false; + if (!typesRegistered) { + qmlRegisterType("LineItem", 1, 0, "LineItem"); + qmlRegisterAnonymousType("DemoPlugin", 1); + typesRegistered = true; + } +} + +void mg::DemoPluginMg::cb_GraphEdits(mg_msgs::msg::TEditCycle::ConstSharedPtr msg) { + std::lock_guard lock(tree_mut_); + RCLCPP_INFO(node_->get_logger(), "Got edit: %u %u", msg->cnew_points, msg->cmodifications); + for (int i = 0; i < msg->cnew_points; i++) { + points_.emplace_back(msg->new_points[i].x, msg->new_points[i].y); + children_.emplace_back(); + } + for (int i = 0; i < msg->cmodifications; i++) { + const mg_msgs::msg::TEdit modification = msg->modifications[i]; + if (modification.type == mg_msgs::msg::TEditCycle::DELETE) { + children_[modification.idx].erase(modification.idy); + cchildren_--; + } else { + children_[modification.idx].insert(modification.idy); + cchildren_++; + } + } + + points_dirty = msg->cnew_points > 0; + children_dirty = msg->cmodifications > 0; + RCLCPP_INFO(node_->get_logger(), "Got edit: %lu %u", points_.size(), cchildren_); + emit treeChanged(); +} + +void mg::DemoPluginMg::cb_tf_timer() { + + try { + double x = NAN; + double y = NAN; + + auto tmsg = tf_buffer_->lookupTransform("odom", "base-link", tf2::TimePointZero); + + tf2::Transform t; + tf2::convert(tmsg.transform, t); + t.getBasis().getRPY(x, y, robotTheta_); + auto vec3 = tmsg.transform.translation; + + robotPos_ = { vec3.x, vec3.y }; + robotPosChanged(robotPos_); + robotThetaChanged(robotTheta_); + } catch (const tf2::TransformException& ex) { } +} + +void mg::DemoPluginMg::postPoint(qreal x, qreal y) { + geometry_msgs::msg::PointStamped point; + point.header.frame_id = "odom"; + point.point.x = x; + point.point.y = y; + pub_point_->publish(point); } \ No newline at end of file