Загрузка данных


**square_publisher.py**

```python
#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
import math


class SquarePublisher(Node):

    LINEAR_SPEED = 1.0
    ANGULAR_SPEED = math.pi / 2
    SIDE_DURATION = 2.0
    TURN_DURATION = 1.0

    def __init__(self):
        super().__init__('square_publisher')
        self.publisher_ = self.create_publisher(Twist, '/turtle1/cmd_vel', 10)
        self.timer_period = 0.1
        self.timer = self.create_timer(self.timer_period, self.timer_callback)
        self.state = 'forward'
        self.reset_state()
        self.declare_parameter('side_duration', 2.0)
        self.get_logger().info('SquarePublisher node started')

    def reset_state(self):
        self.state = 'forward'
        self.state_start_time = self.get_clock().now()
        self.get_logger().info('State reset: starting from forward movement')

    def timer_callback(self):
        try:
            if self.publisher_.get_subscription_count() == 0:
                self.get_logger().warn('No subscribers on /turtle1/cmd_vel, is turtlesim running?')
                return

            side_duration = self.get_parameter('side_duration').value
            msg = Twist()
            current_time = self.get_clock().now()
            state_elapsed_time = (current_time - self.state_start_time).nanoseconds / 1e9

            if self.state == 'forward':
                msg.linear.x = self.LINEAR_SPEED
                msg.angular.z = 0.0
                if state_elapsed_time >= side_duration:
                    self.state = 'turn'
                    self.state_start_time = self.get_clock().now()
                    self.get_logger().info('Turning 90 degrees...')

            elif self.state == 'turn':
                msg.linear.x = 0.0
                msg.angular.z = self.ANGULAR_SPEED
                if state_elapsed_time >= self.TURN_DURATION:
                    self.state = 'forward'
                    self.state_start_time = self.get_clock().now()
                    self.get_logger().info('Moving forward...')

            self.publisher_.publish(msg)

        except Exception as e:
            self.get_logger().error(f'Error in timer_callback: {str(e)}')


def main(args=None):
    rclpy.init(args=args)
    square_publisher = SquarePublisher()
    try:
        rclpy.spin(square_publisher)
    except KeyboardInterrupt:
        square_publisher.get_logger().info('Node stopped by user')
    except Exception as e:
        square_publisher.get_logger().error(f'Unexpected error: {str(e)}')
    finally:
        square_publisher.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()
```

**setup.py**

```python
from setuptools import setup

package_name = 'lab_turtlesim'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='student',
    maintainer_email='student@university.edu',
    description='Turtlesim lab package for ROS 2 learning',
    license='Apache License 2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'square_publisher = lab_turtlesim.square_publisher:main',
        ],
    },
)
```

**package.xml**

```xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypelayout="1.0"?>
<package format="3">
  <name>lab_turtlesim</name>
  <version>0.0.0</version>
  <description>Turtlesim lab package for ROS 2 learning</description>
  <maintainer email="student@university.edu">student</maintainer>
  <license>Apache License 2.0</license>

  <depend>rclpy</depend>
  <depend>geometry_msgs</depend>
  <depend>turtlesim</depend>

  <test_depend>ament_copyright</test_depend>
  <test_depend>ament_flake8</test_depend>
  <test_depend>ament_pep257</test_depend>
  <test_depend>python3-pytest</test_depend>

  <export>
    <build_type>ament_python</build_type>
  </export>
</package>
```