ZENORAK_ROS2_CONTROL PACKAGE:
zenorak_ros2_control/ ├── config/ │ ├── controller.yaml # Controller configuration ├── description/ │ └── zenorak.xacro # Robot URDF description ├── launch/ │ ├── launch_robot.launch.py # Main robot launch file │ └── rsp.launch.py # Robot state publisher launch ├── meshes/ │ ├── collision/ # Collision meshes │ └── visual/ # Visual meshes └── rviz/ └── default.rviz # RViz visualization config
- Base Link: Main chassis with mass of __ kg
- Four Wheels: Each wheel with individual inertial properties
- Front Left Wheel
- Front Right Wheel
- Rear Left Wheel
- Rear Right Wheel
- Joint Configuration: Continuous joints for wheel rotation
- Hardware Interface: Configured for Arduino-based differential drive control
2. Robot State Publisher (rsp.launch.py) - Processes the Xacro file and publishes robot state information:
- Converts Xacro to URDF format
- Publishes TF (transform) tree for all robot links
- Provides
/robot_descriptiontopic for visualization - Essential for RViz and navigation stack integration
Key Functions:
- Reads
zenorak.xacrofrom the description folder - Processes macros into complete URDF
- Launches
robot_state_publishernode with robot description
3. Main Launch File (launch_robot.launch.py) - Orchestrates the complete robot system startup with coordinated timing:
Launch Sequence:
-
Robot State Publisher (Immediate) - Publishes robot URDF and transforms
-
Controller Manager (3-second delay)
- Manages hardware interface to Arduino
- Loads controller configurations
- Provides real-time control loop
-
Differential Drive Controller (After Controller Manager)
- Accepts
/cmd_velcommands - Controls front left and right wheels
- Publishes odometry data
- Accepts
-
Joint State Broadcaster (After Controller Manager)
- Publishes joint positions and velocities
- Enables state monitoring and visualization
Pre-configured visualization setup:
- Robot model display with collision/visual meshes
- Grid reference frame
- TF tree visualization
- Interactive tools for pose setting and measurements
- Fixed frame:
base_link - Orbit camera view for optimal robot observation
ros2 launch zenorak_ros2_control launch_robot.launch.py
This command will:
- Start robot state publisher
- Initialize hardware interface (after 3-second delay)
- Spawn differential drive controller
- Spawn joint state broadcaster
ros2 topic pub /diff_cont/cmd_vel_unstamped geometry_msgs/msg/Twist "{linear: {x: 0.5}, angular: {z: 0.0}}"
ros2 topic pub /diff_cont/cmd_vel_unstamped geometry_msgs/msg/Twist "{linear: {x: 0.0}, angular: {z: 0.5}}"
ros2 run rviz2 rviz2 -d $(ros2 pkg prefix zenorak_ros2_control)/share/zenorak_ros2_control/rviz/default.rviz
ros2 topic echo /joint_states
ros2 topic echo /diff_cont/odom
ros2 control list_controllers
- ROS 2 (Humble or later recommended)
ros2_controlandros2_controllersrobot_state_publisherxacrorviz2diffdrive_arduinohardware plugincontroller_manager
ZENORAK_TELEOP PACKAGE:
- Keyboard Control: Use W, A, S, D keys for intuitive robot movement
- Incremental Commands: Sends progressive command values (0-120) at 1Hz
- Non-blocking Input: Reads keyboard in a separate thread without blocking ROS operations
- Clean Termination: Graceful shutdown with proper terminal restoration
zenorak_teleop/ ├── scripts/ │ └── zenorak_teleop.py # Main teleoperation node ├── launch/ │ └── teleop.launch.py # Launch file ├── CMakeLists.txt # Build configuration └── package.xml # Package metadata
| Key | Command Prefix | Direction | Example Messages |
|---|---|---|---|
| W | f |
Forward | f0, f1, ... f120 |
| A | l |
Left | l0, l1, ... l120 |
| S | b |
Backward | b0, b1, ... b120 |
| D | r |
Right | r0, r1, ... r120 |
| Enter | s |
Stop | s0 |
- Key Press Detection: Continuously reads keyboard input in raw mode (no Enter needed)
- Counter Increment: When a key (W/A/S/D) is held, counter increments from 0 to 120
- Message Publishing: Publishes command at 1Hz (every second) while key is active
- Stop Command: Pressing Enter sends
s0and resets the system
sudo apt install ros--rclpy ros--std-msgs
cd ~/ros2_ws colcon build --packages-select zenorak_teleop source install/setup.bash
ros2 run zenorak_teleop zenorak_teleop.py
ros2 launch zenorak_teleop teleop.launch.py
_read_keys()
- Runs in separate thread
- Reads single characters from stdin
- Updates
active_keywhen W/A/S/D pressed - Sends stop command on Enter
_tick()
- Called every 1 second by ROS timer
- Publishes command if key is active
- Increments counter (0 → 120)
- Stops incrementing at 120
destroy_node()
- Stops keyboard thread
- Restores terminal settings
- Cleans up resources
ZENORAK_SERIAL PACKAGE:
zenorak_serial/ ├── scripts/ │ └── zenorak_serial.py # Serial bridge node ├── CMakeLists.txt # Build configuration └── package.xml # Package metadata
- Subscribe: Listens to
/zenorak_teleop_cmdtopic - Extract: Gets command string from ROS message (e.g., "f25")
- Format: Adds newline character for Arduino's
readStringUntil('\n') - Transmit: Sends via serial to
/dev/ttyACM0at 115200 baud - Log: Records successful transmission for debugging
Examples:
f25\n→ Forward command, intensity 25l10\n→ Left turn, intensity 10s0\n→ Stop command
sudo apt install ros--rclpy ros--std-msgs
sudo apt install python3-serial
pip3 install pyserial
ros2 run zenorak_serial zenorak_serial.py
Terminal 1: Start the bridge
ros2 run zenorak_serial zenorak_serial.pyTerminal 2: Send test command
ros2 topic pub /zenorak_teleop_cmd std_msgs/msg/String "{data: 'f50'}"# Connect Arduino via USB
# Upload control firmware to Arduino
# Verify connection: ls /dev/ttyACM0# Terminal 1: Launch robot control
ros2 launch zenorak_ros2_control launch_robot.launch.py# Terminal 2: Start Arduino bridge
ros2 run zenorak_serial zenorak_serial.py# Terminal 3: Start keyboard control
ros2 run zenorak_teleop zenorak_teleop.py- Use W/A/S/D keys to drive
- Press Enter to stop
- Watch RViz for visualization