diff --git a/README.md b/README.md index 1853418..932de56 100644 --- a/README.md +++ b/README.md @@ -2,27 +2,59 @@ A ROS2 TurtleSim Python Controller similar to turtle_teleop_key, but using python turtle command scripts for controlling instead of key strokes. +Running this example wiill result in the following output: +![turtle_sim_pythonop_demo](./doc/turtlesim_pythonop_demo.png) + Read the [ROS2 turtlesim Tutorial](https://docs.ros.org/en/jazzy/Tutorials/Beginner-CLI-Tools/Introducing-Turtlesim/Introducing-Turtlesim.html) if you are unfamiliar with this evironment. -# Installation and Running as ROS package +The following Python turtle commands are supported. See the +[Python Turtle](https://docs.python.org/3/library/turtle.html) page for command +details. + +* Movement + + forward(), backward(), right(), left(), goto(), setpos(), teleport(), setx(), + sety(), setheading(), home(), circle() + +* State + + position(), towards(), xcor(), ycor(), heading(), distance(), clear() + +* Pen Control + + pendown(), penup() -1. Clone this repository into a ros2 workspace src folder + +## Installation and Running as ROS2 package + +1. Clone this repository into a ROS2 workspace src folder 2. Build workspace with `colcon build` followed by `source install/local_setup.bash` 3. In another terminal launch the turtlesim package as described in the ROS2 Tutorial - sudo apt install ros-jazzy-turtlesim + sudo apt install ros-$ROS_DISTRO-turtlesim ros2 run turtlesim turtlesim_node 3. Run this package from the workspace with run turtlesim_teleop_python pythonop_turtle -# Interactive Test +## Parameter + +The package provides the following custom parameters: + +| Parameter | Type |Description | Default | +|---------------|-------|--------------------------------------------------| --------| +| delay | float | Delay between sending update messages in seconds.| 1.0 | +| scale_angular | float | Scale factor for angular movements. | 1.0 | +| scale_linear | float | Scale factor for linear movements. | 1.0 | + + +## Interactive Usage Interactive testing is working by going into `turtlesim_teleop_python/turtlesim_teleop_python` folder -and start python3. Then execute the commands below as an example: +and start python3 from there. Then execute the commands below as an example: ```python import rclpy diff --git a/doc/turtlesim_pythonop_demo.png b/doc/turtlesim_pythonop_demo.png new file mode 100755 index 0000000..70cce65 Binary files /dev/null and b/doc/turtlesim_pythonop_demo.png differ diff --git a/turtlesim_teleop_python/pythonop_turtle.py b/turtlesim_teleop_python/pythonop_turtle.py index 393c64f..1ca39d5 100644 --- a/turtlesim_teleop_python/pythonop_turtle.py +++ b/turtlesim_teleop_python/pythonop_turtle.py @@ -82,6 +82,8 @@ def clear(self) -> None: """Send clear request.""" request = Empty.Request() self._clear_srv.call_async(request) + self._delay() + def penup(self) -> None: """Lift the pen up.""" @@ -92,6 +94,8 @@ def penup(self) -> None: request.width = 3 request.off = 1 self._setPen_srv.call_async(request) + self._delay() + pu = penup up = penup @@ -105,6 +109,7 @@ def pendown(self) -> None: request.width = 3 request.off = 0 self._setPen_srv.call_async(request) + self._delay() def delay(self, dl=None) -> float: """Set or get update turtle update delay in seconds.""" @@ -137,7 +142,8 @@ def goto(self, x, y) -> None: request.y = float(self.ycor()) * self._scale_linear request.theta = math.radians(self.heading() * self._scale_angular) self._teleport_abs_srv.call_async(request) - rclpy.spin_once(self, timeout_sec=0.0) + self._delay() + def _rotate(self, angle): super()._rotate(angle) @@ -159,12 +165,14 @@ def _update_geometry(self, distance: float = 0.0, angle: float = 0.0) -> None: msg.linear.x = float(distance) * self._scale_linear self._publisher.publish(msg) - # tiwst message delay + self._delay() + + def _delay(self, n=None): + """Message delay wait.""" wait_for_time = time.time() + self._twist_delay while time.time() < wait_for_time: rclpy.spin_once(self, timeout_sec=0.0) - def main(args=None): """Application runnable enty point.""" rclpy.init(args=args) @@ -176,26 +184,36 @@ def main(args=None): def demo(turtle: TurtleTwistPublisher) -> None: """Do some turtle fun.""" - turtle.penup() turtle.clear() + turtle.penup() turtle.home() + turtle.left(90.0) + turtle.forward(1.0) turtle.pendown() - turtle.left(90) - turtle.forward(5) - turtle.right(160) - turtle.forward(5.5) - turtle.left(160) - turtle.forward(5) - turtle.right(90) - turtle.forward(3) - turtle.backward(1.5) - turtle.right(90) - turtle.forward(5) + turtle.circle(radius=1.0, extent=180.1) + turtle.right(180.0) + turtle.circle(radius=1.0, extent=180.1) + x = turtle.xcor() + y = turtle.ycor() + for i in range(0,181, 30): + print(i) + print(math.cos(math.radians(float(i)))) + turtle.goto( + x + 1.0 - math.cos(math.radians(float(i))), + y - i /90) + + x = turtle.xcor() + y = turtle.ycor() + for i in range(0,181, 30): + print(i) + print(math.cos(math.radians(float(i)))) + turtle.goto( + x + 1.0 + math.cos(math.radians(180.0 + float(i))), + y + i /90) + turtle.penup() - turtle.goto(2, 2) - turtle.pendown() - turtle.circle(1.5) + turtle.home() -if __name__ == "__main__": +if __name__ == "__main__": main()