diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3a5df5cd..368057d4 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -17,9 +17,15 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ python3-numpy \ libboost-python-dev \ libopencv-dev \ - python3-opencv + python3-opencv \ + ros-humble-cv-bridge + +RUN echo "/opt/ros/$ROS_DISTRO/lib" > /etc/ld.so.conf.d/ros2.conf \ + && echo "/opt/ros/$ROS_DISTRO/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" >> /etc/ld.so.conf.d/ros2.conf \ + && ldconfig RUN pip3 install --no-cache-dir \ + "numpy<2" \ moteus \ pyusb \ pybind11 \ @@ -55,11 +61,11 @@ RUN useradd trickfire --shell /bin/bash --create-home --no-log-init -G video,sud && touch /home/trickfire/.sudo_as_admin_successful \ && chown trickfire:trickfire /home/trickfire/.sudo_as_admin_successful -# trickfire is non-root, but SocketCAN raw sockets (candump/cansend and the RMD-X8 -# node's CanDriver) need CAP_NET_RAW/CAP_NET_ADMIN, which a non-root exec doesn't get -# just from the container's `cap_add`/`privileged` settings. Grant NOPASSWD sudo for -# only the specific CAN tooling and the built can_rmdx8 node so this works without an -# interactive password, without handing trickfire unrestricted root. +# Bringing the CAN link up needs CAP_NET_ADMIN, which non-root trickfire doesn't get just +# from the container's `privileged` setting, so grant NOPASSWD sudo for the CAN tooling +# that setup-can-network.sh drives. The can_rmdx8 node is deliberately NOT listed here: it +# has to run as trickfire like the rest of the ROS graph or cross-user FastDDS shared +# memory drops its traffic, and an AF_CAN raw socket needs no capability to open. COPY .devcontainer/trickfire-can-sudoers /etc/sudoers.d/trickfire-can RUN chmod 0440 /etc/sudoers.d/trickfire-can && visudo -cf /etc/sudoers.d/trickfire-can diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3f177b6e..45736447 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,8 +1,8 @@ { "dockerComposeFile": "docker-compose.yml", "service": "viator", - "workspaceFolder": "/home/trickfire/urc-2023", - "postCreateCommand": "pre-commit install", + "workspaceFolder": "/home/trickfire/viator", + "postCreateCommand": "make hooks", "customizations": { "vscode": { "extensions": [ diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index fa5c8599..b39b6842 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -4,12 +4,12 @@ services: context: .. dockerfile: .devcontainer/Dockerfile target: viator - image: urc-2023:latest + image: viator:latest container_name: viator user: trickfire volumes: - - ..:/home/trickfire/urc-2023 + - ..:/home/trickfire/viator # - /dev/video0:/dev/video0 - type: bind source: ${HOME}/.ssh @@ -18,7 +18,7 @@ services: bind: create_host_path: true - working_dir: /home/trickfire/urc-2023 + working_dir: /home/trickfire/viator network_mode: host diff --git a/.devcontainer/trickfire-can-sudoers b/.devcontainer/trickfire-can-sudoers index b545cf2b..06562fd4 100644 --- a/.devcontainer/trickfire-can-sudoers +++ b/.devcontainer/trickfire-can-sudoers @@ -1,3 +1 @@ -Defaults!/home/trickfire/urc-2023/install/can_rmdx8/lib/can_rmdx8/can_rmdx8 !env_reset, env_delete-="PYTHONPATH" - -trickfire ALL=(root) NOPASSWD: /usr/sbin/ip, /usr/sbin/modprobe, /usr/bin/candump, /usr/bin/cansend, /usr/bin/cangen, /usr/bin/cansniffer, /home/trickfire/urc-2023/install/can_rmdx8/lib/can_rmdx8/can_rmdx8 +trickfire ALL=(root) NOPASSWD: /usr/sbin/ip, /usr/sbin/modprobe, /usr/bin/candump, /usr/bin/cansend, /usr/bin/cangen, /usr/bin/cansniffer diff --git a/.devcontainer/trickfire.bashrc b/.devcontainer/trickfire.bashrc index 834bd39a..0a1edccd 100644 --- a/.devcontainer/trickfire.bashrc +++ b/.devcontainer/trickfire.bashrc @@ -22,7 +22,7 @@ fi [ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)" # ---------- ROS workspace overlay ---------- -export ROS_WS="${ROS_WS:-/home/trickfire/urc-2023}" +export ROS_WS="${ROS_WS:-/home/trickfire/viator}" _ros_source_env() { if [ -f "/opt/ros/${ROS_DISTRO}/setup.bash" ]; then diff --git a/.vscode/settings.json b/.vscode/settings.json index 342c687a..3e0c6fa4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -40,12 +40,12 @@ "python.autoComplete.extraPaths": [ "/opt/ros/humble/lib/python3.10/site-packages", "./src", - "/home/trickfire/urc-2023/install/custom_interfaces/local/lib/python3.10/dist-packages" + "/home/trickfire/viator/install/custom_interfaces/local/lib/python3.10/dist-packages" ], "python.analysis.extraPaths": [ "/opt/ros/humble/lib/python3.10/site-packages", "./src", - "/home/trickfire/urc-2023/install/custom_interfaces/local/lib/python3.10/dist-packages" + "/home/trickfire/viator/install/custom_interfaces/local/lib/python3.10/dist-packages" ], "python.analysis.diagnosticSeverityOverrides": { diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Makefile b/Makefile index 46f87d14..55ca2f35 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,11 @@ -.PHONY: build launch container connect can-setup sync-orin format hooks +.PHONY: build clean launch container connect can-setup sync-orin format hooks build: ./scripts/build.sh +clean: + rm -rf build install log + launch: ./scripts/launch.sh @@ -15,7 +18,7 @@ connect: can-setup: ./scripts/setup-can-network.sh -sync-orin: +sync: ./scripts/sync-to-orin.sh $(IP) $(REMOTE_PATH) format: diff --git a/README.md b/README.md index 2ece3dd7..e6e1a2ba 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ # Viator -Software developed by [Trickfire Robotics](https://www.trickfirerobotics.org/) for the Viator Rover built for the [University Rover Challenge](https://urc.marssociety.org/), using [ROS2 Humble](https://docs.ros.org/en/humble/index.html). +Software developed by [Trickfire Robotics](https://www.trickfirerobotics.org/) for the Viator Rover built for the [University Rover Challenge](https://urc.marssociety.org/). ## Documentation -**Full documentation is at [docs.trickfirerobotics.com/simulations](https://docs.trickfirerobotics.com/simulations).** See also our -[Notion wiki](https://www.notion.so/trickfire/Getting-Started-With-Viator-Rover-1491fd41ff5b801485e0f6ad57e0a0aa). +**Full documentation is at [docs.trickfirerobotics.com/simulations](https://docs.trickfirerobotics.com/viator).** -- [Getting Started](http://docs.trickfirerobotics.com/urc-2023/getting-started) - dev environment setup -- [Architecture](http://docs.trickfirerobotics.com/urc-2023/architecture) - architecture decisions/explanations -- [Rover Launch](http://docs.trickfirerobotics.com/urc-2023/launching) - how to launch Viator +- [Getting Started](http://docs.trickfirerobotics.com/viator/getting-started) - dev environment setup +- [Architecture](http://docs.trickfirerobotics.com/viator/architecture) - architecture decisions/explanations +- [Rover Launch](http://docs.trickfirerobotics.com/viator/launching) - how to launch Viator diff --git a/docs/architecture.mdx b/docs/architecture.mdx index 59459c4c..38ff94dd 100644 --- a/docs/architecture.mdx +++ b/docs/architecture.mdx @@ -7,7 +7,7 @@ slug: architecture ## Repo layout ``` -urc-2023/ +viator/ ├── src/ # ROS 2 workspace (colcon) │ ├── arm/ # Arm control node │ ├── camera/ # Camera streaming node @@ -31,13 +31,13 @@ urc-2023/ Not a ROS node itself; every node package imports from here. -| File | Purpose | -| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `lib/configs.py` | Static motor configuration (CAN IDs, motor type, gear ratios) shared across the whole robot. | -| `lib/interface/robot_interface.py` | `RobotInterface` — the utility class nodes use to command motors (converts between physical units and raw motor commands, publishes over the CAN bridges). | -| `lib/interface/robot_info.py` | `RobotInfo` — the read-side counterpart: subscribes to motor state topics and exposes the current state of every motor on the robot. | -| `lib/motor_state/` | Typed state objects for each motor backend (`CANMotorState`, `MoteusMotorState`, `RMDX8MotorState`). | -| `lib/color_codes.py`, `lib/json_msg.py` | Small logging/serialization helpers. | +| File | Purpose | +| --- | --- | +| `lib/configs.py` | Static motor configuration (CAN IDs, motor type, gear ratios) shared across the whole robot. | +| `lib/interface/robot_interface.py` | `RobotInterface` — the utility class nodes use to command motors (converts between physical units and raw motor commands, publishes over the CAN bridges). | +| `lib/interface/robot_info.py` | `RobotInfo` — the read-side counterpart: subscribes to motor state topics and exposes the current state of every motor on the robot. | +| `lib/motor_state/` | Typed state objects for each motor backend (`CANMotorState`, `MoteusMotorState`, `RMDX8MotorState`). | +| `lib/color_codes.py`, `lib/json_msg.py` | Small logging/serialization helpers. | ## Motor drivers @@ -62,13 +62,13 @@ Two independent CAN motor controller backends, both bridging to the shared `lib/ ## Robot-facing nodes -| Node | Description | -| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `drivebase` | Subscribes to left/right drive commands and forwards them to the wheel motors via `RobotInterface`. | -| `arm` | Arm control; supports per-motor velocity/position control today (`individual_control_vel.py`), with inverse kinematics stubbed out as a future `ArmModeEnum` mode. Mode is switched at runtime via the `custom_interfaces/srv/ArmMode` service. | -| `camera` | `roscamera` node (`camera/roscamera.py`) enumerates connected USB cameras and publishes compressed image streams over `sensor_msgs/CompressedImage`. | -| `heartbeat` | Connection watchdog: if the base station connection drops, it's responsible for cutting power to the motors as a safety stop. | -| `mission_control_updater` | Periodically collects motor state via `RobotInfo`, serializes it to JSON (`info_to_json_helper.py`), and publishes it for the mission control dashboard (delivered over `ros-humble-rosbridge-server`, installed in the Dockerfile). | +| Node | Description | +| --- | --- | +| `drivebase` | Subscribes to left/right drive commands and forwards them to the wheel motors via `RobotInterface`. | +| `arm` | Arm control; supports per-motor velocity/position control today (`individual_control_vel.py`), with inverse kinematics stubbed out as a future `ArmModeEnum` mode. Mode is switched at runtime via the `custom_interfaces/srv/ArmMode` service. | +| `camera` | `roscamera` node (`camera/roscamera.py`) enumerates connected USB cameras and publishes compressed image streams over `sensor_msgs/CompressedImage`. | +| `heartbeat` | Connection watchdog: if the base station connection drops, it's responsible for cutting power to the motors as a safety stop. | +| `mission_control_updater` | Periodically collects motor state via `RobotInfo`, serializes it to JSON (`info_to_json_helper.py`), and publishes it for the mission control dashboard (delivered over `ros-humble-rosbridge-server`, installed in the Dockerfile). | ## `custom_interfaces` diff --git a/docs/getting-started.mdx b/docs/getting-started.mdx index d53f94e6..18fe9e93 100644 --- a/docs/getting-started.mdx +++ b/docs/getting-started.mdx @@ -4,39 +4,28 @@ description: Set up a development environment for the Viator rover software. slug: / --- -This is the software for **Viator**, Trickfire Robotics' rover for the [University Rover -Challenge](https://urc.marssociety.org/), built on [ROS 2 Humble](https://docs.ros.org/en/humble/). +This is the software for **Viator**, Trickfire Robotics' rover for the [University Rover Challenge](https://urc.marssociety.org/), built on [ROS 2 Humble](https://docs.ros.org/en/humble/). ## Prerequisites - [Docker](https://docs.docker.com/get-docker/) -- [Visual Studio Code](https://code.visualstudio.com/) with the - [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - extension +- [Visual Studio Code](https://code.visualstudio.com/) with the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension -Development happens inside a Docker container so every contributor gets the same ROS 2 Humble -environment, regardless of host OS. +Development happens inside a Docker container so every contributor gets the same ROS 2 Humble environment, regardless of host OS. ## Set up the dev container 1. Clone the repo (with submodules): ```bash title="Terminal" - git clone --recurse-submodules https://github.com/TrickfireRobotics/urc-2023.git + git clone --recurse-submodules https://github.com/TrickfireRobotics/viator.git ``` -2. Open the folder in VS Code and choose **Reopen in Container** when prompted (or run - **Dev Containers: Reopen in Container** from the command palette). This uses - `.devcontainer/docker-compose.yml` to build `.devcontainer/Dockerfile` (which installs - ROS 2 Humble, the CAN/motor tooling, and the - [myactuator_rmd](https://github.com/2b-t/myactuator_rmd) library) and starts it as a - container named `viator`, so it's easy to find with `docker ps`. +2. Open the folder in VS Code and choose **Reopen in Container** when prompted (or run **Dev Containers: Reopen in Container** from the command palette). This uses `.devcontainer/docker-compose.yml` to build `.devcontainer/Dockerfile` (which installs ROS 2 Humble, the CAN/motor tooling, and the [myactuator_rmd](https://github.com/2b-t/myactuator_rmd) library) and starts it as a container named `viator`, so it's easy to find with `docker ps`. ## Build and launch -All common actions are exposed as `make` targets from the repo root — see -[Launching the Rover](launching) for the full workflow. The short version, from inside the -container: +All common actions are exposed as `make` targets from the repo root — see [Launching the Rover](launching) for the full workflow. The short version, from inside the container: ```bash title="Terminal" make build # colcon build --symlink-install @@ -51,20 +40,15 @@ make launch # ros2 launch viator_launch robot.launch.py ## Formatting and linting -Python is formatted/linted with [Ruff](https://docs.astral.sh/ruff/) and type-checked with -[mypy](https://mypy-lang.org/); shell scripts are formatted with -[shfmt](https://github.com/mvdan/sh). Install the recommended VS Code extensions when prompted, -or run everything manually: +Python is formatted/linted with [Ruff](https://docs.astral.sh/ruff/) and type-checked with [mypy](https://mypy-lang.org/); shell scripts are formatted with [shfmt](https://github.com/mvdan/sh). Install the recommended VS Code extensions when prompted, or run everything manually: ```bash title="Terminal" make format ``` -Run `make hooks` once after cloning to install the pre-commit hooks that enforce this -automatically at commit time. +Run `make hooks` once after cloning to install the pre-commit hooks that enforce this automatically at commit time. ## Where to go next - [Architecture](architecture) — what each ROS package does and how they fit together. -- [Launching the Rover](launching) — the full build → CAN setup → launch workflow, including - deploying to the onboard Orin. +- [Launching the Rover](launching) — the full build → CAN setup → launch workflow, including deploying to the onboard Orin. diff --git a/docs/launching.mdx b/docs/launching.mdx index 847db4ac..eeb3ecda 100644 --- a/docs/launching.mdx +++ b/docs/launching.mdx @@ -7,7 +7,7 @@ This walks through the full workflow for getting Viator's software running end t ## Start mission control -Mission control lives in its own repo, separate from `urc-2023`. +Mission control lives in its own repo, separate from `viator`. @@ -37,15 +37,15 @@ Mission control lives in its own repo, separate from `urc-2023`. - Mission control is a plain Node/Vite project - run it on your host, not inside the `urc-2023` - dev container. + Mission control is a plain Node/Vite project - run it on your host, not inside the `viator` dev + container. ## Connect to the rover ```bash title="Terminal" ssh trickfire@192.168.0.112 -cd ~/urc-2023 +cd ~/viator ``` ## Bring up the CAN bus @@ -68,7 +68,7 @@ Back in the first terminal, bring the CAN interface up: make can-setup ``` -This loads the `can`/`can_raw`/`mttcan` kernel modules, brings `can1` up at a 1 Mbit bitrate, and sends enable + speed-mode commands to the drivebase motors (CAN IDs `0x155`-`0x15A`). You should see that traffic show up in the `candump` terminal. +This loads the `can`/`can_raw`/`mttcan` kernel modules, brings `can0` up at a 1 Mbit bitrate, and sends enable + speed-mode commands to the drivebase motors (CAN IDs `0x155`-`0x15A`). You should see that traffic show up in the `candump` terminal. ## Build and launch diff --git a/scripts/build.sh b/scripts/build.sh index d2942208..148fc8d7 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,8 +1,10 @@ #!/usr/bin/env bash +cd "$(dirname "$0")/.." + source /opt/ros/$ROS_DISTRO/setup.bash colcon build \ --symlink-install \ - --base-paths /home/trickfire/urc-2023 --cmake-args \ + --base-paths . --cmake-args \ -DCMAKE_BUILD_TYPE=Debug diff --git a/scripts/launch.sh b/scripts/launch.sh index 0aa2012c..5d12e344 100755 --- a/scripts/launch.sh +++ b/scripts/launch.sh @@ -1,14 +1,13 @@ #!/usr/bin/env bash +cd "$(dirname "$0")/.." -source /opt/ros/$ROS_DISTRO/setup.bash -source /home/trickfire/urc-2023/install/setup.bash - -#modprobe can -#modprobe can_raw -#modprobe mttcan -#ip link set can0 type can bitrate 1000000 dbitrate 5000000 fd on -#ip link set can0 up +# enable colored logs +export RCUTILS_COLORIZED_OUTPUT=1 +export PYTHONPATH="$(pwd)/src/:$PYTHONPATH" -export PYTHONPATH="/home/trickfire/urc-2023/src/:$PYTHONPATH" +# source ros +source /opt/ros/$ROS_DISTRO/setup.bash +source ./install/setup.bash -ros2 launch viator_launch robot.launch.py --log-level rosbridge_websocket:=warn +# launch using ros +ros2 launch viator_launch robot.launch.py diff --git a/scripts/setup-can-network.sh b/scripts/setup-can-network.sh index 5cb76709..e863add2 100755 --- a/scripts/setup-can-network.sh +++ b/scripts/setup-can-network.sh @@ -1,20 +1,35 @@ #!/bin/bash +set -e + +IFACE="${CAN_IFACE:-can0}" +BITRATE=1000000 # Commands START_CMD="8800000000000000" CLEAR_CMD="9B00000000000000" SPEED_CMD="A200000000000000" +can_state() { + ip -details link show "$IFACE" | awk '/berr-counter/ {for (i = 1; i <= NF; i++) if ($i == "state") print $(i + 1)}' +} + +tx_packets() { + ip -s link show "$IFACE" | awk '/^ *TX:/ {getline; print $2}' +} + # Ensure driver dependencies are loaded sudo modprobe can sudo modprobe can_raw sudo modprobe mttcan # Set up the CAN interface -sudo ip link set can1 down -sudo ip link set can1 type can bitrate 1000000 -sudo ip link set can1 up -echo "CAN interface can1 set up successfully." +sudo ip link set "$IFACE" down +sudo ip link set "$IFACE" type can bitrate "$BITRATE" +sudo ip link set "$IFACE" up +echo "CAN interface $IFACE set up successfully." + +TX_BEFORE=$(tx_packets) +TX_BEFORE=${TX_BEFORE:-0} # Motor CAN IDs (hexadecimal) MOTOR_IDS=("155" "156" "157" "158" "159" "15A") @@ -22,16 +37,31 @@ MOTOR_IDS=("155" "156" "157" "158" "159" "15A") # Enable motors in speed mode for CAN_ID in "${MOTOR_IDS[@]}"; do echo "Sending clear command to CAN ID 0x$CAN_ID: $CLEAR_CMD" - sudo cansend can1 "$CAN_ID#$CLEAR_CMD" + sudo cansend "$IFACE" "$CAN_ID#$CLEAR_CMD" sleep 0.1 echo "Sending start command to CAN ID 0x$CAN_ID: $START_CMD" - sudo cansend can1 "$CAN_ID#$START_CMD" + sudo cansend "$IFACE" "$CAN_ID#$START_CMD" sleep 0.1 echo "Sending speed mode command to CAN ID 0x$CAN_ID: $SPEED_CMD" - sudo cansend can1 "$CAN_ID#$SPEED_CMD" + sudo cansend "$IFACE" "$CAN_ID#$SPEED_CMD" sleep 0.1 done +TX_AFTER=$(tx_packets) +TX_AFTER=${TX_AFTER:-0} +TX_SENT=$((TX_AFTER - TX_BEFORE)) +STATE=$(can_state) + +if [ "$STATE" = "BUS-OFF" ] || [ "$TX_SENT" -eq 0 ]; then + echo "ERROR: $IFACE transmitted $TX_SENT frames and is in state ${STATE:-UNKNOWN}." >&2 + echo "Nothing reached the bus, so candump will show nothing." >&2 + echo "Check transceiver power and its standby pin, 120 ohm termination, CANH/CANL" >&2 + echo "orientation, and that the motors are powered and set to $BITRATE bit/s." >&2 + echo "Details: ip -details -statistics link show $IFACE" >&2 + exit 1 +fi + echo "Speed setup commands sent to CAN IDs 21-26 (hex 0x15-0x1A)." +echo "$TX_SENT frames confirmed transmitted on $IFACE (state: $STATE)." diff --git a/scripts/sync-to-orin.sh b/scripts/sync-to-orin.sh index 90d34fdb..ce87dbb6 100755 --- a/scripts/sync-to-orin.sh +++ b/scripts/sync-to-orin.sh @@ -1,25 +1,15 @@ #!/bin/bash -# Syncs the local urc-2023 repo to a remote orin over rsync. -# Usage: ./sync-to-orin.sh -# -# ip - IP address of the remote host (e.g. 192.168.0.148) -# remote_path - Absolute path on the remote (e.g. /home/trickfire/urc-2023) +# Syncs the local viator repo to a remote orin over rsync. -if [ -z "$1" ] || [ -z "$2" ]; then - echo "Usage: $0 " - echo " ip IP address of the orin" - echo " remote_path Path on the orin to the repo to sync" - exit 1 -fi +REMOTE_IP="192.168.0.112" -REMOTE_IP="$1" -REMOTE_PATH="$2" +REMOTE_PATH="${1:-/home/trickfire/viator}" LOCAL_PATH="$(cd "$(dirname "$0")/.." && git rev-parse --show-toplevel)/" echo "Syncing to trickfire@${REMOTE_IP}:${REMOTE_PATH} ..." -rsync -avz --progress \ +rsync -avz --delete --progress \ --exclude='.git/' \ --exclude='build/' \ --exclude='install/' \ diff --git a/src/arm/package.xml b/src/arm/package.xml index 97ba82af..52b6d663 100644 --- a/src/arm/package.xml +++ b/src/arm/package.xml @@ -3,17 +3,12 @@ arm 0.0.0 - TODO: Package description - trickfire - TODO: License declaration + Controls the rover arm's motors and operating mode + trickfire + Apache-2.0 custom_interfaces - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest - ament_python diff --git a/src/arm/setup.py b/src/arm/setup.py index e475a248..121f0912 100644 --- a/src/arm/setup.py +++ b/src/arm/setup.py @@ -13,10 +13,9 @@ install_requires=["setuptools"], zip_safe=True, maintainer="trickfire", - maintainer_email="vladimirkupryukhin@gmail.com", - description="TODO: Package description", - license="TODO: License declaration", - tests_require=["pytest"], + maintainer_email="tfrbtcs@uw.edu", + description="Controls the rover arm's motors and operating mode", + license="Apache-2.0", entry_points={ "console_scripts": ["arm = arm.arm:main"], }, diff --git a/src/arm/test/test_copyright.py b/src/arm/test/test_copyright.py deleted file mode 100644 index 60c2d1e6..00000000 --- a/src/arm/test/test_copyright.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -# Remove the `skip` decorator once the source file(s) have a copyright header -@pytest.mark.skip(reason="No copyright header has been placed in the generated source file.") -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors" diff --git a/src/camera/package.xml b/src/camera/package.xml index 2500f65e..8aa564e3 100644 --- a/src/camera/package.xml +++ b/src/camera/package.xml @@ -3,16 +3,15 @@ camera 0.0.0 - TODO: Package description - trickfire - TODO: License declaration + Captures and publishes compressed video from the rover's cameras + trickfire + Apache-2.0 - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest + rclpy + cv_bridge + sensor_msgs ament_python - \ No newline at end of file + diff --git a/src/camera/setup.py b/src/camera/setup.py index 805334a7..e34cdd21 100644 --- a/src/camera/setup.py +++ b/src/camera/setup.py @@ -13,10 +13,9 @@ install_requires=["setuptools"], zip_safe=True, maintainer="trickfire", - maintainer_email="kimdavid2222@gmail.com", - description="TODO: Package description", - license="TODO: License declaration", - tests_require=["pytest"], + maintainer_email="tfrbtcs@uw.edu", + description="Captures and publishes compressed video from the rover's cameras", + license="Apache-2.0", entry_points={ "console_scripts": ["roscamera = camera.roscamera:main"], }, diff --git a/src/camera/test/test_copyright.py b/src/camera/test/test_copyright.py deleted file mode 100644 index 60c2d1e6..00000000 --- a/src/camera/test/test_copyright.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -# Remove the `skip` decorator once the source file(s) have a copyright header -@pytest.mark.skip(reason="No copyright header has been placed in the generated source file.") -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors" diff --git a/src/can_moteus/package.xml b/src/can_moteus/package.xml index 025f5ab9..bf56641f 100644 --- a/src/can_moteus/package.xml +++ b/src/can_moteus/package.xml @@ -3,14 +3,10 @@ can_moteus 0.0.0 - TODO: Package description - trickfire - TODO: License declaration + Controls Moteus motor controllers over CAN + trickfire + Apache-2.0 - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest rclpy diff --git a/src/can_moteus/setup.py b/src/can_moteus/setup.py index 38aceb45..804991d9 100644 --- a/src/can_moteus/setup.py +++ b/src/can_moteus/setup.py @@ -17,10 +17,9 @@ install_requires=["setuptools"], zip_safe=True, maintainer="trickfire", - maintainer_email="trickfire@todo.todo", - description="TODO: Package description", - license="TODO: License declaration", - tests_require=["pytest"], + maintainer_email="tfrbtcs@uw.edu", + description="Controls Moteus motor controllers over CAN", + license="Apache-2.0", entry_points={ "console_scripts": ["can_moteus = can_moteus.ros_moteus_bridge:main"], }, diff --git a/src/can_moteus/test/test_copyright.py b/src/can_moteus/test/test_copyright.py deleted file mode 100644 index 60c2d1e6..00000000 --- a/src/can_moteus/test/test_copyright.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -# Remove the `skip` decorator once the source file(s) have a copyright header -@pytest.mark.skip(reason="No copyright header has been placed in the generated source file.") -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors" diff --git a/src/can_rmdx8/can_rmdx8/rmdx8_motor_manager.py b/src/can_rmdx8/can_rmdx8/rmdx8_motor_manager.py index 76d087f6..acf28fc6 100644 --- a/src/can_rmdx8/can_rmdx8/rmdx8_motor_manager.py +++ b/src/can_rmdx8/can_rmdx8/rmdx8_motor_manager.py @@ -29,7 +29,7 @@ def __init__(self) -> None: super().__init__("can_rmdx8_node") self.get_logger().info(colorStr("Launching can_rmdx8 node", ColorCodes.BLUE_OK)) self._id_to_rmdx8_motor: dict[int, RMDx8Motor] = {} - self.driver = rmd.CanDriver("can1") + self.driver = rmd.CanDriver("can0") self._driver_lock = Lock() self._req_buffer: deque[tuple[int, String]] = deque(maxlen=1000) self._buffer_lock = Lock() diff --git a/src/can_rmdx8/package.xml b/src/can_rmdx8/package.xml index 25165770..c5234849 100644 --- a/src/can_rmdx8/package.xml +++ b/src/can_rmdx8/package.xml @@ -3,14 +3,9 @@ can_rmdx8 0.0.0 - TODO: Package description - trickfire - TODO: License declaration - - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest + Controls RMDx8 motors over CAN + trickfire + Apache-2.0 ament_python diff --git a/src/can_rmdx8/setup.py b/src/can_rmdx8/setup.py index 7aa0601d..dffeb7aa 100644 --- a/src/can_rmdx8/setup.py +++ b/src/can_rmdx8/setup.py @@ -13,10 +13,9 @@ install_requires=["setuptools"], zip_safe=True, maintainer="trickfire", - maintainer_email="trickfire@todo.todo", - description="TODO: Package description", - license="TODO: License declaration", - tests_require=["pytest"], + maintainer_email="tfrbtcs@uw.edu", + description="Controls RMDx8 motors over CAN", + license="Apache-2.0", entry_points={ "console_scripts": ["can_rmdx8 = can_rmdx8.rmdx8_motor_manager:main"], }, diff --git a/src/can_rmdx8/test/test_copyright.py b/src/can_rmdx8/test/test_copyright.py deleted file mode 100644 index 60c2d1e6..00000000 --- a/src/can_rmdx8/test/test_copyright.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -# Remove the `skip` decorator once the source file(s) have a copyright header -@pytest.mark.skip(reason="No copyright header has been placed in the generated source file.") -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors" diff --git a/src/custom_interfaces/package.xml b/src/custom_interfaces/package.xml index 53deff37..6a828636 100644 --- a/src/custom_interfaces/package.xml +++ b/src/custom_interfaces/package.xml @@ -3,9 +3,9 @@ custom_interfaces 0.0.0 - TODO: Package description - trickfire - TODO: License declaration + Custom ROS message and service definitions for Viator + trickfire + Apache-2.0 ament_cmake diff --git a/src/drivebase/package.xml b/src/drivebase/package.xml index 474fac57..dd4b1322 100644 --- a/src/drivebase/package.xml +++ b/src/drivebase/package.xml @@ -4,13 +4,8 @@ drivebase 0.0.0 Connects the controller to the wheel motors - trickfire - TODO: License declaration - - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest + trickfire + Apache-2.0 ament_python diff --git a/src/drivebase/setup.py b/src/drivebase/setup.py index 36d76aa0..dc40b522 100644 --- a/src/drivebase/setup.py +++ b/src/drivebase/setup.py @@ -13,10 +13,9 @@ install_requires=["setuptools"], zip_safe=True, maintainer="trickfire", - maintainer_email="cklay@uw.edu", + maintainer_email="tfrbtcs@uw.edu", description="Connects the controller to the wheel motors", - license="TODO: License declaration", - tests_require=["pytest"], + license="Apache-2.0", entry_points={ "console_scripts": ["drivebase = drivebase.drivebase:main"], }, diff --git a/src/drivebase/test/test_copyright.py b/src/drivebase/test/test_copyright.py deleted file mode 100644 index 9167f3d7..00000000 --- a/src/drivebase/test/test_copyright.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors" diff --git a/src/heartbeat/heartbeat/heartbeat.py b/src/heartbeat/heartbeat/heartbeat.py index 76c6afdc..b394246f 100644 --- a/src/heartbeat/heartbeat/heartbeat.py +++ b/src/heartbeat/heartbeat/heartbeat.py @@ -41,8 +41,8 @@ def __init__(self) -> None: # give enough time (10s) for others to initialize time.sleep(10) - # flag to store connection status - self._connection_lost = False + # flag to store connection status; starts "lost" until the first heartbeat arrives + self._connection_lost = True # create subscription to mission control self._is_alive_subscriber = self.create_subscription( @@ -81,12 +81,17 @@ def heartbeat_callback(self, msg: Bool) -> None: # Update the timestamp of the last received heartbeat message self._last_heartbeat_time = time.time() - # Log connection active as before # doesn't matter the data, pub always pub True # just check to make sure nothing is wrong with pub if msg.data: - self.get_logger().info(colorStr("Connection active", ColorCodes.GREEN_OK)) - self._connection_lost = False + # Only log at INFO on the transition into a connected state (startup or + # reconnect); the recurring per-second tick goes to DEBUG so it doesn't + # flood the default INFO output. + if self._connection_lost: + self.get_logger().info(colorStr("Connection active", ColorCodes.GREEN_OK)) + self._connection_lost = False + else: + self.get_logger().debug(colorStr("Connection active", ColorCodes.GREEN_OK)) # Tell the client that the heartbeat was received. msg = Bool() diff --git a/src/heartbeat/package.xml b/src/heartbeat/package.xml index d2ba95be..8e95d55a 100644 --- a/src/heartbeat/package.xml +++ b/src/heartbeat/package.xml @@ -3,18 +3,13 @@ heartbeat 0.0.0 - Heartbeat Node Package - trickfire - TODO: License declaration + Monitors rover connectivity and stops the motors if it's lost + trickfire + Apache-2.0 rclpy std_msgs - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest - ament_python diff --git a/src/heartbeat/setup.py b/src/heartbeat/setup.py index f745ee2a..fc205620 100644 --- a/src/heartbeat/setup.py +++ b/src/heartbeat/setup.py @@ -13,10 +13,9 @@ install_requires=["setuptools"], zip_safe=True, maintainer="trickfire", - maintainer_email="vanillanguyen635@gmail.com", - description="TODO: Package description", - license="TODO: License declaration", - tests_require=["pytest"], + maintainer_email="tfrbtcs@uw.edu", + description="Monitors rover connectivity and stops the motors if it's lost", + license="Apache-2.0", entry_points={ "console_scripts": [ # ros 2 executable = packagename.filename : function we want to run diff --git a/src/heartbeat/test/test_copyright.py b/src/heartbeat/test/test_copyright.py deleted file mode 100644 index 60c2d1e6..00000000 --- a/src/heartbeat/test/test_copyright.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -# Remove the `skip` decorator once the source file(s) have a copyright header -@pytest.mark.skip(reason="No copyright header has been placed in the generated source file.") -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors" diff --git a/src/heartbeat/test/test_flake8.py b/src/heartbeat/test/test_flake8.py deleted file mode 100644 index 22fffcb8..00000000 --- a/src/heartbeat/test/test_flake8.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2017 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_flake8.main import main_with_errors - - -@pytest.mark.flake8 -@pytest.mark.linter -def test_flake8(): - rc, errors = main_with_errors(argv=[]) - assert rc == 0, "Found %d code style errors / warnings:\n" % len(errors) + "\n".join(errors) diff --git a/src/heartbeat/test/test_pep257.py b/src/heartbeat/test/test_pep257.py deleted file mode 100644 index 4eddb46e..00000000 --- a/src/heartbeat/test/test_pep257.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_pep257.main import main - - -@pytest.mark.linter -@pytest.mark.pep257 -def test_pep257(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found code style errors / warnings" diff --git a/src/mission_control_updater/package.xml b/src/mission_control_updater/package.xml index fb8ad91e..d45a70ab 100644 --- a/src/mission_control_updater/package.xml +++ b/src/mission_control_updater/package.xml @@ -3,14 +3,9 @@ mission_control_updater 0.0.0 - TODO: Package description - trickfire - TODO: License declaration - - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest + Sends rover telemetry to Mission Control + trickfire + Apache-2.0 ament_python diff --git a/src/mission_control_updater/setup.py b/src/mission_control_updater/setup.py index f6469a61..629cec5b 100644 --- a/src/mission_control_updater/setup.py +++ b/src/mission_control_updater/setup.py @@ -13,10 +13,9 @@ install_requires=["setuptools"], zip_safe=True, maintainer="trickfire", - maintainer_email="vladimirkupryukhin@gmail.com", - description="TODO: Package description", - license="TODO: License declaration", - tests_require=["pytest"], + maintainer_email="tfrbtcs@uw.edu", + description="Sends rover telemetry to Mission Control", + license="Apache-2.0", entry_points={ "console_scripts": ["mission_control_updater = mission_control_updater.updater:main"], }, diff --git a/src/mission_control_updater/test/test_copyright.py b/src/mission_control_updater/test/test_copyright.py deleted file mode 100644 index 60c2d1e6..00000000 --- a/src/mission_control_updater/test/test_copyright.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -# Remove the `skip` decorator once the source file(s) have a copyright header -@pytest.mark.skip(reason="No copyright header has been placed in the generated source file.") -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors" diff --git a/src/viator_launch/launch/robot.launch.py b/src/viator_launch/launch/robot.launch.py index 62e2d674..017b0ace 100644 --- a/src/viator_launch/launch/robot.launch.py +++ b/src/viator_launch/launch/robot.launch.py @@ -7,18 +7,13 @@ from launch_xml.launch_description_sources import XMLLaunchDescriptionSource can_moteus_node = Node(package="can_moteus", executable="can_moteus", name="can_moteus_node") - - drivebase_node = Node(package="drivebase", executable="drivebase", name="drivebase_node") -# Runs as root via sudo: opening the raw CAN socket for can1 needs CAP_NET_RAW/NET_ADMIN, -# which the non-root trickfire user doesn't have (see .devcontainer/trickfire-can-sudoers). -can_rmdx8_node = Node( - package="can_rmdx8", - executable="can_rmdx8", - name="can_rmdx8_node", - prefix="sudo -n --", -) +# must stay non-root like every other node here: FastDDS falls back to shared memory for +# same-host traffic and those /dev/shm segments are 0644, so a root node and a trickfire +# node discover each other but silently exchange no data. AF_CAN raw sockets don't need +# CAP_NET_RAW anyway (unlike AF_INET), only bringing the link up does +can_rmdx8_node = Node(package="can_rmdx8", executable="can_rmdx8", name="can_rmdx8_node") mission_control_updater_node = Node( package="mission_control_updater", @@ -54,7 +49,7 @@ def generate_launch_description() -> launch.LaunchDescription: # pylint: disable=invalid-name return launch.LaunchDescription( [ - can_moteus_node, + # can_moteus_node, (dsabeled for now cause arm is not implemented) drivebase_node, can_rmdx8_node, mission_control_updater_node, diff --git a/src/viator_launch/package.xml b/src/viator_launch/package.xml index 2a692421..30107fd0 100644 --- a/src/viator_launch/package.xml +++ b/src/viator_launch/package.xml @@ -3,9 +3,9 @@ viator_launch 0.0.0 - TODO: Package description - trickfire - TODO: License declaration + Launch files for starting the Viator rover + trickfire + Apache-2.0 can_moteus can_rmdx8 @@ -13,13 +13,6 @@ mission_control_updater arm camera - example_node - - - ament_copyright - ament_flake8 - ament_pep257 - python3-pytest ament_python diff --git a/src/viator_launch/setup.py b/src/viator_launch/setup.py index 070aeb3b..ee0f2bf4 100644 --- a/src/viator_launch/setup.py +++ b/src/viator_launch/setup.py @@ -18,8 +18,7 @@ # Zip-safety is not yet confirmed. zip_safe=True, maintainer="trickfire", - maintainer_email="phillipov@outlook.com", - description="TODO: Package description", - license="TODO: License declaration", - tests_require=["pytest"], + maintainer_email="tfrbtcs@uw.edu", + description="Launch files for starting the Viator rover", + license="Apache-2.0", ) diff --git a/src/viator_launch/test/test_copyright.py b/src/viator_launch/test/test_copyright.py deleted file mode 100644 index 9167f3d7..00000000 --- a/src/viator_launch/test/test_copyright.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright 2015 Open Source Robotics Foundation, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import pytest -from ament_copyright.main import main - - -@pytest.mark.copyright -@pytest.mark.linter -def test_copyright(): - rc = main(argv=[".", "test"]) - assert rc == 0, "Found errors"