Skip to content

Commit eee7664

Browse files
committed
feat: add pixi workspace
1 parent f8a6bc7 commit eee7664

File tree

12 files changed

+44197
-0
lines changed

12 files changed

+44197
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SCM syntax highlighting & preventing 3-way merges
2+
pixi.lock merge=binary linguist-language=YAML linguist-generated=true

.gitignore

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# pixi environments
2+
.pixi/*
3+
!.pixi/config.toml
4+
5+
# build stuff
6+
**/build/
7+
**/install/
8+
**/log/
9+
**/COLCON_IGNORE
10+
**/AMENT_IGNORE
11+
12+
# python
13+
src/**/**.egg-info
14+
src/**/uv.lock
15+
**/__pycache__
16+
17+
# misc weird files from various oses/programs
18+
.ropeproject
19+
.DS_Store
20+
**/.pdb
21+
**/.vscode
22+
**/.ze

pixi.lock

Lines changed: 43943 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pixi.toml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
[workspace]
2+
authors = [
3+
"The Sooner Rover Team", # :D
4+
"Barrett Ray <[email protected]>",
5+
]
6+
channels = ["conda-forge", "robostack-humble"]
7+
name = "tutorial"
8+
platforms = ["linux-aarch64", "linux-64", "osx-arm64", "osx-64"]
9+
version = "0.1.0"
10+
11+
[dependencies]
12+
13+
# command-line tools (not for compilation)
14+
gh = { version = ">=2.78.0", channel = "conda-forge" } # GitHub CLI
15+
just = { version = ">=1.42.4,<2", channel = "conda-forge" } # `just` command runner
16+
lazygit = { version = ">=0.54.2,<0.55", channel = "conda-forge" } # `git` TUI tool
17+
18+
# build tools (e.g., c compiler, rust, glibc)
19+
c-compiler = { channel = "conda-forge" }
20+
clang = { channel = "conda-forge" }
21+
clangxx = { channel = "conda-forge" }
22+
cxx-compiler = { channel = "conda-forge" }
23+
glib = { version = ">=2.80.2,<3", channel = "conda-forge" }
24+
make = { version = "==4.4.1", channel = "conda-forge" }
25+
rust = { version = ">=1.89.0", channel = "conda-forge" }
26+
27+
# system python dependencies
28+
basedpyright = { version = ">=1.31.3", channel = "conda-forge" }
29+
numpy = ">=1.26,<2"
30+
python = "3.11.*"
31+
ruff = ">=0.12.11"
32+
uv = { version = "==0.8.11", channel = "conda-forge" }
33+
34+
# ros 2 tooling (e.g., colcon, ros2-cli)
35+
colcon-core = { channel = "conda-forge" }
36+
colcon-cmake = { channel = "conda-forge" }
37+
colcon-common-extensions = { channel = "conda-forge" }
38+
colcon-mixin = { channel = "conda-forge" }
39+
colcon-ros = { channel = "conda-forge" }
40+
colcon-test-result = { channel = "conda-forge" }
41+
ros-humble-cyclonedds = { channel = "robostack-humble" }
42+
ros-humble-ros2cli = { channel = "robostack-humble" }
43+
ros-humble-ros2cli-common-extensions = { channel = "robostack-humble" }
44+
ros2-distro-mutex = { version = ">=0.7", channel = "robostack-humble" } # IMPORTANT! change ver if needed
45+
46+
# install the ROS 2 desktop package.
47+
#
48+
# WARNING: this is a HUGE download. it has virtually everything that a new
49+
# ROS 2 user would want to learn how to use it.
50+
#
51+
# but yeah, again, HUGE download.
52+
ros-humble-desktop = { version = "==0.10.0", channel = "robostack-humble" }
53+
54+
# required for `python-refactoring` tool
55+
[pypi-dependencies]
56+
cst_lsp = ">=0.1.3"

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[tool.basedpyright]
2+
exclude = ["install"]
3+
allowedUntypedLibraries = ["sensor_msgs.msg", "rclpy"]
4+
reportUnknownVariableType = "none"
5+
reportUnknownMemberType = "none"

src/.gitkeep

