brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
ros2-roboticsBest practices for ROS 2 robotics development, covering package structure, nodes, topics/services/actions, launch files, QoS, tf2 transforms, and testing. Use when creating ROS 2 packages, writing nodes in rclpy or rclcpp, defining custom messages/services/actions, writing launch files, configuring QoS profiles, working with tf2 transforms, or building and …
Independent GitHub snapshot · Automated classification · Original documentation governs
This skill covers building ROS 2 packages and nodes, including package structure, communication patterns (topics, services, actions), timing and frames, build/test workflows with colcon, and common pitfalls in robotics software.
ros2 pkg create --build-type ament_python <name> (Python) or --build-type ament_cmake <name> (C++) inside a colcon workspace's src/ directory..msg, .srv, or .action files under msg/, srv/, action/ only when a standard interface (std_msgs, geometry_msgs, sensor_msgs, nav_msgs) doesn't fit.launch/*.launch.py file using launch_ros.actions.Node.colcon build --symlink-install from the workspace root, then source install/setup.bash.pytest for Python, gtest/launch_testing for C++/integration) and run colcon test.ros2 run, ros2 launch, ros2 topic echo, ros2 node info, and ros2 doctor to verify runtime behavior.lidar_driver, path_planner, arm_controller) rather than a monolithic package.package.xml consistently with the build type declared in it, and either CMakeLists.txt (ament_cmake, C++) or setup.py/setup.cfg (ament_python).launch/ for launch scripts, config/ for YAML parameter files, msg/ for message definitions, srv/ for services, action/ for actions, and urdf//xacro/ for robot descriptions.package.xml (<depend>, <exec_depend>, <build_depend>) so the workspace builds reproducibly.self.declare_parameter('rate_hz', 10.0) and read them with self.get_parameter('rate_hz').value; never rely on undeclared parameters.geometry_msgs/Twist, sensor_msgs/LaserScan, nav_msgs/Odometry) before creating custom interfaces — custom types fragment the ecosystem and lose compatibility with existing tools.import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy
from geometry_msgs.msg import Twist
class SafeVelocityPublisher(Node):
"""Publishes bounded velocity commands at a fixed rate."""
def __init__(self) -> None:
super().__init__("safe_velocity_publisher")
self.declare_parameter("rate_hz", 10.0)
self.declare_parameter("max_linear_speed", 0.5)
rate_hz = self.get_parameter("rate_hz").value
self._max_linear = self.get_parameter("max_linear_speed").value
# Reliable QoS for a low-rate command topic; sensor streams would
# typically use BEST_EFFORT with a shallow history instead.
qos = QoSProfile(
reliability=ReliabilityPolicy.RELIABLE,
history=HistoryPolicy.KEEP_LAST,
depth=10,
)
self._publisher = self.create_publisher(Twist, "cmd_vel", qos)
self._timer = self.create_timer(1.0 / rate_hz, self._on_timer)
self._target_linear = 0.0
def _on_timer(self) -> None:
msg = Twist()
msg.linear.x = max(-self._max_linear, min(self._max_linear, self._target_linear))
self._publisher.publish(msg)
def main(args: list | None = None) -> None:
rclpy.init(args=args)
node = SafeVelocityPublisher()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == "__main__":
main()
self.get_clock().now(), and use_sim_time when a simulation clock is in play) instead of wall-clock time whenever simulation or bag replay matters.tf2 (tf2_ros.Buffer + TransformListener) for all frame transforms; never hand-roll coordinate transforms between named frames.base_link, odom, map, sensor frames) and their conventions (REP-103 for axis orientation, REP-105 for the map→odom→base_link tree).MultiThreadedExecutor, worker threads, or actions so the node keeps servicing other callbacks.BEST_EFFORT/volatile for high-rate sensor data where dropped samples are acceptable, RELIABLE/TRANSIENT_LOCAL for latched-like configuration topics, and RELIABLE/volatile for command paths.colcon build (typically --symlink-install during development) and keep inter-package dependencies explicit in package.xml.ament_flake8, ament_pep257 for Python; ament_cpplint, ament_uncrustify for C++ — via colcon test.launch_testing-based integration tests for multi-node behavior (e.g., "does node A receive what node B publishes within N seconds").tf2.LookupException), stale sensor data, and services or actions that are unavailable when called.ament_index_python.packages.get_package_share_directory.BEST_EFFORT publisher with a RELIABLE subscriber) — the connection silently never delivers data.use_sim_time:=true when running against a simulator, causing timestamps and tf2 lookups to disagree with the simulated clock.