peifeng-unity
3 年前
当前提交
1347d063
共有 72 个文件被更改,包括 2120 次插入 和 473 次删除
-
3tutorials/pick_and_place/PickAndPlaceProject/Assets/DemoScripts/Demo.cs
-
6tutorials/pick_and_place/Scripts/SourceDestinationPublisher.cs
-
16tutorials/pick_and_place/Scripts/TrajectoryPlanner.cs
-
4tutorials/pick_and_place/docker/set-up-workspace
-
17tutorials/ros_unity_integration/README.md
-
13tutorials/ros_unity_integration/network.md
-
85tutorials/ros_unity_integration/publisher.md
-
152tutorials/ros_unity_integration/setup.md
-
41tutorials/ros_unity_integration/subscriber.md
-
5tutorials/ros_unity_integration/unity_scripts/RosPublisherExample.cs
-
2tutorials/ros_unity_integration/unity_scripts/RosSubscriberExample.cs
-
8tutorials/ros_unity_integration/unity_scripts/RosUnityServiceExample.cs
-
11tutorials/ros_unity_integration/unity_scripts/RosServiceCallExample.cs
-
83tutorials/ros_unity_integration/unity_service.md
-
2tutorials/ros_unity_integration/ros_packages/unity_robotics_demo/scripts/position_service.py
-
158tutorials/ros_unity_integration/images/create_cube.png
-
40tutorials/ros_unity_integration/images/docker_cli.png
-
399tutorials/ros_unity_integration/images/generate_messages_3.png
-
36tutorials/ros_unity_integration/images/move_tool.png
-
121tutorials/ros_unity_integration/images/ros1_icon.png
-
129tutorials/ros_unity_integration/images/ros2_icon.png
-
126tutorials/ros_unity_integration/images/ros2_protocol.png
-
86tutorials/ros_unity_integration/images/settings_ros_ip.png
-
151tutorials/ros_unity_integration/images/unity-tab-square-white.png
-
103tutorials/ros_unity_integration/service_call.md
-
22tutorials/ros_unity_integration/ros2_docker/Dockerfile
-
5tutorials/ros_unity_integration/ros2_docker/source_ros.sh
-
25tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/package.xml
-
0tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/resource/unity_robotics_demo
-
4tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/setup.cfg
-
29tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/setup.py
-
23tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/test/test_copyright.py
-
25tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/test/test_flake8.py
-
23tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/test/test_pep257.py
-
0tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/unity_robotics_demo/__init__.py
-
50tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/unity_robotics_demo/color_publisher.py
-
34tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo/unity_robotics_demo/position_service.py
-
34tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo_msgs/CMakeLists.txt
-
25tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo_msgs/package.xml
-
24tutorials/ros_unity_integration/ros_docker/Dockerfile
-
6tutorials/ros_unity_integration/ros_docker/set-up-workspace
-
34tutorials/ros_unity_integration/ros_packages/unity_robotics_demo/CMakeLists.txt
-
34tutorials/ros_unity_integration/ros_packages/unity_robotics_demo/package.xml
-
48tutorials/ros_unity_integration/ros_packages/unity_robotics_demo/scripts/color_publisher.py
-
40tutorials/ros_unity_integration/ros_packages/unity_robotics_demo_msgs/CMakeLists.txt
-
7tutorials/ros_unity_integration/ros_packages/unity_robotics_demo_msgs/msg/PosRot.msg
-
4tutorials/ros_unity_integration/ros_packages/unity_robotics_demo_msgs/msg/UnityColor.msg
-
28tutorials/ros_unity_integration/ros_packages/unity_robotics_demo_msgs/package.xml
-
3tutorials/ros_unity_integration/ros_packages/unity_robotics_demo_msgs/srv/ObjectPoseService.srv
-
3tutorials/ros_unity_integration/ros_packages/unity_robotics_demo_msgs/srv/PositionService.srv
-
154tutorials/ros_unity_integration/server_endpoint.md
-
112tutorials/ros_unity_integration/service.md
-
0/tutorials/ros_unity_integration/unity_scripts/RosServiceCallExample.cs
-
0/tutorials/ros_unity_integration/ros_packages/unity_robotics_demo/launch
-
0/tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo_msgs/msg
-
0/tutorials/ros_unity_integration/ros_packages/unity_robotics_demo/scripts/position_service.py
-
0/tutorials/ros_unity_integration/ros2_packages/unity_robotics_demo_msgs/srv
|
|||
#!/bin/bash |
|||
|
|||
source /opt/ros/melodic/setup.bash |
|||
echo "ROS_IP: $(hostname -i)" > $ROS_WORKSPACE/src/niryo_moveit/config/params.yaml |
|||
echo "ROS_IP: $(hostname -i)" > $ROS_WORKSPACE/src/ros-tcp-endpoint/config/params.yaml |
|||
catkin_make |
|||
catkin_make |
|
|||
# ROS–Unity Initial Setup |
|||
# ROS–Unity Demo Setup |
|||
The minimum requirements for a ROS–Unity integration. |
|||
This document is in two parts - part 1 covers the minimum requirements for a ROS–Unity integration. Part 2 sets up the Unity Robotics Demo package, which you will need if you're following the ROS–Unity Integration tutorials. |
|||
## ROS Environment |
|||
These instructions cover both ROS1 and ROS2. The symbols <img src="images/ros1_icon.png" alt="ros1" width="14" height="14"/> and <img src="images/ros2_icon.png" alt="ros2" width="23" height="14"/> indicate instructions for ROS1 and ROS2 users, respectively. If using ROS2, start with [ROS2 Environment](setup.md#-ros2-environment). |
|||
1. Download and copy the [TCP Endpoint](https://github.com/Unity-Technologies/ROS-TCP-Endpoint) package to the `src` folder in your Catkin workspace. |
|||
## <img src="images/ros1_icon.png" alt="ros1" width="28" height="28"/> ROS Environment |
|||
1. Navigate to your Catkin workspace and run `catkin_make && source devel/setup.bash`. Ensure there are no errors. |
|||
Follow these steps to use ROS (melodic or noetic): |
|||
1. Open a new terminal, navigate to your Catkin workspace, and run: |
|||
1. |
|||
a) If you don't already have a ROS environment set up, we recommend using Docker. Navigate to `tutorials/ros_unity_integration` in your copy of this repo and run the following commands: |
|||
source devel/setup.bash |
|||
roscore & |
|||
docker build -t melodic -f ros_docker/Dockerfile . |
|||
docker run -it --rm -p 10000:10000 melodic /bin/bash |
|||
Once ROS Core has started, it will print `started core service [/rosout]` to the terminal window. |
|||
This should build a docker image and start it. |
|||
1. Note that in the `server_endpoint`, the script fetches parameters for the TCP connection. You will need to know the IP address of your ROS machine as well as the IP address of the machine running Unity. |
|||
- The ROS machine IP, i.e. `ROS_IP` should be the same value as the one set as `Host Name` on the RosConnect component in Unity. |
|||
1. The ROS parameter values can be set using a YAML file. Create a `params.yaml` file in your package, e.g. `./config/params.yaml`. Open the file for editing. |
|||
b) (Alternative) If you're using your own ROS environment, download and copy the [ROS-TCP-Endpoint](https://github.com/Unity-Technologies/ROS-TCP-Endpoint) package into the `src` folder in your Catkin workspace. Then navigate to your Catkin workspace and run `catkin_make`, then `source devel/setup.bash`. Ensure there are no errors. |
|||
1. Update the `ROS_IP` below with the appropriate address and copy the contents into the `params.yaml` file. |
|||
2. Open a new terminal, navigate to your Catkin workspace, and run: |
|||
```yaml |
|||
ROS_IP: <your ROS IP> |
|||
ROS_TCP_PORT: 10000 |
|||
``` |
|||
```bash |
|||
source devel/setup.bash |
|||
roscore |
|||
``` |
|||
e.g. |
|||
Once ROS Core has started, it will print `started core service [/rosout]` to the terminal window. |
|||
```yaml |
|||
ROS_IP: 127.0.0.1 |
|||
ROS_TCP_PORT: 10000 |
|||
3. In your previous terminal, run the following command, replacing the `<your IP address>` with your ROS machine's IP or hostname. |
|||
|
|||
```bash |
|||
rosparam set ROS_IP <your IP address> |
|||
Ensure that the `ROS_TCP_PORT` is set to 10000. |
|||
- If you're running ROS in a Docker container, you can just use `rosparam set ROS_IP 0.0.0.0` |
|||
- On Linux you can find out your IP address with the command `hostname -I` |
|||
- On MacOS you can find out your IP address with `ipconfig getifaddr en0` |
|||
1. Set these newly defined parameters by running `rosparam load`, e.g.: |
|||
6. (Optional) By default, the server_endpoint will listen on port 10000, but this is also controlled by a parameter. If you need to change it, you can run the command `rosparam set ROS_TCP_PORT 10000`, replacing 10000 with the desired port number. |
|||
```bash |
|||
rosparam load PATH/TO/config/params.yaml |
|||
``` |
|||
Alternatively, this YAML can be loaded from a launch file, e.g.: |
|||
7. Start the server endpoint with the following command: |
|||
```xml |
|||
<launch> |
|||
<rosparam file="$(find <PACKAGE_NAME>)/config/params.yaml" command="load"/> |
|||
</launch> |
|||
``` |
|||
```bash |
|||
rosrun ros_tcp_endpoint default_server_endpoint.py |
|||
``` |
|||
|
|||
Once the server_endpoint has started, it will print something similar to `[INFO] [1603488341.950794]: Starting server on 192.168.50.149:10000`. |
|||
|
|||
> Note, for this tutorial we have illustrated how to do everything manually, but for day-to-day use, we recommend starting the endpoint with a launch file. Replace all the above (including the roscore step) with the following command: `roslaunch ros_tcp_endpoint endpoint.launch`. |
|||
> While using this launch file, your ROS_IP and ROS_TCP_PORT parameters are read from the file src/ros_tcp_endpoint/config/params.yaml. You can edit this file to adjust your settings - for example, this command will set the appropriate IP address for your machine: |
|||
> `echo "ROS_IP: $(hostname -i)" > src/ros-tcp-endpoint/config/params.yaml` |
|||
## Unity Scene |
|||
1. Launch Unity and create a new scene. |
|||
2. Open Package Manager and click the + button at the top left corner. Select "add package from git URL" and enter "https://github.com/Unity-Technologies/ROS-TCP-Connector.git?path=/com.unity.robotics.ros-tcp-connector" to install the [ROS TCP Connector](https://github.com/Unity-Technologies/ROS-TCP-Connector) package. |
|||
## <img src="images/ros2_icon.png" alt="ros2" width="46" height="28"/> ROS2 Environment |
|||
![](images/add_package.png) |
|||
Follow these steps if using ROS2: |
|||
![](images/add_package_2.png) |
|||
1. |
|||
a) If you don't already have a ROS2 environment set up, we recommend using Docker. Navigate to `tutorials/ros_unity_integration` in your copy of this repo and run the following commands: |
|||
Messages being passed between Unity and ROS need to be serialized exactly as ROS serializes them internally. This is achieved with the RosMessageGeneration utility, which generates C# classes, including serialization and deserialization functions, based on ROS message files. Adding the ROS TCP Connector package should have created a new Unity menu option, “Robotics/Generate ROS Messages”, which we will use to generate these messages later. |
|||
```bash |
|||
docker build -t foxy -f ros2_docker/Dockerfile . |
|||
docker run -it --rm -p 10000:10000 foxy /bin/bash |
|||
``` |
|||
|
|||
This should build a docker image and start it. |
|||
|
|||
b) Alternatively, if you're not going to use the Docker image, download the [ROS2 branch of the ROS-TCP-Endpoint](https://github.com/Unity-Technologies/ROS-TCP-Endpoint/tree/ROS2) repository and copy it into the `src` folder in your Colcon workspace. Then navigate to your Colcon workspace and run the following commands: |
|||
|
|||
```bash |
|||
source install/setup.bash |
|||
colcon build |
|||
source install/setup.bash |
|||
``` |
|||
|
|||
Note: yes, you need to run the source command twice. The first sets up the environment for the build to use, the second time adds the newly built packages to the environent. |
|||
|
|||
2. In your Colcon workspace, run the following command, replacing `<your IP address>` with your ROS machine's IP or hostname. |
|||
|
|||
```bash |
|||
ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=<your IP address> |
|||
``` |
|||
|
|||
- If you're running ROS in a Docker container, 0.0.0.0 is a valid incoming address, so you can write `ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=0.0.0.0` |
|||
- On Linux you can find out your IP address with the command `hostname -I` |
|||
- On MacOS you can find out your IP address with `ipconfig getifaddr en0` |
|||
|
|||
Once the server_endpoint has started, it will print something similar to `[INFO] [1603488341.950794]: Starting server on 192.168.50.149:10000`. |
|||
|
|||
3. (Alternative) If you need the server to listen on a port that's different from the default 10000, here's the command line to also set the ROS_TCP_PORT parameter: |
|||
|
|||
```bash |
|||
ros2 run ros_tcp_endpoint default_server_endpoint --ros-args -p ROS_IP:=127.0.0.1 -p ROS_TCP_PORT:=10000 |
|||
``` |
|||
|
|||
## <img src="images/unity-tab-square-white.png" alt="ros2" width="24" height="24"/> Unity Setup |
|||
1. Launch Unity and create a new project. The Robotics package works best with a version of Unity no older than 2020. |
|||
2. Open Package Manager and click the + button at the top left corner. Select "add package from git URL" and enter "https://github.com/Unity-Technologies/ROS-TCP-Connector.git?path=/com.unity.robotics.ros-tcp-connector#dev" to install the [ROS-TCP-Connector](https://github.com/Unity-Technologies/ROS-TCP-Connector) package. |
|||
|
|||
![](images/add_package.png) |
|||
|
|||
![](images/add_package_2.png) |
|||
|
|||
3. If you're not using a Docker container, open `Robotics/ROS Settings` from the Unity menu bar, and set the `ROS IP Address` variable to the IP you set earlier. (If you're using Docker, leave it as the default 127.0.0.1.) |
|||
|
|||
![](images/settings_ros_ip.png) |
|||
|
|||
4. <img src="images/ros2_icon.png" alt="ros2" width="23" height="14"/> Also in the ROS Settings window, ROS2 users should switch the protocol to ROS2 now. |
|||
![](images/ros2_protocol.png) |
|||
|
|||
## Install Unity Robotics Demo |
|||
|
|||
The instructions so far have set up the ROS-TCP-Connector package for general use. If you are specifically following one of the [ROS–Unity Integration tutorials](README.md), you'll need to do the following additional steps: |
|||
|
|||
1. Copy the `unity_robotics_demo` and `unity_robotics_demo_msgs` packages into the `src` folder in your Catkin workspace. (Skip this step if you're using one of the Dockerfiles from this repo: they have the demo packages pre-installed.) |
|||
|
|||
- <img src="images/ros1_icon.png" alt="ros1" width="14" height="14"/> If using ROS1, copy them from from `tutorials/ros_unity_integration/ros_packages` in this repo. |
|||
|
|||
- <img src="images/ros2_icon.png" alt="ros2" width="23" height="14"/> If using ROS2, copy them from `tutorials/ros_unity_integration/ros2_packages` in this repo. |
|||
|
|||
1. Build the new packages. |
|||
|
|||
- <img src="images/ros1_icon.png" alt="ros1" width="14" height="14"/> In ROS1: Run `catkin_make`, and then `source devel/setup.bash` (again) so that ROS can find the newly built messages. |
|||
|
|||
- <img src="images/ros2_icon.png" alt="ros2" width="23" height="14"/> In ROS2: run `colcon build`, then `source install/setup.bash` (again) so that ROS can find the newly built messages. |
|||
|
|||
2. In the Unity menu bar, go to `Robotics` -> `Generate ROS Messages...`. In the Message Browser window, click the Browse button at the top right to set the ROS message path to `tutorials/ros_unity_integration/ros_packages/unity_robotics_demo_msgs` in this repo. |
|||
|
|||
(Note: The version in the ros2_packages folder is equivalent; ROS2 users can feel free to use it, or not.) |
|||
|
|||
3. In the message browser, expand the unity_robotics_demo_msgs subfolder and click "Build 2 msgs" and "Build 2 srvs" to generate C# scripts from the ROS .msg and .srv files. |
|||
|
|||
![](images/generate_messages_3.png) |
|||
|
|||
The generated files will be saved in the default directories `Assets/RosMessages/UnityRoboticsDemo/msg` and `Assets/RosMessages/UnityRoboticsDemo/srv`. Note, there is no difference between the message scripts generated in ROS1 and ROS2 mode. You don't need to regenerate messages when you switch between them. |
|
|||
# ROS–Unity Integration: Service Call |
|||
|
|||
Create a simple Unity scene which calls an external [ROS service](http://wiki.ros.org/Services) with a GameObject's position and rotation to receive a new position to move the GameObject towards. |
|||
|
|||
## Setting Up |
|||
|
|||
- Follow the [ROS–Unity Demo Setup](setup.md) guide if you haven't already done so. |
|||
|
|||
## Start the Position service |
|||
- For this tutorial we will need a ros service for Unity to call. In a new terminal window, navigate to your ROS workspace. |
|||
|
|||
a) <img src="images/ros1_icon.png" alt="ros1" width="14" height="14"/> In ROS1, run the following commands: |
|||
|
|||
```bash |
|||
source devel/setup.bash |
|||
rosrun unity_robotics_demo position_service.py |
|||
``` |
|||
|
|||
b) <img src="images/ros2_icon.png" alt="ros2" width="23" height="14"/> In ROS2, instead run: |
|||
|
|||
```bash |
|||
source install/setup.bash |
|||
ros2 run unity_robotics_demo position_service |
|||
``` |
|||
|
|||
|
|||
## Create Unity Service Caller |
|||
- Create a script and name it `RosServiceCallExample.cs` |
|||
- Paste the following code into `RosServiceCallExample.cs` |
|||
- (Alternatively, you can drag the script file into Unity from `tutorials/ros_unity_integration/unity_scripts`). |
|||
|
|||
```csharp |
|||
using UnityEngine; |
|||
using Unity.Robotics.ROSTCPConnector; |
|||
using RosMessageTypes.UnityRoboticsDemo; |
|||
|
|||
public class RosServiceCallExample : MonoBehaviour |
|||
{ |
|||
ROSConnection ros; |
|||
|
|||
public string serviceName = "pos_srv"; |
|||
|
|||
public GameObject cube; |
|||
|
|||
// Cube movement conditions |
|||
public float delta = 1.0f; |
|||
public float speed = 2.0f; |
|||
private Vector3 destination; |
|||
|
|||
float awaitingResponseUntilTimestamp = -1; |
|||
|
|||
void Start() |
|||
{ |
|||
ros = ROSConnection.instance; |
|||
ros.RegisterRosService<PositionServiceRequest>(serviceName); |
|||
destination = cube.transform.position; |
|||
} |
|||
|
|||
private void Update() |
|||
{ |
|||
// Move our position a step closer to the target. |
|||
float step = speed * Time.deltaTime; // calculate distance to move |
|||
cube.transform.position = Vector3.MoveTowards(cube.transform.position, destination, step); |
|||
|
|||
if (Vector3.Distance(cube.transform.position, destination) < delta && Time.time > awaitingResponseUntilTimestamp) |
|||
{ |
|||
Debug.Log("Destination reached."); |
|||
|
|||
PosRotMsg cubePos = new PosRotMsg( |
|||
cube.transform.position.x, |
|||
cube.transform.position.y, |
|||
cube.transform.position.z, |
|||
cube.transform.rotation.x, |
|||
cube.transform.rotation.y, |
|||
cube.transform.rotation.z, |
|||
cube.transform.rotation.w |
|||
); |
|||
|
|||
PositionServiceRequest positionServiceRequest = new PositionServiceRequest(cubePos); |
|||
|
|||
// Send message to ROS and return the response |
|||
ros.SendServiceMessage<PositionServiceResponse>(serviceName, positionServiceRequest, Callback_Destination); |
|||
awaitingResponseUntilTimestamp = Time.time + 1.0f; // don't send again for 1 second, or until we receive a response |
|||
} |
|||
} |
|||
|
|||
void Callback_Destination(PositionServiceResponse response) |
|||
{ |
|||
awaitingResponseUntilTimestamp = -1; |
|||
destination = new Vector3(response.output.pos_x, response.output.pos_y, response.output.pos_z); |
|||
Debug.Log("New Destination: " + destination); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
- Create an empty GameObject and name it `RosService`. |
|||
- Attach the `RosServiceExample` script to the `RosService` GameObject. Drag the cube GameObject onto its `cube` parameter. |
|||
- Pressing play in the Editor should start communication with the `position_service` script, running as a ROS node, causing the cube to move to random positions in the scene. |
|||
|
|||
|
|||
> Please reference [networking troubleshooting](network.md) doc if any errors are thrown. |
|||
|
|||
![](images/tcp_3.gif) |
|
|||
FROM ros:foxy-ros-base |
|||
|
|||
# Make ROS2 Workspace Dirss |
|||
RUN mkdir -p /home/dev_ws/src |
|||
|
|||
# Copy ROS2 packages into workspace |
|||
COPY ./ros2_packages/ /home/dev_ws/src |
|||
|
|||
#Check out ROS-TCP-Endpoint, ROS2 version |
|||
RUN git clone https://github.com/Unity-Technologies/ROS-TCP-Endpoint /home/dev_ws/src/ros_tcp_endpoint -b ROS2 |
|||
|
|||
# Reference script with commands to source workspace |
|||
COPY ./ros2_docker/source_ros.sh /home/dev_ws/source_ros.sh |
|||
|
|||
# Change to workspace on sign in |
|||
RUN echo "cd home/dev_ws" >> ~/.bashrc |
|||
|
|||
# Build the workspace |
|||
RUN cd home/dev_ws && . /opt/ros/foxy/setup.sh && colcon build |
|||
|
|||
# Source the workspace on sign in |
|||
RUN echo ". install/local_setup.bash" >> ~/.bashrc |
|
|||
#!/bin/bash |
|||
|
|||
source /opt/ros/foxy/setup.bash |
|||
. install/local_setup.bash |
|||
ros2 launch ros2_test test_launcher.py |
|
|||
<?xml version="1.0"?> |
|||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> |
|||
<package format="3"> |
|||
<name>unity_robotics_demo</name> |
|||
<version>0.0.1</version> |
|||
<description>Package for use in ROS-Unity Integration tutorials (ROS2 version)</description> |
|||
<maintainer email="unity-robotics@unity.com">Unity Robotics</maintainer> |
|||
<license>TODO: License declaration</license> |
|||
|
|||
<test_depend>ament_copyright</test_depend> |
|||
<test_depend>ament_flake8</test_depend> |
|||
<test_depend>ament_pep257</test_depend> |
|||
<test_depend>python3-pytest</test_depend> |
|||
|
|||
<exec_depend>rclpy</exec_depend> |
|||
<exec_depend>std_msgs</exec_depend> |
|||
|
|||
<build_depend>rosidl_default_generators</build_depend> |
|||
<exec_depend>rosidl_default_runtime</exec_depend> |
|||
<member_of_group>rosidl_interface_packages</member_of_group> |
|||
|
|||
<export> |
|||
<build_type>ament_python</build_type> |
|||
</export> |
|||
</package> |
|
|||
[develop] |
|||
script-dir=$base/lib/unity_robotics_demo |
|||
[install] |
|||
install-scripts=$base/lib/unity_robotics_demo |
|
|||
import glob |
|||
import os |
|||
|
|||
from setuptools import setup |
|||
|
|||
package_name = 'unity_robotics_demo' |
|||
|
|||
setup( |
|||
name=package_name, |
|||
version='0.0.1', |
|||
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='Unity Robotics', |
|||
maintainer_email='unity-robotics@unity3d.com', |
|||
description='ROS2 Unity Integration Testing', |
|||
license='TODO: License declaration', |
|||
tests_require=['pytest'], |
|||
entry_points={ |
|||
'console_scripts': [ |
|||
'color_publisher = unity_robotics_demo.color_publisher:main', |
|||
'position_service = unity_robotics_demo.position_service:main', |
|||
], |
|||
}, |
|||
) |
|
|||
# Copyright 2015 Open Source Robotics Foundation, Inc. |
|||
# |
|||
# Licensed under the Apache License, Version 2.0 (the "License"); |
|||
# you may not use this file except in compliance with the License. |
|||
# You may obtain a copy of the License at |
|||
# |
|||
# http://www.apache.org/licenses/LICENSE-2.0 |
|||
# |
|||
# Unless required by applicable law or agreed to in writing, software |
|||
# distributed under the License is distributed on an "AS IS" BASIS, |
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
# See the License for the specific language governing permissions and |
|||
# limitations under the License. |
|||
|
|||
from ament_copyright.main import main |
|||
import pytest |
|||
|
|||
|
|||
@pytest.mark.copyright |
|||
@pytest.mark.linter |
|||
def test_copyright(): |
|||
rc = main(argv=['.', 'test']) |
|||
assert rc == 0, 'Found errors' |
|
|||
# Copyright 2017 Open Source Robotics Foundation, Inc. |
|||
# |
|||
# Licensed under the Apache License, Version 2.0 (the "License"); |
|||
# you may not use this file except in compliance with the License. |
|||
# You may obtain a copy of the License at |
|||
# |
|||
# http://www.apache.org/licenses/LICENSE-2.0 |
|||
# |
|||
# Unless required by applicable law or agreed to in writing, software |
|||
# distributed under the License is distributed on an "AS IS" BASIS, |
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
# See the License for the specific language governing permissions and |
|||
# limitations under the License. |
|||
|
|||
from ament_flake8.main import main_with_errors |
|||
import pytest |
|||
|
|||
|
|||
@pytest.mark.flake8 |
|||
@pytest.mark.linter |
|||
def test_flake8(): |
|||
rc, errors = main_with_errors(argv=[]) |
|||
assert rc == 0, \ |
|||
'Found %d code style errors / warnings:\n' % len(errors) + \ |
|||
'\n'.join(errors) |
|
|||
# Copyright 2015 Open Source Robotics Foundation, Inc. |
|||
# |
|||
# Licensed under the Apache License, Version 2.0 (the "License"); |
|||
# you may not use this file except in compliance with the License. |
|||
# You may obtain a copy of the License at |
|||
# |
|||
# http://www.apache.org/licenses/LICENSE-2.0 |
|||
# |
|||
# Unless required by applicable law or agreed to in writing, software |
|||
# distributed under the License is distributed on an "AS IS" BASIS, |
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|||
# See the License for the specific language governing permissions and |
|||
# limitations under the License. |
|||
|
|||
from ament_pep257.main import main |
|||
import pytest |
|||
|
|||
|
|||
@pytest.mark.linter |
|||
@pytest.mark.pep257 |
|||
def test_pep257(): |
|||
rc = main(argv=['.', 'test']) |
|||
assert rc == 0, 'Found code style errors / warnings' |
|
|||
#!/usr/bin/env python |
|||
|
|||
import random |
|||
import rclpy |
|||
|
|||
from rclpy.node import Node |
|||
|
|||
from unity_robotics_demo_msgs.msg import UnityColor |
|||
|
|||
|
|||
class ColorPublisher(Node): |
|||
|
|||
def __init__(self): |
|||
super().__init__('color_publisher') |
|||
self.publisher_ = self.create_publisher(UnityColor, 'color', 10) |
|||
timer_period = 0.5 # seconds |
|||
self.timer = self.create_timer(timer_period, self.timer_callback) |
|||
self.i = 0 |
|||
self.do_publish() |
|||
|
|||
def do_publish(self): |
|||
if self.i == 0: |
|||
color = UnityColor() |
|||
color.r = random.randint(0, 255) |
|||
color.g = random.randint(0, 255) |
|||
color.b = random.randint(0, 255) |
|||
color.a = 1 |
|||
self.get_logger().info(f'Publishing: {color}') |
|||
self.publisher_.publish(color) |
|||
|
|||
self.i += 1 |
|||
|
|||
def timer_callback(self): |
|||
quit() |
|||
|
|||
|
|||
def main(args=None): |
|||
rclpy.init(args=args) |
|||
|
|||
color_pub = ColorPublisher() |
|||
|
|||
while rclpy.ok(): |
|||
rclpy.spin_once(color_pub) |
|||
|
|||
#color_pub.destroy_node() |
|||
#rclpy.shutdown() |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
main() |
|
|||
#!/usr/bin/env python |
|||
|
|||
import random |
|||
import rclpy |
|||
|
|||
from unity_robotics_demo_msgs.srv import PositionService |
|||
|
|||
from rclpy.node import Node |
|||
|
|||
class PositionServiceNode(Node): |
|||
|
|||
def __init__(self): |
|||
super().__init__('position_service_node') |
|||
self.srv = self.create_service(PositionService, 'pos_srv', self.new_position_callback) |
|||
|
|||
def new_position_callback(self, request, response): |
|||
response.output.pos_x = random.uniform(-4.0, 4.0) |
|||
response.output.pos_z = random.uniform(-4.0, 4.0) |
|||
|
|||
return response |
|||
|
|||
|
|||
def main(args=None): |
|||
rclpy.init(args=args) |
|||
|
|||
pos_service = PositionServiceNode() |
|||
|
|||
rclpy.spin(pos_service) |
|||
|
|||
rclpy.shutdown() |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
main() |
|
|||
cmake_minimum_required(VERSION 3.5) |
|||
project(unity_robotics_demo_msgs) |
|||
|
|||
# find dependencies |
|||
find_package(rosidl_default_generators REQUIRED) |
|||
find_package(builtin_interfaces REQUIRED) |
|||
find_package(geometry_msgs REQUIRED) |
|||
find_package(std_msgs REQUIRED) |
|||
|
|||
rosidl_generate_interfaces(${PROJECT_NAME} |
|||
"msg/PosRot.msg" |
|||
"msg/UnityColor.msg" |
|||
"srv/PositionService.srv" |
|||
"srv/ObjectPoseService.srv" |
|||
DEPENDENCIES builtin_interfaces geometry_msgs std_msgs |
|||
) |
|||
|
|||
if(BUILD_TESTING) |
|||
find_package(ament_lint_auto REQUIRED) |
|||
# the following line skips the linter which checks for copyrights |
|||
# uncomment the line when a copyright and license is not present in all source files |
|||
#set(ament_cmake_copyright_FOUND TRUE) |
|||
# the following line skips cpplint (only works in a git repo) |
|||
# uncomment the line when this package is not in a git repo |
|||
#set(ament_cmake_cpplint_FOUND TRUE) |
|||
ament_lint_auto_find_test_dependencies() |
|||
endif() |
|||
|
|||
ament_package() |
|||
|
|||
|
|||
|
|||
|
|||
|
|
|||
<?xml version="1.0"?> |
|||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> |
|||
<package format="3"> |
|||
<name>unity_robotics_demo_msgs</name> |
|||
<version>0.0.1</version> |
|||
<description>Messages used by ROS-Unity Integration tutorial (ROS2 version)</description> |
|||
<maintainer email="unity-robotics@unity.com">Unity Robotics</maintainer> |
|||
<license>TODO: License declaration</license> |
|||
|
|||
<buildtool_depend>ament_cmake</buildtool_depend> |
|||
|
|||
<test_depend>ament_lint_auto</test_depend> |
|||
<test_depend>ament_lint_common</test_depend> |
|||
|
|||
<build_depend>rosidl_default_generators</build_depend> |
|||
|
|||
<exec_depend>rosidl_default_runtime</exec_depend> |
|||
|
|||
<member_of_group>rosidl_interface_packages</member_of_group> |
|||
|
|||
|
|||
<export> |
|||
<build_type>ament_cmake</build_type> |
|||
</export> |
|||
</package> |
|
|||
FROM ros:melodic-ros-base |
|||
|
|||
ENV ROS_WORKSPACE=/catkin_ws |
|||
|
|||
# Copy packages |
|||
COPY ./ros_packages/ $ROS_WORKSPACE/src/ |
|||
|
|||
RUN git clone https://github.com/Unity-Technologies/ROS-TCP-Endpoint $ROS_WORKSPACE/src/ros_tcp_endpoint -b laurie/Ros2SinglePackage |
|||
|
|||
COPY ./ros_docker/set-up-workspace /setup.sh |
|||
#COPY docker/tutorial / |
|||
|
|||
RUN chmod +x /setup.sh && /setup.sh && rm /setup.sh |
|||
|
|||
WORKDIR $ROS_WORKSPACE |
|||
|
|||
# Source the workspace on sign in |
|||
RUN echo ". devel/setup.bash" >> ~/.bashrc |
|||
|
|||
# making sure the file modes are executable |
|||
RUN chmod +x src/ros_tcp_endpoint/src/ros_tcp_endpoint/*.py |
|||
|
|||
#ENTRYPOINT ["/tutorial"] |
|||
|
|
|||
#!/bin/bash |
|||
|
|||
source /opt/ros/melodic/setup.bash |
|||
echo "ROS_IP: 0.0.0.0" > $ROS_WORKSPACE/src/ros_tcp_endpoint/config/params.yaml |
|||
cd $ROS_WORKSPACE |
|||
catkin_make |
|
|||
cmake_minimum_required(VERSION 2.8.3) |
|||
project(unity_robotics_demo) |
|||
|
|||
find_package(catkin REQUIRED COMPONENTS |
|||
rospy |
|||
std_msgs |
|||
geometry_msgs |
|||
ros_tcp_endpoint |
|||
message_generation |
|||
) |
|||
|
|||
catkin_package(CATKIN_DEPENDS |
|||
ros_tcp_endpoint |
|||
message_runtime) |
|||
|
|||
catkin_install_python(PROGRAMS |
|||
scripts/position_service.py |
|||
scripts/color_publisher.py |
|||
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} |
|||
) |
|||
|
|||
|
|||
############# |
|||
## Testing ## |
|||
############# |
|||
|
|||
## Add gtest based cpp test target and link libraries |
|||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_robotics_demo.cpp) |
|||
# if(TARGET ${PROJECT_NAME}-test) |
|||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) |
|||
# endif() |
|||
|
|||
## Add folders to be run by python nosetests |
|||
# catkin_add_nosetests(test) |
|
|||
<?xml version="1.0"?> |
|||
<package format="2"> |
|||
<name>unity_robotics_demo</name> |
|||
<version>0.0.0</version> |
|||
<description>The unity_robotics_demo package (ROS1 version)</description> |
|||
|
|||
<maintainer email="unity-robotics@unity3d.com">Unity Robotics</maintainer> |
|||
|
|||
|
|||
<license>Apache 2.0</license> |
|||
|
|||
<buildtool_depend>catkin</buildtool_depend> |
|||
<build_depend>rospy</build_depend> |
|||
<build_depend>message_generation</build_depend> |
|||
<build_depend>std_msgs</build_depend> |
|||
<build_depend>ros_tcp_endpoint</build_depend> |
|||
<build_depend>unity_robotics_demo_msgs</build_depend> |
|||
<build_export_depend>rospy</build_export_depend> |
|||
<build_export_depend>std_msgs</build_export_depend> |
|||
<build_export_depend>ros_tcp_endpoint</build_export_depend> |
|||
<build_export_depend>unity_robotics_demo_msgs</build_export_depend> |
|||
<exec_depend>message_runtime</exec_depend> |
|||
<exec_depend>rospy</exec_depend> |
|||
<exec_depend>std_msgs</exec_depend> |
|||
<exec_depend>ros_tcp_endpoint</exec_depend> |
|||
<exec_depend>unity_robotics_demo_msgs</exec_depend> |
|||
|
|||
|
|||
<!-- The export tag contains other, unspecified, tags --> |
|||
<export> |
|||
<!-- Other tools can request additional information be placed here --> |
|||
|
|||
</export> |
|||
</package> |
|
|||
#!/usr/bin/env python |
|||
|
|||
import random |
|||
import rospy |
|||
import rosgraph |
|||
import time |
|||
from unity_robotics_demo_msgs.msg import UnityColor |
|||
|
|||
|
|||
TOPIC_NAME = 'color' |
|||
NODE_NAME = 'color_publisher' |
|||
|
|||
|
|||
def post_color(): |
|||
pub = rospy.Publisher(TOPIC_NAME, UnityColor, queue_size=10) |
|||
rospy.init_node(NODE_NAME, anonymous=True) |
|||
|
|||
r = random.randint(0, 255) |
|||
g = random.randint(0, 255) |
|||
b = random.randint(0, 255) |
|||
color = UnityColor(r, g, b, 1) |
|||
|
|||
wait_for_connections(pub, TOPIC_NAME) |
|||
pub.publish(color) |
|||
|
|||
time.sleep(0.1) |
|||
|
|||
|
|||
def wait_for_connections(pub, topic): |
|||
ros_master = rosgraph.Master('/rostopic') |
|||
topic = rosgraph.names.script_resolve_name('rostopic', topic) |
|||
num_subs = 0 |
|||
for sub in ros_master.getSystemState()[1]: |
|||
if sub[0] == topic: |
|||
num_subs+=1 |
|||
|
|||
for i in range(10): |
|||
if pub.get_num_connections() == num_subs: |
|||
return |
|||
time.sleep(0.1) |
|||
raise RuntimeError("failed to get publisher") |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
try: |
|||
post_color() |
|||
except rospy.ROSInterruptException: |
|||
pass |
|
|||
cmake_minimum_required(VERSION 2.8.3) |
|||
project(unity_robotics_demo_msgs) |
|||
|
|||
find_package(catkin REQUIRED COMPONENTS |
|||
rospy |
|||
std_msgs |
|||
geometry_msgs |
|||
message_generation |
|||
) |
|||
|
|||
add_message_files(FILES |
|||
PosRot.msg |
|||
UnityColor.msg |
|||
) |
|||
add_service_files(FILES |
|||
ObjectPoseService.srv |
|||
PositionService.srv |
|||
) |
|||
|
|||
generate_messages( |
|||
DEPENDENCIES |
|||
geometry_msgs |
|||
std_msgs |
|||
) |
|||
|
|||
catkin_package(CATKIN_DEPENDS |
|||
message_runtime) |
|||
|
|||
############# |
|||
## Testing ## |
|||
############# |
|||
|
|||
## Add gtest based cpp test target and link libraries |
|||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_robotics_demo.cpp) |
|||
# if(TARGET ${PROJECT_NAME}-test) |
|||
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME}) |
|||
# endif() |
|||
|
|||
## Add folders to be run by python nosetests |
|||
# catkin_add_nosetests(test) |
|
|||
float32 pos_x |
|||
float32 pos_y |
|||
float32 pos_z |
|||
float32 rot_x |
|||
float32 rot_y |
|||
float32 rot_z |
|||
float32 rot_w |
|
|||
int32 r |
|||
int32 g |
|||
int32 b |
|||
int32 a |
|
|||
<?xml version="1.0"?> |
|||
<package format="2"> |
|||
<name>unity_robotics_demo_msgs</name> |
|||
<version>0.0.1</version> |
|||
<description>Messages for the unity_robotics_demo package (ROS1 version)</description> |
|||
|
|||
<maintainer email="unity-robotics@unity3d.com">Unity Robotics</maintainer> |
|||
|
|||
|
|||
<license>Apache 2.0</license> |
|||
|
|||
<buildtool_depend>catkin</buildtool_depend> |
|||
<build_depend>message_generation</build_depend> |
|||
<build_depend>std_msgs</build_depend> |
|||
<build_export_depend>rospy</build_export_depend> |
|||
<build_export_depend>std_msgs</build_export_depend> |
|||
<exec_depend>message_runtime</exec_depend> |
|||
<exec_depend>rospy</exec_depend> |
|||
<exec_depend>std_msgs</exec_depend> |
|||
<exec_depend>ros_tcp_endpoint</exec_depend> |
|||
|
|||
|
|||
<!-- The export tag contains other, unspecified, tags --> |
|||
<export> |
|||
<!-- Other tools can request additional information be placed here --> |
|||
|
|||
</export> |
|||
</package> |
|
|||
string object_name |
|||
--- |
|||
geometry_msgs/Pose object_pose |
|
|||
PosRot input |
|||
--- |
|||
PosRot output |
|
|||
# ROS–Unity Integration: Server Endpoint |
|||
|
|||
A walkthrough of the important components of a ROS TCP endpoint script using the `robotics_demo` package as a example. |
|||
|
|||
The following is an example of a server endpoint Python script that: |
|||
|
|||
- Gets parameters from `rosparam` |
|||
- Creates corresponding ROS Publisher, Subscriber, and Service objects to interact with topics and services running in ROS network |
|||
- Starts TCP Server process to handle incoming and outgoing connections |
|||
|
|||
|
|||
```python |
|||
#!/usr/bin/env python |
|||
|
|||
import rospy |
|||
|
|||
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService, UnityService |
|||
from robotics_demo.msg import PosRot, UnityColor |
|||
from robotics_demo.srv import PositionService, ObjectPoseService |
|||
|
|||
def main(): |
|||
ros_node_name = rospy.get_param("/TCP_NODE_NAME", 'TCPServer') |
|||
buffer_size = rospy.get_param("/TCP_BUFFER_SIZE", 1024) |
|||
connections = rospy.get_param("/TCP_CONNECTIONS", 10) |
|||
tcp_server = TcpServer(ros_node_name, buffer_size, connections) |
|||
rospy.init_node(ros_node_name, anonymous=True) |
|||
|
|||
tcp_server.start({ |
|||
'pos_rot': RosPublisher('pos_rot', PosRot, queue_size=10), |
|||
'color': RosSubscriber('color', UnityColor, tcp_server), |
|||
'pos_srv': RosService('pos_srv', PositionService), |
|||
'obj_pose_srv': UnityService('obj_pose_srv', ObjectPoseService, tcp_server), |
|||
}) |
|||
|
|||
rospy.spin() |
|||
|
|||
|
|||
if __name__ == "__main__": |
|||
main() |
|||
``` |
|||
|
|||
|
|||
## Import Statements for Services and Messages |
|||
```python |
|||
from ros_tcp_endpoint import TcpServer, RosPublisher, RosSubscriber, RosService, UnityService |
|||
from robotics_demo.msg import PosRot, UnityColor |
|||
from robotics_demo.srv import PositionService, ObjectPoseService |
|||
``` |
|||
|
|||
## Creating the Server |
|||
|
|||
Requires: |
|||
|
|||
- The ROS node name |
|||
|
|||
```python |
|||
tcp_server = TcpServer(ros_node_name, buffer_size, connections) |
|||
``` |
|||
|
|||
The `ros_node_name` argument is required and the `buffer_size` and `connections` are optional. They are set to `1024` and `10` by default if not provided in the constructor arguments. |
|||
|
|||
## Instantiate the ROS Node |
|||
|
|||
```python |
|||
rospy.init_node(ros_node_name, anonymous=True) |
|||
``` |
|||
|
|||
## Starting the Server |
|||
|
|||
```python |
|||
tcp_server.start({ |
|||
'pos_rot': RosPublisher('pos_rot', PosRot, queue_size=10), |
|||
'color': RosSubscriber('color', UnityColor, tcp_server), |
|||
'pos_srv': RosService('pos_srv', PositionService), |
|||
'obj_pose_srv': UnityService('obj_pose_srv', ObjectPoseService, tcp_server), |
|||
}) |
|||
|
|||
rospy.spin() |
|||
``` |
|||
|
|||
## Source Destination Dictionary |
|||
|
|||
The argument to start() is a dictionary keyed by topic or service with the corresponding ROS communication class as the value. The dictionary is used by the TCP server to direct messages to and from the ROS network. |
|||
|
|||
## ROS Publisher |
|||
A ROS Publisher allows a Unity component to send messages on a given topic to other ROS nodes. It requires three components: |
|||
|
|||
- Topic name |
|||
- ROS message class generated from running `catkin_make` command |
|||
- Queue size (optional) |
|||
|
|||
`RosPublisher('pos_rot', PosRot, queue_size=10)` |
|||
|
|||
## ROS Subscriber |
|||
A ROS Subscriber allows a Unity component to receive messages from other ROS nodes on a given topic. It requires three components: |
|||
|
|||
- Topic name |
|||
- ROS message class generated from running `catkin_make` command |
|||
- The tcp server that will connect to Unity |
|||
|
|||
`RosSubscriber('color', UnityColor, tcp_server)` |
|||
|
|||
## ROS Service |
|||
A ROS Service is similar to a RosPublisher, in that a Unity component sends a Request message to another ROS node. Unlike a Publisher, the Unity component then waits for a Response back. It requires two components: |
|||
|
|||
- Service name |
|||
- ROS Service class generated from running `catkin_make` command |
|||
|
|||
`RosService('pos_srv', PositionService)` |
|||
|
|||
## Unity Service |
|||
|
|||
A Unity Service is similar to a RosSubscriber, in that a Unity component receives a Request message from another ROS node. It then sends a Response back. It requires three components: |
|||
|
|||
- Service name |
|||
- ROS Service class generated from running `catkin_make` command |
|||
- The tcp server that will connect to Unity |
|||
|
|||
`UnityService('obj_pose_srv', ObjectPoseService, tcp_server)` |
|||
|
|||
|
|||
## Parameters |
|||
|
|||
The following parameters can be hardcoded, but for the sake of portability, we recommend setting the parameters using the `rosparam set` command, or a `rosparam` YAML file. |
|||
|
|||
```python |
|||
ros_node_name = rospy.get_param("/TCP_NODE_NAME", 'TCPServer') |
|||
buffer_size = rospy.get_param("/TCP_BUFFER_SIZE", 1024) |
|||
connections = rospy.get_param("/TCP_CONNECTIONS", 10) |
|||
``` |
|||
|
|||
In addition, the TCPServer class uses the ROS parameters ROS_IP and ROS_TCP_PORT to determine what ip & port to listen on. |
|||
|
|||
> Note: Read more about the ROS Parameter Server [here](http://wiki.ros.org/Parameter%20Server). |
|||
|
|||
## Launch File |
|||
An example launch file that will set the appropriate ROSPARAM values required for a parameterized TCP Endpoint script. |
|||
|
|||
``` |
|||
<launch> |
|||
|
|||
<env name="ROS_IP" value="127.0.0.1"/> |
|||
<env name="ROS_HOSTNAME" value="$(env ROS_IP)"/> |
|||
|
|||
<param name="ROS_IP" type="str" value="$(env ROS_IP)" /> |
|||
<param name="ROS_TCP_PORT" type="int" value="10000" /> |
|||
<param name="TCP_NODE_NAME" type="str" value="TCPServer" /> |
|||
|
|||
<group ns="position_service_and_endpoint"> |
|||
<node pkg="robotics_demo" name="position_service" type="position_service.py"/> |
|||
<node pkg="robotics_demo" name="server_endpoint" type="server_endpoint.py"/> |
|||
</group> |
|||
</launch> |
|||
``` |
|
|||
# ROS–Unity Integration: Service |
|||
|
|||
Create a simple Unity scene which calls a [ROS service](http://wiki.ros.org/Services) with a GameObject's position and rotation to receive a new position to move the GameObject towards. |
|||
|
|||
## Setting Up ROS |
|||
|
|||
(Skip to [Start the Position service](service.md#start-the-position-service) if you already did the [ROS–Unity Integration Publisher](publisher.md) or [Subscriber](subscriber.md) tutorials.) |
|||
|
|||
- Copy the `tutorials/ros_packages/robotics_demo` folder of this repo into the `src` folder in your Catkin workspace. |
|||
|
|||
- Follow the [ROS–Unity Initial Setup](setup.md) guide. |
|||
|
|||
- Open a new terminal window, navigate to your ROS workspace, and run the following commands: |
|||
|
|||
```bash |
|||
source devel/setup.bash |
|||
rosrun robotics_demo server_endpoint.py |
|||
``` |
|||
|
|||
Once the server_endpoint has started, it will print something similar to `[INFO] [1603488341.950794]: Starting server on 192.168.50.149:10000`. |
|||
|
|||
## Start the Position service |
|||
- Open a new terminal window, navigate to your ROS workspace, and run the following commands: |
|||
|
|||
```bash |
|||
source devel/setup.bash |
|||
rosrun robotics_demo position_service.py |
|||
``` |
|||
|
|||
## Setting Up Unity Scene |
|||
- Generate the C# code for `PositionService`'s messages by going to `Robotics` -> `Generate ROS Messages...` |
|||
- Set the input file path to `PATH/TO/Unity-Robotics-Hub/tutorials/ros_packages/robotics_demo`, expand the robotics_demo folder and click `Build 2 srvs`. |
|||
|
|||
![](images/generate_messages_2.png) |
|||
|
|||
- The generated files will be saved in the default directory `Assets/RosMessages/RoboticsDemo/srv`. |
|||
- Create a script and name it `RosServiceExample.cs` |
|||
- Paste the following code into `RosServiceExample.cs` |
|||
- **Note:** This script can be found at `tutorials/ros_unity_integration/unity_scripts`. |
|||
|
|||
```csharp |
|||
using RosMessageTypes.RoboticsDemo; |
|||
using UnityEngine; |
|||
using Unity.Robotics.ROSTCPConnector; |
|||
|
|||
public class RosServiceExample : MonoBehaviour |
|||
{ |
|||
ROSConnection ros; |
|||
|
|||
public string serviceName = "pos_srv"; |
|||
|
|||
public GameObject cube; |
|||
|
|||
// Cube movement conditions |
|||
public float delta = 1.0f; |
|||
public float speed = 2.0f; |
|||
private Vector3 destination; |
|||
|
|||
float awaitingResponseUntilTimestamp = -1; |
|||
|
|||
void Start() |
|||
{ |
|||
ros = ROSConnection.instance; |
|||
destination = cube.transform.position; |
|||
} |
|||
|
|||
private void Update() |
|||
{ |
|||
// Move our position a step closer to the target. |
|||
float step = speed * Time.deltaTime; // calculate distance to move |
|||
cube.transform.position = Vector3.MoveTowards(cube.transform.position, destination, step); |
|||
|
|||
if (Vector3.Distance(cube.transform.position, destination) < delta && Time.time > awaitingResponseUntilTimestamp) |
|||
{ |
|||
Debug.Log("Destination reached."); |
|||
|
|||
MPosRot cubePos = new MPosRot( |
|||
cube.transform.position.x, |
|||
cube.transform.position.y, |
|||
cube.transform.position.z, |
|||
cube.transform.rotation.x, |
|||
cube.transform.rotation.y, |
|||
cube.transform.rotation.z, |
|||
cube.transform.rotation.w |
|||
); |
|||
|
|||
MPositionServiceRequest positionServiceRequest = new MPositionServiceRequest(cubePos); |
|||
|
|||
// Send message to ROS and return the response |
|||
ros.SendServiceMessage<MPositionServiceResponse>(serviceName, positionServiceRequest, Callback_Destination); |
|||
awaitingResponseUntilTimestamp = Time.time+1.0f; // don't send again for 1 second, or until we receive a response |
|||
} |
|||
} |
|||
|
|||
void Callback_Destination(MPositionServiceResponse response) |
|||
{ |
|||
awaitingResponseUntilTimestamp = -1; |
|||
destination = new Vector3(response.output.pos_x, response.output.pos_y, response.output.pos_z); |
|||
Debug.Log("New Destination: " + destination); |
|||
} |
|||
} |
|||
``` |
|||
|
|||
- From the main menu bar, open `Robotics/ROS Settings`, and change the `ROS IP Address` variable to the ROS IP. |
|||
- Create an empty GameObject and name it `RosService`. |
|||
- Attach the `RosServiceExample` script to the `RosService` GameObject. Drag the cube GameObject onto its `cube` parameter. |
|||
- Pressing play in the Editor should start communication with the `position_service` script, running as a ROS node, causing the cube to move to random positions in the scene. |
|||
|
|||
|
|||
> Please reference [networking troubleshooting](network.md) doc if any errors are thrown. |
|||
|
|||
![](images/tcp_3.gif) |
撰写
预览
正在加载...
取消
保存
Reference in new issue