Whitespace-only changes.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# this file is REQUIRED to create a "script" (`ros2 run`-able node)
2+
#
3+
# technically, it creates a python package/mod, which is different from a ROS 2
4+
# package (lol). but all you need to know is that, when you have a folder
5+
# with python files in it, make sure to add an `__init__.py` file!
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
"""
2+
An example ROS 2 node written in Python.
3+
4+
See the real node here:
5+
https://github.com/Sooner-Rover-Team/auto_ros2/tree/main/src/navigator/navigator_node
6+
"""
7+
8+
from dataclasses import dataclass
9+
import time
10+
import rclpy
11+
from rclpy.node import Node
12+
from rclpy.qos import QoSPresetProfiles
13+
from rclpy.subscription import Subscription
14+
from sensor_msgs.msg import NavSatFix
15+
from typing_extensions import override
16+
17+
18+
@dataclass(kw_only=True)
19+
class NavigatorNode(Node):
20+
"""
21+
An example ROS 2 node.
22+
23+
Notice how there's the `@dataclass` annotation thingy up there? That lets
24+
us say _what_ data will be stored in the class. It cleans things up a lot!
25+
26+
After this comment ends, you'll see the class "data fields"...
27+
"""
28+
29+
_gps_subscription: Subscription
30+
"""
31+
Here's our first field!
32+
33+
This `_gps_subscription` variable is accessible throughout the class, in
34+
all of its methods.
35+
"""
36+
37+
def __init__(self):
38+
"""
39+
"Initializes" the node.
40+
41+
This function makes the node known to ROS 2 when it's created in
42+
Python code. It also sets up a bunch of variables, like our
43+
`_gps_subscription` field.
44+
"""
45+
46+
# first, we have to initialize the `Node` class that this one extends.
47+
#
48+
# inside that `__init__` function, we're giving our node a name. ROS 2
49+
# will refer to it as `navigator_node` from now on, unless you rename
50+
# it in a launch file.
51+
#
52+
# IMPORTANT: you are REQUIRED to call this function to correctly create
53+
# a ROS 2 node.
54+
super().__init__("navigator_node")
55+
56+
# next, we can initialize the `_gps_subscription` variable.
57+
#
58+
# you can see that we have another method at the bottom of this class
59+
# called `_gps_callback`. that's a function we want to run if another
60+
# node sends us a `NavSatFix` (GPS message).
61+
#
62+
# so, let's set that up accordingly:
63+
self._gps_subscription = self.create_subscription(
64+
msg_type=NavSatFix,
65+
topic="/sensors/gps",
66+
callback=self._gps_callback,
67+
qos_profile=QoSPresetProfiles.SENSOR_DATA.value,
68+
)
69+
70+
# great! we've now set up a ROS 2 node correctly!
71+
#
72+
# the function now returns...
73+
74+
# required boilerplate -- please ignore!
75+
@override
76+
def __hash__(self) -> int:
77+
return super().__hash__()
78+
79+
def _gps_callback(self, msg: NavSatFix):
80+
"""This function runs when we receive a GPS message!"""
81+
82+
# extract data from message
83+
lat: float = msg.latitude
84+
lon: float = msg.longitude
85+
alt: float = msg.altitude
86+
87+
# print out the data
88+
print(f"Got a GPS message! lat: {lat}, lon: {lon}, alt: {alt}")
89+
90+
91+
def main(args: list[str] | None = None):
92+
"""
93+
Starts the Navigator node.
94+
"""
95+
rclpy.init(args=args)
96+
navigator_node: NavigatorNode = NavigatorNode()
97+
98+
# tell the user that the node's running, and let them know how to stop it!
99+
#
100+
# note that the weird \033 escapes down there show color in the terminal,
101+
# which makes it a little easier to read, in my view. ~bray
102+
print(
103+
"The Navigator node is now running! You can press Ctrl + C at any time to stop it."
104+
)
105+
print()
106+
print("Please paste the following code into another ROS 2 terminal:")
107+
print(
108+
'\033[0;34mros2 \033[0;35mtopic pub \033[0;32m/sensors/gps sensor_msgs/NavSatFix \033[0;31m"{ latitude: 1.0, longitude: 2.0, altitude: 3.0 }"\033[0m'
109+
)
110+
print()
111+
112+
# spin the node until ROS 2 stops it (or you spam Ctrl^C)
113+
while rclpy.ok():
114+
rclpy.spin_once(navigator_node, timeout_sec=0)
115+
time.sleep(1e-4)
116+
117+
# destroy the Node explicitly
118+
#
119+
# this is optional - otherwise, the garbage collector does it automatically
120+
# when it runs.
121+
navigator_node.destroy_node()
122+
rclpy.shutdown()

src/navigator/package.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" ?>
2+
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
3+
<package format="3">
4+
<name>navigator</name>
5+
<version>1.0.0</version>
6+
<description>Sample package.</description>
7+
8+
<maintainer email="[email protected]">Barrett Ray</maintainer>
9+
10+
<license>BSD0</license>
11+
12+
<export>
13+
<build_type>ament_python</build_type>
14+
</export>
15+
</package>

src/navigator/resource/navigator

Whitespace-only changes.

0 commit comments

Comments
 (0)