devcontainer docker support and DDS network interfcace configuraion settings are added

This commit is contained in:
Rooholla-KhorramBakht 2024-09-30 17:38:26 -04:00
parent d4b8412dc0
commit 99f8eb3a6a
11 changed files with 162 additions and 10 deletions

View File

@ -0,0 +1,9 @@
<CycloneDDS>
<Domain>
<General>
<Interfaces>
<NetworkInterface name="enx00e04c006390" priority="default" multicast="default" />
</Interfaces>
</General>
</Domain>
</CycloneDDS>

Binary file not shown.

View File

@ -18,17 +18,22 @@ from cyclonedds.util import duration
from threading import Thread
from scipy.spatial.transform import Rotation
from Go2Py.joy import xKeySwitch, xRockerBtn
from Go2Py.utils import set_cyclonedds_config
class GO2Real():
def __init__(
self,
interface_name=None,
mode='lowlevel', # 'highlevel' or 'lowlevel'
vx_max=0.5,
vy_max=0.4,
ωz_max=0.5,
):
assert mode in ['highlevel', 'lowlevel'], "mode should be either 'highlevel' or 'lowlevel'"
if interface_name is not None:
set_cyclonedds_config(interface_name)
self.mode = mode
self.simulated = False
self.prestanding_q = np.array([0.0, 1.26186061, -2.5,
@ -50,8 +55,11 @@ class GO2Real():
self.lowcmd_topic_name = "rt/go2py/low_cmd"
self.highcmd_topic_name = "rt/go2py/high_cmd"
self.lowstate_topic_name = "rt/go2py/state"
try:
self.participant = DomainParticipant()
except:
raise Exception('Could not initialize the DDS communication. Is the interface name provided correctly?')
self.participant = DomainParticipant()
self.lowstate_topic = Topic(self.participant, self.lowstate_topic_name, Go2pyState_)
self.state_reader = DataReader(self.participant, self.lowstate_topic)
@ -69,6 +77,7 @@ class GO2Real():
self.state = None
self.setCommands = {'lowlevel': self.setCommandsLow,
'highlevel': self.setCommandsHigh}[self.mode]
self.state = Go2pyState_
self.state_thread = Thread(target=self.state_update)
self.running = True
self.state_thread.start()

View File

@ -0,0 +1,22 @@
import os
import tempfile
from Go2Py import ASSETS_PATH
def set_cyclonedds_config(interface_name):
# Generate the XML configuration
xml_content = f"""<CycloneDDS>
<Domain>
<General>
<Interfaces>
<NetworkInterface name="{interface_name}" priority="default" multicast="default" />
</Interfaces>
</General>
</Domain>
</CycloneDDS>"""
# Create a temporary XML file
cfg_file_path = os.path.join(ASSETS_PATH, 'cyclonedds.xml')
with open(cfg_file_path, 'w') as f:
f.write(xml_content)
# Set the environment variable
os.environ['CYCLONEDDS_URI'] = f'file://{cfg_file_path}'

View File

@ -0,0 +1,8 @@
include Go2Py/assets/*.xml
include Go2Py/assets/urdf/*.urdf
include Go2Py/assets/mujoco/*.xml
include Go2Py/mujoco/assets/*.obj
include Go2Py/mujoco/dae/*.dae
include Go2Py/assets/checkpoints/walk_these_ways/checkpoints/*.jit
include Go2Py/assets/checkpoints/walk_these_ways/checkpoints/*.pt
include Go2Py/assets/checkpoints/walk_these_ways/*.pkl

View File

@ -1,7 +1,16 @@
INTERFACE = enx00e04c006390 # interface name used to talk with the robot
# Target to run the script with the specified interface
ddscfg:
python3 scripts/set_cyclonedds_config.py $(INTERFACE) && /bin/bash scripts/ros_env_setup.bash
frontcam:
@cd deploy && docker build --no-cache --tag go2py_frontcam_publisher:latest -f docker/Dockerfile.frontcam .
docker_start:
@cd .devcontainer && docker compose up go2py
isaac_ros_start:
@./scripts/run_dev.sh
nav2:

View File

@ -2,6 +2,6 @@ source /opt/ros/humble/setup.bash
source /unitree_ros2/cyclonedds_ws/install/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI='<CycloneDDS><Domain><General><Interfaces>
<NetworkInterface name="eth0" priority="default" multicast="default" />
<NetworkInterface name="enx00e04c006390" priority="default" multicast="default" />
</Interfaces></General></Domain></CycloneDDS>'
source /bridge_ws/install/setup.bash && ros2 launch /root/launch/bridge.launch.py

View File

@ -47,6 +47,8 @@ If everything has been successful, you should be able to access the internet on
## Installing the Docker
All the deployed services in Go2Py are based on docker so make sure that docker and Nvidia runtime is installed. For this, you can follow through the Isaac-ROS installation instructions [here](https://nvidia-isaac-ros.github.io/getting_started/hardware_setup/compute/jetson_storage.html).
**Note:** For the LiDAR node, the `nvidia contaner toolkit` should also be installed on the robot.
## Installing the Go2Py
Go2Py has two main components. A set of services running on the robot and a Python package that can run anywhere and is used to communicate with the robot in Python.
@ -70,11 +72,15 @@ sudo make bridge_install
# For the robot description service
make robot_description
sudo make robot_description_install
```
The first command for each service makes the corresponding docker image and the second command, copies the service file that runs those images into the appropriate locations of the system and enables them as autorun services. You can check for the success of this installation by checking the output of the `systemctl status service_name.service` command where the `service_name` is replaced with the name of the service you want to check.
**Note**: At the moment, the implemented LiDAR driver service only supports the XT16 sensor. If you have this sensor on your robot run:
```bash
# For the LiDAR driver
make hesai
sudo make hesai_install
```
The first command for each service makes the corresponding docker image and the second command, copies the service file that runs those images into the appropriate locations of the system and enables them as autorun services. You can check for the success of this installation by checking the output of the `systemctl status service_name.service` command where the `service_name` is replaced with the name of the service you want to check.
### Installing the GoPy
#### Local Installation
@ -82,15 +88,20 @@ Finally, we need to install the Go2Py Python library on a computer located on th
```bash
pip install -e .
```
After successful installation, open the `Makefile` in the root directory and set the `INTERFACE` variable at the top of the file to the network interface name connected to the robot's network. Then, simply run `make ddscfg` to configure CycloneDDS for proper communication with the robot.
To check the installation, run the interface example [here](../examples/00-robot-interface.ipynb) to make sure you can read the state of the robot.
#### Using Docker
In addition to local installation, you can use the provided docker support. To do so, run `make docker_start` in the root directory of the repository:
```bash
cd ~/Go2Py
make docker_start
```
In addition to local installation, you can use the provided docker support:
##### VSCode Devcontainers
Simply install the devcontainer extension in your VSCode and press `SHIFT+Ctrl+P` and run `Rebuild and Reopen in Container` while you're in the root directory of the project.
#### Direct
With this, a docker container with all the required dependencies will be launched and the Go2Py repository will be mounted into `/workspaces/Go2Py` and installed in editable mode. Since our docker support is based on the Nvida Isaac-ROS images, you should be able to use the Iasaac-ROS packages within this environment.
Runing `make docker_start` launces a container with all the requirements installed. Attach to this container and follow the local installation instructions inside the docker.
#### Installation With Isaac-ROS Docker
Running `make isaac_ros_start` starts a docker container with all the required dependencies. The Go2Py repository will be mounted into `/workspaces/Go2Py` and installed in editable mode. Inside this docker environment, you can use the Iasaac-ROS packages.
Note that our docker image may be extended in a similar way to the Isaac-ROS images (as explained [here](https://nvidia-isaac-ros.github.io/repositories_and_packages/isaac_ros_common/index.html)). Simply append the `CONFIG_IMAGE_KEY="ros2_humble.go2py"` [here](../scripts/.isaac_ros_common-config) with the key to your custom Dockerfile name (e.g. `CONFIG_IMAGE_KEY="ros2_humble.go2py.custom"` for `Dockerfile.custom`) and place your docker file under `docker` directory [here](../docker) and append its name with the key you used (e.g. `Dockerfile.custom`). Your custom Dockerfile should start with:
```docker
@ -98,3 +109,6 @@ ARG BASE_IMAGE
FROM ${BASE_IMAGE}
```
In addition to this added docker image layer, you can add your own post execution commands that are excuted each time you start the docker container. These commands should be appended to the end of `workspace-entrypoint.sh` script [here](../docker/scripts/workspace-entrypoint.sh).
#### Enabling GUI Access
In case you're interested in running the simulations inside the docker with GUI support, you need to run `xhost +` on your host terminal to allow X11 requests from the applications inside the Docker.

63
multicast_config.py Normal file
View File

@ -0,0 +1,63 @@
import argparse
import subprocess
def configure_multicast(device_name):
"""
Configures multicast settings for a given network device.
@param device_name: The name of the network device to configure.
@type device_name: str
@raises subprocess.CalledProcessError: If the execution of any command fails.
@note:
This function requires administrative privileges to execute commands like 'route' and 'ifconfig'.
Run the Python script as a superuser or provide the necessary credentials.
@example:
device = 'eth0'
configure_multicast(device)
"""
add_route_command = [
"route",
"add",
"-net",
"224.0.0.0",
"netmask",
"240.0.0.0",
"dev",
device_name,
]
enable_multicast_command = ["sudo", "ifconfig", device_name, "multicast"]
subprocess.run(add_route_command, check=True)
subprocess.run(enable_multicast_command, check=True)
def main():
"""
Main entry point of the script.
Parses the command-line arguments and invokes the configuration function.
"""
# Create an argument parser
parser = argparse.ArgumentParser(
description="Configure multicast settings for a network interface."
)
# Add the interface name argument
parser.add_argument(
"interface", type=str, help="The name of the network interface to configure."
)
# Parse the command-line arguments
args = parser.parse_args()
# Invoke the configuration function
configure_multicast(args.interface)
if __name__ == "__main__":
main()

4
scripts/ros_env_setup.bash Executable file
View File

@ -0,0 +1,4 @@
source /opt/ros/humble/setup.bash
source /unitree_ros2/cyclonedds_ws/install/setup.bash
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export CYCLONEDDS_URI=file://$(pwd)/Go2Py/assets/cyclonedds.xml

View File

@ -0,0 +1,14 @@
from Go2Py.utils import set_cyclonedds_config
import argparse
def main():
# Set up argument parsing
parser = argparse.ArgumentParser(description="Set CycloneDDS configuration.")
parser.add_argument("network_interface", help="The name of the network interface used to communicate with the robot.")
# Parse the arguments
args = parser.parse_args()
# Set the CycloneDDS configuration
set_cyclonedds_config(args.network_interface)
if __name__ == "__main__":
main()