-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* muto composer ported to ros2 * modified workflow file for ros2 * renamed workflow file and added rosdep * updated package information * updated workflow file * removed rosdep init from workflow * added python3-pip to workflow run * added universe repo to workflow file * updated workflow file * added -y flag to apt update * added setuptools to workflow file * removed newline on description * changed ros setup script on workflow * replaced source with . in workflow file * replaced ros setup scripts from bash to sh * commented colcon test out on workflow file * updated README.md for ros2
- Loading branch information
1 parent
7574b56
commit cebc72e
Showing
33 changed files
with
1,918 additions
and
721 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: Colcon Build and Test | ||
|
||
on: [push] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
container: osrf/ros:humble-desktop | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
|
||
- run: | | ||
mkdir -p $(pwd)/tmp/muto/src/ | ||
ln -s $(pwd) $(pwd)/tmp/muto/src/composer | ||
cd $(pwd)/tmp/muto | ||
apt-get update -y | ||
apt-get install python3-pip -y | ||
pip3 install setuptools==58.2.0 | ||
. /opt/ros/humble/setup.sh | ||
rosdep update -y | ||
rosdep install --from-path src --ignore-src -r -y --rosdistro humble | ||
colcon build | ||
. install/setup.sh | ||
# colcon test | ||
# colcon test-result --all --verbose | ||
name: Composer ROS2 Humble container build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,98 +4,58 @@ | |
# Muto Composer | ||
|
||
## Build | ||
After you checkou the repository, ource your ROS environment and make sure the additional dependencies such as the eclipse paho mqtt client library is installed. | ||
After you checkout the repository, source your ROS environment and make sure the additional dependencies such as the eclipse paho mqtt client library is installed. | ||
|
||
```bash | ||
source /opt/ro/noetic/setup.bash | ||
pip install paho-mqtt celery requests | ||
source /opt/ros/humble/setup.bash | ||
pip3 install paho-mqtt celery requests | ||
``` | ||
|
||
## Muto Twins | ||
|
||
Muto agent requires network connectivity to the Muto Twins (ditto) and MQTT servers. The address for the muto sandbox is: | ||
* The twin servers and API: http://sandbox.muto.ai | ||
* The mqtt server: mqtt://sandbox.muto.ai:1883 | ||
* The twin servers and API: https://sandbox.composiv.ai/ | ||
* The mqtt server: mqtt://sandbox.composiv.ai:1883 | ||
|
||
## Running agent | ||
|
||
The muto agent must be launched and the target device and the devices should have access to all the packages required to launch the stacks. Fo these purposes you can either choose to run a containerizedf version of muto or launch it direct from the devices after all the packages (such as the muto learning modules) are build and installed on the AV. | ||
The muto agent must be launched and the target device and the devices should have access to all the packages required to launch the stacks. For these purposes you can either choose to run a containerized version of muto or launch it direct from the devices after all the packages (such as the muto learning modules) are build and installed on the AV. | ||
|
||
```bash | ||
source devel/setup.bash | ||
roslaunch muto_agent agent.launch | ||
``` | ||
|
||
where agent.launch is: | ||
|
||
```xml | ||
<?xml version="1.0"?> | ||
<launch> | ||
<node pkg="muto_agent" name="muto_agent" type="muto_agent.py"> | ||
<rosparam command="load" file="$(find muto_agent)/params.yaml" /> | ||
</node> | ||
</launch> | ||
``` | ||
|
||
and params.yaml is: | ||
|
||
```yaml | ||
|
||
muto: | ||
nav_topic: /nav | ||
type: simulator | ||
twin_url: "http://ditto:[email protected]" | ||
mqtt: | ||
host: sandbox.composiv.ai | ||
port: 1883 | ||
keep_alive: 60 | ||
user: none | ||
password: none | ||
thing: | ||
namespace: ai.composiv.sandbox.f1tenth | ||
anonymous: False # Use this for automatically generated id (uuid based) | ||
# if anonymous is True or anynoymous param is missing, name/id will be auto generated | ||
name: simulator-monster-01 | ||
source install/setup.bash | ||
ros2 launch agent agent.launch | ||
``` | ||
|
||
## Twins | ||
There are two definition types for thins on the wtin server: | ||
* Stack - The model os the muto adaptive software stack that can be running on an AV | ||
- Thing definition id for stack is: ai.composiv.sandbox.f1tenth:Stack:1.0.0 | ||
* Vehicle - The device twin for the AV, where parameters, telemetry data and stack associations are managed | ||
- Thing definition id for vehicle is: ai.composiv.sandbox.f1tenth:TestCar:1.0.0 | ||
Examples of these definitions can be sampled by sending http rest requests to the sandbox server | ||
http://sandbox.composiv.ai. Muto Twin Server | ||
|
||
You can get stacks from twin server via:: | ||
```bash | ||
curl 'http://sandbox.composiv.ai/api/2/search/things?filter=eq(definition,"ai.composiv.sandbox.f1tenth:Stack:1.0.0")' | ||
curl 'link_to_stack_url' | ||
``` | ||
returns: | ||
which returns something similar to the below structure: | ||
|
||
```json | ||
{ | ||
"name": "Muto Learning Simulator with Gap Follwer", | ||
"context": "eteration_office", | ||
"stackId": "ai.composiv.sandbox.f1tenth:composir_simulator_gf.launch", | ||
"stackId": "org.eclipse.muto.sandbox:f1tenth-multiagent-gym.launch", | ||
"stack": [ | ||
{ | ||
"thingId": "ai.composiv.sandbox.f1tenth:composiv_simulator.launch" | ||
"thingId": "org.eclipse.muto.sandbox:racecar1.launch" | ||
} | ||
], | ||
"node": [ | ||
{ | ||
"name": "cass_gap_follower", | ||
"pkg": "cass_gap_follower", | ||
"exec": "cass_gap_follower", | ||
"name": "reactive_gap_follower", | ||
"pkg": "reactive_gap_follower", | ||
"exec": "reactive_gap_follower", | ||
"param": [ | ||
{ "from": "$(find cass_gap_follower)/params.yaml" } | ||
{ "from": "$(find reactive_gap_follower)/params.yaml" } | ||
] | ||
} | ||
] | ||
} | ||
``` | ||
|
||
This is a stack with a single node, "cass_gap_follower". However, it includes another stack (with many other nodes and parameters) that it requires with a stackId reference ai.composiv.sandbox.f1tenth:composiv_simulator.launch. The elements of the stack model resembles a [ROS launch XML](https://wiki.ros.org/roslaunch/XML), so it should be fairly straightforward to understand if you have experience with it. | ||
This is a stack with a single node, "cass_gap_follower". However, it includes another stack (with many other nodes and parameters) that it requires with a stackId reference org.eclipse.muto.sandbox:f1tenth-multiagent-gym.launch. The elements of the stack model resembles a [ROS launch XML](https://wiki.ros.org/roslaunch/XML), so it should be fairly straightforward to understand if you have experience writing XML launch files | ||
|
||
## Managing Stacks and Vehicles | ||
|
||
|
@@ -106,10 +66,10 @@ $ curl -X PUT -H "Content-Type: application/json" -d ' | |
{ | ||
"name": "Muto Learning Simulator with Gap Follower", | ||
"context": "eteration_office", | ||
"stackId": "ai.composiv.sandbox.f1tenth:composir_simulator_gf.launch", | ||
"stackId": "org.eclipse.muto.sandbox:composiv_simulator_gf.launch", | ||
"stack": [ | ||
{ | ||
"thingId": "ai.composiv.sandbox.f1tenth:composiv_simulator.launch" | ||
"thingId": "org.eclipse.muto.sandbox:composiv_simulator.launch" | ||
} | ||
], | ||
"node": [ | ||
|
@@ -123,24 +83,24 @@ $ curl -X PUT -H "Content-Type: application/json" -d ' | |
} | ||
] | ||
} | ||
' http://sandbox.composiv.ai/api/2/things/ai.composiv.sandbox.f1tenth:composiv_simulator_gf.launch | ||
' http://sandbox.composiv.ai/api/2/things/org.eclipse.muto.sandbox:composiv_simulator_gf.launch | ||
|
||
``` | ||
|
||
## Managing Stacks and Vehicles | ||
We can use the TWINS to directly communicating commands to the vehicle itself. The twin server supports special mqtt channels for these purposes called **twin** and **live** channels. For example the following command can be published to the sandbox MQTT server to activate a stack on a car. Each vehicle has its dedicated **twin** and **live** channels: | ||
|
||
```yaml | ||
topic: ai.composiv.sandbox.f1tenth:simulator-monster-01/stack/commands/active | ||
topic: org.eclipse.muto.sandbox::simulator-monster-01/stack/commands/active | ||
``` | ||
```yaml | ||
payload: { | ||
"name": "Muto Learning Simulator with Gap Follwer", | ||
"context": "eteration_office", | ||
"stackId": "ai.composiv.sandbox.f1tenth:composiv_simulator_gf.launch", | ||
"stackId": "org.eclipse.muto.sandbox::composiv_simulator_gf.launch", | ||
"stack": [ | ||
{ | ||
"thingId": "ai.composiv.sandbox.f1tenth:composiv_simulator.launch" | ||
"thingId": "org.eclipse.muto.sandbox::composiv_simulator.launch" | ||
} | ||
], | ||
"node": [ | ||
|
@@ -159,13 +119,16 @@ payload: { | |
You can use any open-source mqtt client to issue these commands and monitor various muto twin messages [MQTTX](https://mqttx.app/). Another option is the [mosquitto_pub](https://mosquitto.org/man/mosquitto_pub-1.html), which is a simple MQTT version 5/3.1.1 client that will publish a single message on a topic and exit. You can publish the message described above using the commandline: | ||
|
||
```bash | ||
mosquitto_pub -d -h sandbox.composiv.ai -p 1883 -t "ai.composiv.sandbox.f1tenth:simulator-monster-01/stack/commands/active" -m '{"name":"Composiv Learning Simulator with Gap Follwer","context":"eteration_office","stackId":"ai.composiv.sandbox.f1tenth:composiv_simulator_gf.launch","stack":[{"thingId":"ai.composiv.sandbox.f1tenth:composiv_simulator.launch"}],"node":[{"name":"cass_gap_follower","pkg":"cass_gap_follower","exec":"cass_gap_follower","param":[{"from":"$(find cass_gap_follower)/params.yaml"}]}]}' | ||
mosquitto_pub -d -h sandbox.composiv.ai -p 1883 -t "org.eclipse.muto.sandbox::simulator-monster-01/stack/commands/active" -m '{"name":"Composiv Learning Simulator with Gap Follwer","context":"eteration_office","stackId":"org.eclipse.muto.sandbox::composiv_simulator_gf.launch","stack":[{"thingId":"org.eclipse.muto.sandbox::composiv_simulator.launch"}],"node":[{"name":"cass_gap_follower","pkg":"cass_gap_follower","exec":"cass_gap_follower","param":[{"from":"$(find cass_gap_follower)/params.yaml"}]}]}' | ||
|
||
``` | ||
|
||
|
||
## Controlling the F1Tenth Car (navigate on/off) | ||
|
||
```bash | ||
rostopic pub --once /mux std_msgs/Int32MultiArray "{layout: { dim: [], data_offset: 0}, data: [0, 0, 0, 0, 1 , 0] }" | ||
ros2 topic pub --once /mux std_msgs/Int32MultiArray "{layout: { dim: [], data_offset: 0}, data: [0, 0, 0, 0, 1 , 0] }" | ||
``` | ||
|
||
## More information | ||
Check out the Eclipse Muto github.io page for further reading: [Eclipse Muto](https://eclipse-muto.github.io/docs/docs/muto) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# | ||
# Copyright (c) 2023 Composiv.ai, Eteration A.S. and others | ||
# | ||
# All rights reserved. This program and the accompanying materials | ||
# are made available under the terms of the Eclipse Public License v2.0 | ||
# and Eclipse Distribution License v1.0 which accompany this distribution. | ||
# | ||
# The Eclipse Public License is available at | ||
# http://www.eclipse.org/legal/epl-v10.html | ||
# and the Eclipse Distribution License is available at | ||
# http://www.eclipse.org/org/documents/edl-v10.php. | ||
# | ||
# Contributors: | ||
# Composiv.ai, Eteration A.S. - initial API and implementation | ||
# | ||
|
||
import os | ||
import yaml | ||
import json | ||
import rclpy | ||
from rclpy.node import Node | ||
|
||
from ament_index_python.packages import get_package_share_directory | ||
from composer.stack import Stack | ||
from composer.twin import Twin | ||
from composer.edge_device import EdgeDevice | ||
from muto_msgs.srv import ComposePlugin | ||
from muto_msgs.msg import PluginResponse, StackManifest, PlanManifest | ||
|
||
|
||
class MutoDefaultComposePlugin(Node): | ||
def __init__(self): | ||
super().__init__("compose_plugin") | ||
|
||
self.declare_parameter("name", "example-01") | ||
self.declare_parameter("namespace", "org.eclipse.muto.sandbox") | ||
self.declare_parameter("stack_topic", "stack") | ||
self.declare_parameter("twin_topic", "twin") | ||
self.declare_parameter("anonymous", False) | ||
self.declare_parameter( | ||
"twin_url", "http://ditto:[email protected]") | ||
|
||
self.name = self.get_parameter("name").value | ||
self.namespace = self.get_parameter("namespace").value | ||
self.stack_topic = self.get_parameter("stack_topic").value | ||
self.twin_topic = self.get_parameter("twin_topic").value | ||
self.twin_url = self.get_parameter("twin_url").value | ||
self.anonymous = self.get_parameter("anonymous").value | ||
|
||
self.muto = { | ||
"name": self.name, | ||
"namespace": self.namespace, | ||
"stack_topic": self.stack_topic, | ||
"twin_topic": self.twin_topic, | ||
"twin_url": self.twin_url, | ||
"anonymous": self.anonymous | ||
} | ||
|
||
self.srv = self.create_service( | ||
ComposePlugin, "muto_compose", self.handle_compose | ||
) | ||
|
||
self.twin = Twin(node='muto_compose_plugin', | ||
config=self.muto, publisher=None) | ||
self.edge_device = EdgeDevice(twin=self.twin) | ||
|
||
def handle_compose(self, req, res): | ||
plan = req.input | ||
|
||
st = json.loads(plan.current.stack) | ||
current_stack = Stack(self.edge_device, st, None) | ||
st = json.loads(plan.next.stack) | ||
|
||
if st.get('stackId', None) is not None: | ||
manifest = self.twin.stack(st['stackId']) | ||
nextStack = Stack(self.edge_device, manifest, None) | ||
else: | ||
nextStack = Stack(self.edge_device, st, None) | ||
|
||
merged = current_stack.merge(nextStack) | ||
|
||
res.output = PlanManifest( | ||
current=plan.current, | ||
next=plan.next, | ||
pipeline=plan.pipeline, | ||
planned=StackManifest( | ||
type="json", | ||
stack=json.dumps(merged.manifest) | ||
), | ||
result=PluginResponse( | ||
result_code=0, error_message="", error_description="" | ||
) | ||
) | ||
return res | ||
|
||
|
||
def main(args=None): | ||
rclpy.init(args=args) | ||
node = MutoDefaultComposePlugin() | ||
rclpy.spin(node) | ||
node.destroy_node() | ||
rclpy.shutdown() | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.