diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..af152af --- /dev/null +++ b/.clang-format @@ -0,0 +1,65 @@ +--- +BasedOnStyle: Google +AccessModifierOffset: -2 +ConstructorInitializerIndentWidth: 2 +AlignEscapedNewlinesLeft: false +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AlwaysBreakTemplateDeclarations: true +AlwaysBreakBeforeMultilineStrings: true +BreakBeforeBinaryOperators: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: true +BinPackParameters: true +ColumnLimit: 120 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +DerivePointerBinding: false +PointerBindsToType: true +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 60 +PenaltyBreakString: 1 +PenaltyBreakFirstLessLess: 1000 +PenaltyExcessCharacter: 1000 +PenaltyReturnTypeOnItsOwnLine: 90 +SpacesBeforeTrailingComments: 2 +Cpp11BracedListStyle: false +Standard: Auto +IndentWidth: 2 +TabWidth: 2 +UseTab: Never +IndentFunctionDeclarationAfterType: false +SpacesInParentheses: false +SpacesInAngles: false +SpaceInEmptyParentheses: false +SpacesInCStyleCastParentheses: false +SpaceAfterControlStatementKeyword: true +SpaceBeforeAssignmentOperators: true +ContinuationIndentWidth: 4 +SortIncludes: false +SpaceAfterCStyleCast: false + +# Configure each individual brace in BraceWrapping +BreakBeforeBraces: Custom + +# Control of individual brace wrapping cases +BraceWrapping: { + AfterClass: 'true' + AfterControlStatement: 'true' + AfterEnum : 'true' + AfterFunction : 'true' + AfterNamespace : 'true' + AfterStruct : 'true' + AfterUnion : 'true' + BeforeCatch : 'true' + BeforeElse : 'true' + IndentBraces : 'false' +} +... \ No newline at end of file diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..fd8c681 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,147 @@ +# Generated from CLion Inspection settings +--- +Checks: '-*, +bugprone-argument-comment, +bugprone-assert-side-effect, +bugprone-bad-signal-to-kill-thread, +bugprone-branch-clone, +bugprone-copy-constructor-init, +bugprone-dangling-handle, +bugprone-dynamic-static-initializers, +bugprone-fold-init-type, +bugprone-forward-declaration-namespace, +bugprone-forwarding-reference-overload, +bugprone-inaccurate-erase, +bugprone-incorrect-roundings, +bugprone-integer-division, +bugprone-lambda-function-name, +bugprone-macro-parentheses, +bugprone-macro-repeated-side-effects, +bugprone-misplaced-operator-in-strlen-in-alloc, +bugprone-misplaced-pointer-arithmetic-in-alloc, +bugprone-misplaced-widening-cast, +bugprone-move-forwarding-reference, +bugprone-multiple-statement-macro, +bugprone-no-escape, +bugprone-parent-virtual-call, +bugprone-posix-return, +bugprone-reserved-identifier, +bugprone-sizeof-container, +bugprone-sizeof-expression, +bugprone-spuriously-wake-up-functions, +bugprone-string-constructor, +bugprone-string-integer-assignment, +bugprone-string-literal-with-embedded-nul, +bugprone-suspicious-enum-usage, +bugprone-suspicious-include, +bugprone-suspicious-memset-usage, +bugprone-suspicious-missing-comma, +bugprone-suspicious-semicolon, +bugprone-suspicious-string-compare, +bugprone-suspicious-memory-comparison, +bugprone-suspicious-realloc-usage, +bugprone-swapped-arguments, +bugprone-terminating-continue, +bugprone-throw-keyword-missing, +bugprone-too-small-loop-variable, +bugprone-undefined-memory-manipulation, +bugprone-undelegated-constructor, +bugprone-unhandled-self-assignment, +bugprone-unused-raii, +bugprone-unused-return-value, +bugprone-use-after-move, +bugprone-virtual-near-miss, +cert-dcl21-cpp, +cert-dcl58-cpp, +cert-err34-c, +cert-err52-cpp, +cert-err60-cpp, +cert-flp30-c, +cert-msc50-cpp, +cert-msc51-cpp, +cert-str34-c, +cppcoreguidelines-interfaces-global-init, +cppcoreguidelines-narrowing-conversions, +cppcoreguidelines-pro-type-member-init, +cppcoreguidelines-pro-type-static-cast-downcast, +cppcoreguidelines-slicing, +google-default-arguments, +google-explicit-constructor, +google-runtime-operator, +hicpp-exception-baseclass, +hicpp-multiway-paths-covered, +misc-misplaced-const, +misc-new-delete-overloads, +misc-no-recursion, +misc-non-copyable-objects, +misc-throw-by-value-catch-by-reference, +misc-unconventional-assign-operator, +misc-uniqueptr-reset-release, +modernize-avoid-bind, +modernize-concat-nested-namespaces, +modernize-deprecated-headers, +modernize-deprecated-ios-base-aliases, +modernize-loop-convert, +modernize-make-shared, +modernize-make-unique, +modernize-pass-by-value, +modernize-raw-string-literal, +modernize-redundant-void-arg, +modernize-replace-auto-ptr, +modernize-replace-disallow-copy-and-assign-macro, +modernize-replace-random-shuffle, +modernize-return-braced-init-list, +modernize-shrink-to-fit, +modernize-unary-static-assert, +modernize-use-auto, +modernize-use-bool-literals, +modernize-use-emplace, +modernize-use-equals-default, +modernize-use-equals-delete, +modernize-use-nodiscard, +modernize-use-noexcept, +modernize-use-nullptr, +modernize-use-override, +modernize-use-transparent-functors, +modernize-use-uncaught-exceptions, +mpi-buffer-deref, +mpi-type-mismatch, +openmp-use-default-none, +performance-faster-string-find, +performance-for-range-copy, +performance-implicit-conversion-in-loop, +performance-inefficient-algorithm, +performance-inefficient-string-concatenation, +performance-inefficient-vector-operation, +performance-move-const-arg, +performance-move-constructor-init, +performance-no-automatic-move, +performance-noexcept-move-constructor, +performance-trivially-destructible, +performance-type-promotion-in-math-fn, +performance-unnecessary-copy-initialization, +performance-unnecessary-value-param, +portability-simd-intrinsics, +readability-avoid-const-params-in-decls, +readability-const-return-type, +readability-container-size-empty, +readability-convert-member-functions-to-static, +readability-delete-null-pointer, +readability-deleted-default, +readability-inconsistent-declaration-parameter-name, +readability-make-member-function-const, +readability-misleading-indentation, +readability-misplaced-array-index, +readability-non-const-parameter, +readability-redundant-control-flow, +readability-redundant-declaration, +readability-redundant-function-ptr-dereference, +readability-redundant-smartptr-get, +readability-redundant-string-cstr, +readability-redundant-string-init, +readability-simplify-subscript-expr, +readability-static-accessed-through-instance, +readability-static-definition-in-anonymous-namespace, +readability-string-compare, +readability-uniqueptr-delete-release, +readability-use-anyofallof' \ No newline at end of file diff --git a/.devcontainer/.gitignore b/.devcontainer/.gitignore new file mode 100644 index 0000000..4cf41a1 --- /dev/null +++ b/.devcontainer/.gitignore @@ -0,0 +1 @@ +home/p* \ No newline at end of file diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 808cbb3..dc8c573 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -14,6 +14,7 @@ RUN apt-get update \ python3-pip \ curl \ rsync \ + psmisc \ && rm -rf /var/lib/apt/lists/* RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 62b6e97..b3b90e3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,5 +1,5 @@ { - "name": "OpenMowerROS2 development environment", + "name": "OpenMowerNext development environment", "privileged": true, "remoteUser": "openmower", "dockerComposeFile": "docker-compose.yaml", diff --git a/.devcontainer/docker-compose.yaml b/.devcontainer/docker-compose.yaml index 5a17634..7f373ba 100644 --- a/.devcontainer/docker-compose.yaml +++ b/.devcontainer/docker-compose.yaml @@ -37,8 +37,6 @@ services: depends_on: - xserver groot: - profiles: - - with_groot image: jkaflik/behaviortree-groot:latest ipc: host pid: host diff --git a/.devcontainer/home/map.geojson b/.devcontainer/home/map.geojson index 3361e66..63a1826 100644 --- a/.devcontainer/home/map.geojson +++ b/.devcontainer/home/map.geojson @@ -6,8 +6,11 @@ "properties": { "id": "0859c0c1-ec2d-4197-96b7-2d12f6cf1cd9", "name": "backyard", - "type": "lawn", - "fill": "#00ff00" + "type": "operation", + "fill": "#00ff00", + "style": { + "color": "#00ff00" + } }, "geometry": { "coordinates": [ @@ -84,7 +87,10 @@ "id": "6387f8e9-bc4e-48a5-95e2-fedd3b3b5c09", "name": "driveway", "type": "navigation", - "fill": "#ffffff" + "fill": "#ffffff", + "style": { + "color": "#ffffff" + } }, "geometry": { "coordinates": [ @@ -119,8 +125,11 @@ "type": "Feature", "properties": { "id": "a7a3e913-5e9e-4959-8044-059f40356996", - "type": "lawn", - "fill": "#00ff00" + "type": "operation", + "fill": "#00ff00", + "style": { + "color": "#00ff00" + } }, "geometry": { "coordinates": [ @@ -170,10 +179,13 @@ { "type": "Feature", "properties": { - "fill": "#ff0000", - "type": "obstacle", + "type": "exclusion", "name": "tree", - "id": "90cd67cb-a606-4878-be1c-2c08f8fc085d" + "id": "90cd67cb-a606-4878-be1c-2c08f8fc085d", + "fill": "#ff0000", + "style": { + "color": "#ff0000" + } }, "geometry": { "coordinates": [ diff --git a/.devcontainer/scripts/remote_devices.sh b/.devcontainer/scripts/remote_devices.sh index d3ae79a..4e5c8ae 100755 --- a/.devcontainer/scripts/remote_devices.sh +++ b/.devcontainer/scripts/remote_devices.sh @@ -16,12 +16,25 @@ then exit 1 fi +isFirstRun=false + # check if RSA private key exists, if not create it if [ ! -f ~/.ssh/id_rsa ]; then + isFirstRun=true + ssh-keygen -t rsa -b 4096 -C "devcontainer@devcontainer" -f ~/.ssh/id_rsa -q -N "" + + echo "Add the following public key to the authorized_keys file on the host:" + echo "----------------------------------------" + + cat ~/.ssh/id_rsa.pub + + echo "----------------------------------------" + echo "Press any key to continue" + read -n 1 -s fi -ssh-copy-id -i ~/.ssh/id_rsa.pub $username@$host +echo "Checking if host is reachable" # check if can ssh to host if ! ssh -o ConnectTimeout=2 $username@$host exit > /dev/null; then @@ -29,6 +42,14 @@ if ! ssh -o ConnectTimeout=2 $username@$host exit > /dev/null; then exit 1 fi +if [ "$isFirstRun" = true ]; then + echo "Install socat on host" + + ssh $username@$host "sudo apt install -y socat > /dev/null" +fi + +echo "Making sure all socat processes are killed on host" + ssh $username@$host "sudo killall socat || true" #trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT @@ -45,9 +66,13 @@ sshAndSocatSerialToTCP() { killall socat > /dev/null || true +echo "Starting socat processes" + sshAndSocatSerialToTCP ttyAMA0 115200 65000 & \ sshAndSocatSerialToTCP ttyAMA1 921600 65001 & \ sshAndSocatSerialToTCP ttyAMA2 115200 65002 & \ sshAndSocatSerialToTCP ttyAMA3 115200 65003 & \ sshAndSocatSerialToTCP ttyAMA4 115200 65004 && fg && fg + +echo "All socat processes have exited, exiting..." diff --git a/.gitignore b/.gitignore index cddf01e..ef88877 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,7 @@ __pycache__/ .clion.source.upload.marker -cmake-build-debug/ +cmake-build-debug*/ /.name /.idea diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1b7ce53 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,132 @@ +cmake_minimum_required(VERSION 3.8) +project(open_mower_next) + +# Default to C++14 +if (NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 14) +endif () + +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(rclcpp REQUIRED) +find_package(nlohmann_json REQUIRED) +find_package(rosidl_default_generators REQUIRED) +find_package(geometry_msgs REQUIRED) +find_package(nav_msgs REQUIRED) +find_package(std_msgs REQUIRED) +find_package(robot_localization REQUIRED) +find_package(tf2 REQUIRED) +find_package(tf2_geometry_msgs REQUIRED) +find_package(foxglove_msgs REQUIRED) +find_package(visualization_msgs REQUIRED) + +### +# map_server_node +### +add_executable(map_server_node + src/map_server/node_main.cpp + src/map_server/map_server_node.hpp + src/map_server/map_server_node.cpp + src/map_server/geo_json_map.cpp + src/map_server/geo_json_map.hpp + src/map_server/polygon_iterator.hpp + src/map_server/some_gaussian_filter.hpp + src/map_server/polygon_utils.hpp) +target_compile_features(map_server_node PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17 +target_include_directories(map_server_node PUBLIC + $ + $ +) + +ament_target_dependencies(map_server_node + std_msgs + geometry_msgs + nav_msgs + foxglove_msgs + visualization_msgs + rclcpp + robot_localization + tf2 + tf2_geometry_msgs +) + +target_link_libraries(map_server_node nlohmann_json::nlohmann_json) + +INSTALL(TARGETS map_server_node + DESTINATION lib/${PROJECT_NAME}) + +## +# map_server_node +## + +### +# sim_node +### +add_executable(sim_node + src/sim/node_main.cpp + src/sim/sim_node.hpp + src/sim/sim_node.cpp + src/sim/sim_node.cpp + src/sim/sim_node.hpp + src/sim/node_main.cpp) +target_compile_features(sim_node PUBLIC c_std_99 cxx_std_17) # Require C99 and C++17 +target_include_directories(sim_node PUBLIC + $ + $ +) + +ament_target_dependencies(sim_node + rclcpp + tf2 + tf2_geometry_msgs +) + +INSTALL(TARGETS sim_node + DESTINATION lib/${PROJECT_NAME}) + +## +# sim_node +## + +rosidl_generate_interfaces(${PROJECT_NAME} + "src/srv/RemoveArea.srv" + "src/srv/RemoveDockingStation.srv" + "src/srv/SaveArea.srv" + "src/srv/SaveDockingStation.srv" + "src/msg/Area.msg" + "src/msg/Map.msg" + "src/msg/DockingStation.msg" + DEPENDENCIES + std_msgs + geometry_msgs + sensor_msgs + tf2 + tf2_geometry_msgs +) + +ament_export_dependencies(rosidl_default_runtime) +rosidl_target_interfaces(map_server_node ${PROJECT_NAME} "rosidl_typesupport_cpp") +rosidl_target_interfaces(sim_node ${PROJECT_NAME} "rosidl_typesupport_cpp") + +if (BUILD_TESTING) + find_package(ament_lint_auto REQUIRED) + # the following line skips the linter which checks for copyrights + # comment the line when a copyright and license is added to all source files + set(ament_cmake_copyright_FOUND TRUE) + # the following line skips cpplint (only works in a git repo) + # comment the line when this package is in a git repo and when + # a copyright and license is added to all source files + set(ament_cmake_cpplint_FOUND TRUE) + ament_lint_auto_find_test_dependencies() +endif () + +INSTALL( + DIRECTORY config launch description worlds maps + DESTINATION share/${PROJECT_NAME} +) + +ament_package() diff --git a/Makefile b/Makefile index 431e067..e162d0d 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ -OPENMOWER_REMOTE_IP ?= 10.0.251.104 -OPENMOWER_REMOTE_USER ?= openmower +REMOTE_HOST ?= omdev.local +REMOTE_USER ?= openmower ROS_LOG_DIR = log/ -all: deps build +all: custom-deps deps build .PHONY: deps build @@ -11,19 +11,23 @@ dev-containers: # turtlebot3_gazebo does not have a build on iron arm64 deps: - rosdep install --from-paths src -i -y --skip-keys="turtlebot3_gazebo" + rosdep install --from-paths ./ -i -y -r custom-deps: sh utils/install-custom-deps.sh +build-libs: + colcon build --base-paths "src/lib/*" + build: colcon build --symlink-install sim: - ros2 launch src/openmower/launch/sim.launch.py + killall -9 ruby || true + ros2 launch launch/sim.launch.py run: - ros2 launch src/openmower/launch/openmower.launch.py + ros2 launch launch/openmower.launch.py dev: cd .devcontainer && docker-compose up -d @@ -35,7 +39,7 @@ run-foxglove: ros2 launch foxglove_bridge foxglove_bridge_launch.xml rsp: - ros2 launch src/openmower/launch/rsp.launch.py + ros2 launch launch/rsp.launch.py remote-devices: - sudo bash .devcontainer/scripts/remote_devices.sh $(OPENMOWER_REMOTE_IP) $(OPENMOWER_REMOTE_USER) + sudo bash .devcontainer/scripts/remote_devices.sh $(REMOTE_HOST) $(REMOTE_USER) diff --git a/NOTES.md b/NOTES.md new file mode 100644 index 0000000..177a07c --- /dev/null +++ b/NOTES.md @@ -0,0 +1,2 @@ +- [generate parameter library](https://github.com/PickNikRobotics/generate_parameter_library) +- [run ROS2 on RaspberryPi 5 Ubuntu 23.10](https://lkseng.github.io/posts/2024/01/07/ros-2-humble-on-raspberrypi-5.html) diff --git a/README.md b/README.md index 996e148..da0a0d4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# OpenMower ROS 2 +cd# OpenMower ROS 2 > Just another software stack for OpenMower lawn mower robot, but this time with ROS2! @@ -10,4 +10,4 @@ The initial goal of this project is to get learn about robot development using R ## Documentation -Documentation is available at [jkaflik.github.io/OpenMowerROS2](https://jkaflik.github.io/OpenMowerROS2/). \ No newline at end of file +Documentation is available at [jkaflik.github.io/OpenMowerNext](https://jkaflik.github.io/OpenMowerNext/). \ No newline at end of file diff --git a/config/behavior_tree.xml b/config/behavior_tree.xml new file mode 100644 index 0000000..323ed82 --- /dev/null +++ b/config/behavior_tree.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/openmower/config/controllers.yaml b/config/controllers.yaml similarity index 100% rename from src/openmower/config/controllers.yaml rename to config/controllers.yaml diff --git a/src/openmower/config/gps.yaml b/config/gps.yaml similarity index 100% rename from src/openmower/config/gps.yaml rename to config/gps.yaml diff --git a/src/openmower/config/hardware/openmower.yaml b/config/hardware/openmower.yaml similarity index 100% rename from src/openmower/config/hardware/openmower.yaml rename to config/hardware/openmower.yaml diff --git a/src/openmower/config/hardware/vesc.yaml b/config/hardware/vesc.yaml similarity index 100% rename from src/openmower/config/hardware/vesc.yaml rename to config/hardware/vesc.yaml diff --git a/src/openmower/config/hardware/yardforce500.yaml b/config/hardware/yardforce500.yaml similarity index 100% rename from src/openmower/config/hardware/yardforce500.yaml rename to config/hardware/yardforce500.yaml diff --git a/config/nav2_params.yaml b/config/nav2_params.yaml new file mode 100644 index 0000000..f33824c --- /dev/null +++ b/config/nav2_params.yaml @@ -0,0 +1,234 @@ +coverage_server: + ros__parameters: + use_sim_time: True + default_headland_width: 0.25 + robot_width: 0.7 + operation_width: 0.7 + min_turning_radius: 0.35 + linear_curv_change: 200.0 + coordinates_in_cartesian_frame: true + default_allow_overlap: false + default_swath_angle_type: "SET_ANGLE" + default_swath_angle: 0.0 # We know its aligned for the demo + +bt_navigator: + ros__parameters: + use_sim_time: True + global_frame: map + robot_base_frame: base_link + odom_topic: /odometry/filtered/map + bt_loop_duration: 10 + default_server_timeout: 20 + default_coverage_bt_xml: /home/ws/config/behavior_tree.xml + # 'default_coverage_bt_xml' uses defaults: + # opennav_coverage_bt/behavior_tree/navigate_w_basic_complete_coverage.xml + navigators: ["navigate_complete_coverage", "navigate_to_pose","navigate_through_poses"] + navigate_complete_coverage: + plugin: "opennav_coverage_navigator/CoverageNavigator" + navigate_to_pose: + plugin: "nav2_bt_navigator/NavigateToPoseNavigator" + navigate_through_poses: + plugin: "nav2_bt_navigator/NavigateThroughPosesNavigator" + error_code_names: ["compute_path_error_code", "follow_path_error_code", "compute_coverage_error_code"] + plugin_lib_names: + - nav2_compute_path_to_pose_action_bt_node + - nav2_compute_path_through_poses_action_bt_node + - nav2_smooth_path_action_bt_node + - nav2_follow_path_action_bt_node + - nav2_spin_action_bt_node + - nav2_wait_action_bt_node + - nav2_assisted_teleop_action_bt_node + - nav2_back_up_action_bt_node + - nav2_drive_on_heading_bt_node + - nav2_clear_costmap_service_bt_node + - nav2_is_stuck_condition_bt_node + - nav2_goal_reached_condition_bt_node + - nav2_goal_updated_condition_bt_node + - nav2_globally_updated_goal_condition_bt_node + - nav2_is_path_valid_condition_bt_node + - nav2_are_error_codes_active_condition_bt_node + - nav2_would_a_controller_recovery_help_condition_bt_node + - nav2_would_a_planner_recovery_help_condition_bt_node + - nav2_would_a_smoother_recovery_help_condition_bt_node + - nav2_initial_pose_received_condition_bt_node + - nav2_reinitialize_global_localization_service_bt_node + - nav2_rate_controller_bt_node + - nav2_distance_controller_bt_node + - nav2_speed_controller_bt_node + - nav2_truncate_path_action_bt_node + - nav2_truncate_path_local_action_bt_node + - nav2_goal_updater_node_bt_node + - nav2_recovery_node_bt_node + - nav2_pipeline_sequence_bt_node + - nav2_round_robin_node_bt_node + - nav2_transform_available_condition_bt_node + - nav2_time_expired_condition_bt_node + - nav2_path_expiring_timer_condition + - nav2_distance_traveled_condition_bt_node + - nav2_single_trigger_bt_node + - nav2_goal_updated_controller_bt_node + - nav2_is_battery_low_condition_bt_node + - nav2_navigate_through_poses_action_bt_node + - nav2_navigate_to_pose_action_bt_node + - nav2_remove_passed_goals_action_bt_node + - nav2_planner_selector_bt_node + - nav2_controller_selector_bt_node + - nav2_goal_checker_selector_bt_node + - nav2_controller_cancel_bt_node + - nav2_path_longer_on_approach_bt_node + - nav2_wait_cancel_bt_node + - nav2_spin_cancel_bt_node + - nav2_back_up_cancel_bt_node + - nav2_assisted_teleop_cancel_bt_node + - nav2_drive_on_heading_cancel_bt_node + - nav2_is_battery_charging_condition_bt_node + - opennav_compute_complete_coverage_action_bt_node + - opennav_cancel_complete_coverage_action_bt_node + +controller_server: + ros__parameters: + use_sim_time: True + controller_frequency: 20.0 + min_x_velocity_threshold: 0.001 + min_y_velocity_threshold: 0.5 + min_theta_velocity_threshold: 0.001 + failure_tolerance: 0.3 + progress_checker_plugin: "progress_checker" + goal_checker_plugins: ["general_goal_checker"] + controller_plugins: ["FollowPath"] + # Progress checker parameters + progress_checker: + plugin: "nav2_controller::SimpleProgressChecker" + required_movement_radius: 0.5 + movement_time_allowance: 10.0 + # Goal checker parameters + general_goal_checker: + stateful: True + plugin: "nav2_controller::SimpleGoalChecker" + xy_goal_tolerance: 0.25 + yaw_goal_tolerance: 0.25 + # RPP parameters + FollowPath: + plugin: "nav2_regulated_pure_pursuit_controller::RegulatedPurePursuitController" + desired_linear_vel: 0.5 + lookahead_dist: 0.6 + min_lookahead_dist: 0.3 + max_lookahead_dist: 0.9 + lookahead_time: 1.5 + rotate_to_heading_angular_vel: 1.8 + use_velocity_scaled_lookahead_dist: true + min_approach_linear_velocity: 0.05 + approach_velocity_scaling_dist: 0.6 + use_collision_detection: true + max_allowed_time_to_collision_up_to_carrot: 1.0 + use_regulated_linear_velocity_scaling: true + use_fixed_curvature_lookahead: false + curvature_lookahead_dist: 0.25 + use_cost_regulated_linear_velocity_scaling: false + regulated_linear_scaling_min_radius: 0.9 + regulated_linear_scaling_min_speed: 0.25 + use_rotate_to_heading: false # allows to follow coverage path better in sharper turns + allow_reversing: false + rotate_to_heading_min_angle: 0.785 + max_angular_accel: 3.2 + max_robot_pose_search_dist: 10.0 + use_interpolation: true + +local_costmap: + local_costmap: + ros__parameters: + use_sim_time: True + update_frequency: 5.0 + publish_frequency: 2.0 + global_frame: odom + robot_base_frame: base_link + rolling_window: true + width: 3 + height: 3 + resolution: 0.05 + robot_radius: 0.5 + plugins: + - static_layer + static_layer: + plugin: "nav2_costmap_2d::StaticLayer" + map_subscribe_transient_local: True + map_topic: "/map_grid" + always_send_full_costmap: True + +global_costmap: + global_costmap: + ros__parameters: + update_frequency: 1.0 + publish_frequency: 1.0 + global_frame: map + robot_base_frame: base_link + robot_radius: 0.5 + resolution: 0.05 + track_unknown_space: true + plugins: ["static_layer"] + static_layer: + plugin: "nav2_costmap_2d::StaticLayer" + map_subscribe_transient_local: True + map_topic: "/map_grid" + always_send_full_costmap: True + + +robot_state_publisher: + ros__parameters: + use_sim_time: True + +bt_navigator_navigate_complete_coverage_rclcpp_node: + ros__parameters: + use_sim_time: True + +velocity_smoother: + ros__parameters: + use_sim_time: True + smoothing_frequency: 20.0 + scale_velocities: False + feedback: "OPEN_LOOP" + max_velocity: [0.26, 0.0, 1.0] + min_velocity: [-0.26, 0.0, -1.0] + max_accel: [2.5, 0.0, 3.2] + max_decel: [-2.5, 0.0, -3.2] + odom_topic: "/odometry/filtered/map" + odom_duration: 0.1 + deadband_velocity: [0.0, 0.0, 0.0] + velocity_timeout: 1.0 + +planner_server: + ros__parameters: + expected_planner_frequency: 20.0 + planner_plugins: ["GridBased"] + GridBased: + plugin: "nav2_navfn_planner/NavfnPlanner" + tolerance: 0.5 + use_astar: false + allow_unknown: true + +behavior_server: + ros__parameters: + local_costmap_topic: local_costmap/costmap_raw + global_costmap_topic: global_costmap/costmap_raw + local_footprint_topic: local_costmap/published_footprint + global_footprint_topic: global_costmap/published_footprint + cycle_frequency: 10.0 + behavior_plugins: ["spin", "backup", "drive_on_heading", "assisted_teleop", "wait"] + spin: + plugin: "nav2_behaviors/Spin" + backup: + plugin: "nav2_behaviors/BackUp" + drive_on_heading: + plugin: "nav2_behaviors/DriveOnHeading" + wait: + plugin: "nav2_behaviors/Wait" + assisted_teleop: + plugin: "nav2_behaviors/AssistedTeleop" + local_frame: odom + global_frame: map + robot_base_frame: base_link + transform_tolerance: 0.1 + simulate_ahead_time: 2.0 + max_rotational_vel: 1.0 + min_rotational_vel: 0.4 + rotational_acc_lim: 3.2 diff --git a/src/openmower/config/robot_localization.yaml b/config/robot_localization.yaml similarity index 99% rename from src/openmower/config/robot_localization.yaml rename to config/robot_localization.yaml index 025bb15..b2f79ef 100644 --- a/src/openmower/config/robot_localization.yaml +++ b/config/robot_localization.yaml @@ -1,7 +1,7 @@ ekf_se_odom: ros__parameters: - frequency: 30.0 - sensor_timeout: 0.1 + frequency: 50.0 + sensor_timeout: 0.025 two_d_mode: true transform_time_offset: 0.0 transform_timeout: 0.0 @@ -25,7 +25,7 @@ ekf_se_odom: true, true, true, false, false, true, false, false, false] - odom0_queue_size: 10 + odom0_queue_size: 50 odom0_nodelay: true odom0_differential: false odom0_relative: false @@ -39,7 +39,7 @@ ekf_se_odom: imu0_nodelay: false imu0_differential: false imu0_relative: false - imu0_queue_size: 10 + imu0_queue_size: 100 imu0_remove_gravitational_acceleration: true use_control: false @@ -78,7 +78,7 @@ ekf_se_odom: ekf_se_map: ros__parameters: - frequency: 10.0 + frequency: 50.0 sensor_timeout: 0.1 two_d_mode: true transform_time_offset: 0.0 diff --git a/src/openmower/config/twist_mux.yaml b/config/twist_mux.yaml similarity index 100% rename from src/openmower/config/twist_mux.yaml rename to config/twist_mux.yaml diff --git a/src/openmower/config/view_bot.rviz b/config/view_bot.rviz similarity index 100% rename from src/openmower/config/view_bot.rviz rename to config/view_bot.rviz diff --git a/custom_deps.yaml b/custom_deps.yaml index e45934e..3c56b82 100644 --- a/custom_deps.yaml +++ b/custom_deps.yaml @@ -14,4 +14,20 @@ repositories: ntrip_client: type: git url: https://github.com/LORD-MicroStrain/ntrip_client - version: feature/ros2_prefer_rtcm_msgs # feature branch with a rtcm_msgs support \ No newline at end of file + version: ros2 + fields2cover: + type: git + url: https://github.com/Fields2Cover/Fields2Cover.git + version: v1.2.1 + opennav_coverage: + type: git + url: https://github.com/open-navigation/opennav_coverage.git + version: iron + ros_gz: + type: git + url: https://github.com/gazebosim/ros_gz.git + version: iron + gz_ros2_control: + type: git + url: https://github.com/ros-controls/gz_ros2_control + version: iron \ No newline at end of file diff --git a/src/openmower/description/camera.xacro b/description/camera.xacro similarity index 100% rename from src/openmower/description/camera.xacro rename to description/camera.xacro diff --git a/src/openmower/description/gazebo_control.xacro b/description/gazebo_control.xacro similarity index 86% rename from src/openmower/description/gazebo_control.xacro rename to description/gazebo_control.xacro index 9e5bd0f..22ee168 100644 --- a/src/openmower/description/gazebo_control.xacro +++ b/description/gazebo_control.xacro @@ -31,7 +31,9 @@ - $(find openmower)/config/controllers.yaml + $(find open_mower_next)/config/controllers.yaml + robot_description + robot_state_publisher diff --git a/src/openmower/description/gps.xacro b/description/gps.xacro similarity index 92% rename from src/openmower/description/gps.xacro rename to description/gps.xacro index a17ede3..d209f0f 100644 --- a/src/openmower/description/gps.xacro +++ b/description/gps.xacro @@ -11,7 +11,7 @@ - gps + gps 1 5 gps/fix diff --git a/src/openmower/description/imu.xacro b/description/imu.xacro similarity index 83% rename from src/openmower/description/imu.xacro rename to description/imu.xacro index f12959c..3a98f43 100644 --- a/src/openmower/description/imu.xacro +++ b/description/imu.xacro @@ -11,8 +11,8 @@ - imu - + imu + 1 50 true diff --git a/src/openmower/description/inertial_macros.xacro b/description/inertial_macros.xacro similarity index 100% rename from src/openmower/description/inertial_macros.xacro rename to description/inertial_macros.xacro diff --git a/src/openmower/description/robot.urdf.xacro b/description/robot.urdf.xacro similarity index 87% rename from src/openmower/description/robot.urdf.xacro rename to description/robot.urdf.xacro index 99505bc..1e6560e 100644 --- a/src/openmower/description/robot.urdf.xacro +++ b/description/robot.urdf.xacro @@ -4,7 +4,7 @@ - + diff --git a/src/openmower/description/robot_core.xacro b/description/robot_core.xacro similarity index 96% rename from src/openmower/description/robot_core.xacro rename to description/robot_core.xacro index 27506d2..68e4ff1 100644 --- a/src/openmower/description/robot_core.xacro +++ b/description/robot_core.xacro @@ -49,6 +49,15 @@ + + + true + true + + + diff --git a/src/openmower/description/ros2_control.xacro b/description/ros2_control.xacro similarity index 97% rename from src/openmower/description/ros2_control.xacro rename to description/ros2_control.xacro index 5196218..d95bb12 100644 --- a/src/openmower/description/ros2_control.xacro +++ b/description/ros2_control.xacro @@ -1,7 +1,7 @@ - + diff --git a/docs/.gitignore b/docs/.gitignore index 48298f1..e993c1c 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,2 +1,3 @@ .vitepress/cache -dist/ \ No newline at end of file +dist/ +node_modules/ \ No newline at end of file diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 42a3bf1..850550e 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -3,9 +3,9 @@ import { withMermaid } from "vitepress-plugin-mermaid"; // https://vitepress.dev/reference/site-config export default withMermaid({ - title: "OpenMowerROS2", + title: "OpenMowerNext", description: "Just another software stack for OpenMower lawn mower robot, but this time with ROS2!", - base: "/OpenMowerROS2/", + base: "/OpenMowerNext/", ignoreDeadLinks: [ // ignore all localhost links /^https?:\/\/localhost/, @@ -55,7 +55,7 @@ export default withMermaid({ ], socialLinks: [ - { icon: 'github', link: 'https://github.com/jkaflik/OpenMowerROS2' }, + { icon: 'github', link: 'https://github.com/jkaflik/OpenMowerNext' }, { icon: 'discord', link: 'https://discord.gg/jE7QNaSxW7' }, ] } diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..0502b38 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,20 @@ +--- +title: Configuration +--- +# {{ $frontmatter.title }} + +## Overview + +Currently most of the configuration is hardcoded everywhere in the code. +Only a few things are configurable using environment variables. +The goal is to: +- all ROS nodes should be configurable using ROS parameters +- when applicable, parameter should support a hot reload +- all parameter change should be persisted and restored on the next start +- documentation should be available for all parameters + +## Environment variables + +- `OM_MAP_PATH` - path to the map file (see: [map management](map-management.md)) +- `OM_DATUM_LAT` - latitude of the datum point +- `OM_DATUM_LON` - longitude of the datum point diff --git a/docs/contributing.md b/docs/contributing.md index ab3b653..aae0835 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -14,7 +14,7 @@ If you are not familiar with ROS, you can start with [ROS2 tutorials](https://do 2. **Clone the Repository**: ```bash - git clone https://github.com/your_username/OpenMowerROS2.git + git clone https://github.com/your_username/OpenMowerNext.git ``` 3. **Set Up ROS2**: Ensure you have ROS2 installed and configured on your system. @@ -23,7 +23,7 @@ If you are not familiar with ROS, you can start with [ROS2 tutorials](https://do ::: info This section is not complete yet. It will be updated as the project progresses. - There is no instruction how to setup ROS2 workspace standalone yet. For a reference, [Dockerfile](https://github.com/jkaflik/OpenMowerROS2/blob/main/Dockerfile) can be used. + There is no instruction how to setup ROS2 workspace standalone yet. For a reference, [Dockerfile](https://github.com/jkaflik/OpenMowerNext/blob/main/Dockerfile) can be used. ::: --- diff --git a/docs/devcontainer.md b/docs/devcontainer.md index 1daf45d..e76aec6 100644 --- a/docs/devcontainer.md +++ b/docs/devcontainer.md @@ -32,3 +32,9 @@ Devcontainer comes up with some containers configured with Docker Compose: All containers share the same X server socket, so GUI applications can be run from the `workspace` container and displayed in the `xserver` container. VNC server in `xserver` runs a web server on port `12345` with a VNC client. You can access it by opening [`http://localhost:12345`](http://localhost:12345) in your browser. + +## Default environment variables loaded in the image + +<<< ../.devcontainer/openmower_config.env{bash} + +For more details about the environment variables, see [Configuration](configuration.md). diff --git a/docs/getting-started.md b/docs/getting-started.md index 4aa288b..7c24885 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -7,13 +7,13 @@ Let's get started with a quick overview of the project. ::: warning Project is in early development stage. Actual mower logic is missing and things are likely to change. -The list of identified missing features can be found in GitHub [issues](https://github.com/jkaflik/OpenMowerROS2/issues). +The list of identified missing features can be found in GitHub [issues](https://github.com/jkaflik/OpenMowerNext/issues). ::: ## Overview The purpose of this project is no different from original [OpenMower project ROS implementation](https://github.com/ClemensElflein/open_mower_ros). -OpenMowerROS2 is build on top of [ROS2](https://index.ros.org/doc/ros2/) following all the best practices and recommendations. +OpenMowerNext is build on top of [ROS2](https://index.ros.org/doc/ros2/) following all the best practices and recommendations. At this stage of the project, only one intention to use it is contributing to the project. If you are interested in the project, please feel free to contribute. It was started as a learning project for myself, but I hope it will be useful for others as well. @@ -30,8 +30,10 @@ This section is not complete yet. It will be updated as the project progresses. - :white_check_mark: IMU - :white_check_mark: GPS - :construction: Simulation using Gazebo -- :construction: [Map management](https://github.com/jkaflik/OpenMowerROS2/issues/19) -- :pencil2: [Mower logic](https://github.com/jkaflik/OpenMowerROS2/issues/9) +- :construction: [Map management](https://github.com/jkaflik/OpenMowerNext/issues/19) +- :pencil2: [Mower logic](https://github.com/jkaflik/OpenMowerNext/issues/9) +- :pencil2: [Configuration](configuration.md) +- :pencil2: User interface ### Roadmap diff --git a/docs/groot.md b/docs/groot.md index 55557f9..d4d2434 100644 --- a/docs/groot.md +++ b/docs/groot.md @@ -11,7 +11,7 @@ GRoot is a GUI for [BehaviourTree.CPP](https://www.behaviortree.dev/). It is a g ![GRoot](https://raw.githubusercontent.com/BehaviorTree/Groot/master/groot-screenshot.png) ::: warning -BehaviourTree.CPP is not yet implemented in this project. See [issue](https://github.com/jkaflik/OpenMowerROS2/issues/9). +BehaviourTree.CPP is not yet implemented in this project. See [issue](https://github.com/jkaflik/OpenMowerNext/issues/9). ::: ## Run GRoot diff --git a/docs/index.md b/docs/index.md index 455f21f..137f8ef 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ layout: home hero: - name: "OpenMowerROS2" + name: "OpenMowerNext" tagline: Just another software stack for OpenMower lawn mower robot, but this time with ROS2! actions: - theme: brand @@ -11,10 +11,10 @@ hero: link: /getting-started - theme: alt text: View on GitHub - link: https://github.com/jkaflik/OpenMowerROS2 + link: https://github.com/jkaflik/OpenMowerNext image: src: /logo.png - alt: OpenMowerROS2 + alt: OpenMowerNext ---