diff --git a/mars_rover/CMakeLists.txt b/mars_rover/CMakeLists.txt index c2c90051..cf80b88b 100644 --- a/mars_rover/CMakeLists.txt +++ b/mars_rover/CMakeLists.txt @@ -44,7 +44,8 @@ install(PROGRAMS nodes/move_arm nodes/move_mast nodes/move_wheel - nodes/run_demo + nodes/run_demo # To run the Gazebo rover demo + nodes/teleop_rover # To run O3DE rover demo nodes/odom_tf_publisher DESTINATION lib/${PROJECT_NAME} ) diff --git a/mars_rover/launch/mars_rover_o3de.launch.py b/mars_rover/launch/mars_rover_o3de.launch.py new file mode 100644 index 00000000..e465867d --- /dev/null +++ b/mars_rover/launch/mars_rover_o3de.launch.py @@ -0,0 +1,212 @@ +""" +Bring up nodes, hardware interfaces to control a Curiosity Rover in Open 3D Engine. + +Author: +Azmyin Md. Kamal, +Ph.D. student in MIE, +Louisiana State University, +Louisiana, USA + +Date: August 29th, 2024 +Version: 1.0 + +AI: ChatGPT 4.o + +""" + +# Imports +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import ExecuteProcess, RegisterEventHandler +from launch_ros.actions import Node, SetParameter +from launch.event_handlers import OnProcessExit +import os +from os import environ +import xacro + +def generate_launch_description(): + """Generate launch description to bringup curiosity rover simulation.""" + # Define paths to mars_rover and simulation packages + mars_rover_demos_path = get_package_share_directory('mars_rover') + mars_rover_models_path = get_package_share_directory('simulation') + # Define + env = {'IGN_GAZEBO_SYSTEM_PLUGIN_PATH': + ':'.join([environ.get('IGN_GAZEBO_SYSTEM_PLUGIN_PATH', default=''), + environ.get('LD_LIBRARY_PATH', default='')]), + 'IGN_GAZEBO_RESOURCE_PATH': + ':'.join([environ.get('IGN_GAZEBO_RESOURCE_PATH', default=''), mars_rover_demos_path])} + + urdf_model_path = os.path.join(mars_rover_models_path, 'models', 'curiosity_path', + 'urdf', 'curiosity_mars_rover.xacro') + + mars_world_model = os.path.join(mars_rover_demos_path, 'worlds', 'mars_curiosity.world') + + doc = xacro.process_file(urdf_model_path) + robot_description = {'robot_description': doc.toxml()} + + # Arm + # arm_node = Node( + # package="mars_rover", + # executable="move_arm", + # output='screen' + # ) + # Sensor mast + # mast_node = Node( + # package="mars_rover", + # executable="move_mast", + # output='screen' + # ) + # Wheel groups + wheel_node = Node( + package="mars_rover", + executable="move_wheel", + output='screen' + ) + # Node to take teleop + teleop_rover_node = Node( + package="mars_rover", + executable="teleop_rover", + output='screen' + ) + # Publish odometry + # odom_node = Node( + # package="mars_rover", + # executable="odom_tf_publisher", + # output='screen' + # ) + + # Fire up Gazebo Ignition + start_world = ExecuteProcess( + cmd=['ign gazebo', mars_world_model, '-r'], + output='screen', + additional_env=env, + shell=True + ) + # Publish various joint positions and link orientation + # This is crucial for simulation + robot_state_publisher = Node( + package='robot_state_publisher', + executable='robot_state_publisher', + name='robot_state_publisher', + output='screen', + parameters=[robot_description]) + # Bridge communication between ROS 2 and the Ignition Gazebo simulation + ros_gz_bridge = Node( + package='ros_gz_bridge', + executable='parameter_bridge', + arguments=[ + '/clock@rosgraph_msgs/msg/Clock[ignition.msgs.Clock', + '/model/curiosity_mars_rover/odometry@nav_msgs/msg/Odometry@ignition.msgs.Odometry', + '/scan@sensor_msgs/msg/LaserScan@ignition.msgs.LaserScan', + ], + output='screen') + # Connect image messages from Gazebo to ROS2 + image_bridge = Node( + package='ros_gz_image', + executable='image_bridge', + arguments=['/image_raw', '/image_raw'], + output='screen') + # Spawn curiosity rover into the world. + spawn = Node( + package='ros_ign_gazebo', executable='create', + arguments=[ + '-name', 'curiosity_mars_rover', + '-topic', robot_description, + '-z', '-7.5' + ], + output='screen' + ) + + # Control Components + component_state_msg = '{name: "IgnitionSystem", target_state: {id: 3, label: ""}}' + + # TODO what bug was resolved with this hack? + # Set hardware_interface state to active + set_hardware_interface_active = ExecuteProcess( + cmd=['ros2', 'service', 'call', + 'controller_manager/set_hardware_component_state', + 'controller_manager_msgs/srv/SetHardwareComponentState', + component_state_msg] + ) + + # Controller to broadcast all joint states + load_joint_state_broadcaster = ExecuteProcess( + cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', + 'joint_state_broadcaster'], + output='screen' + ) + + # Controller for arm + load_arm_joint_traj_controller = ExecuteProcess( + cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', + 'arm_joint_trajectory_controller'], + output='screen' + ) + + # Controller for sensor mast + load_mast_joint_traj_controller = ExecuteProcess( + cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', + 'mast_joint_trajectory_controller'], + output='screen' + ) + + # Controller for wheel + load_wheel_joint_traj_controller = ExecuteProcess( + cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', + 'wheel_velocity_controller'], + output='screen' + ) + # Controller for steering + load_steer_joint_traj_controller = ExecuteProcess( + cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', + 'steer_position_controller'], + output='screen' + ) + # Controller for suspension joints + load_suspension_joint_traj_controller = ExecuteProcess( + cmd=['ros2', 'control', 'load_controller', '--set-state', 'active', + 'wheel_tree_position_controller'], + output='screen' + ) + + return LaunchDescription([ + SetParameter(name='use_sim_time', value=True), + #start_world, + #robot_state_publisher, + #spawn, + # arm_node, + # mast_node, + wheel_node, + teleop_rover_node, # Renamed from run_node + # odom_node, + #ros_gz_bridge, + #image_bridge, + + RegisterEventHandler( + OnProcessExit( + target_action=spawn, + on_exit=[set_hardware_interface_active], + ) + ), + # After the hardware interface is activated, + # the joint state broadcaster is loaded. + RegisterEventHandler( + OnProcessExit( + target_action=set_hardware_interface_active, + on_exit=[load_joint_state_broadcaster], + ) + ), + # After the joint state broadcaster is loaded, + # all trajectory controllers (arm, mast, wheel, steer, suspension) are loaded and activated. + RegisterEventHandler( + OnProcessExit( + target_action=load_joint_state_broadcaster, + on_exit=[ + # load_arm_joint_traj_controller, + # load_mast_joint_traj_controller, + load_wheel_joint_traj_controller, + load_steer_joint_traj_controller, + load_suspension_joint_traj_controller], + ) + ), + ]) diff --git a/mars_rover/nodes/teleop_rover b/mars_rover/nodes/teleop_rover new file mode 100755 index 00000000..e5c6d2d1 --- /dev/null +++ b/mars_rover/nodes/teleop_rover @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 + +""" +Implementation of the TeleOpRover class. + +This node acts as an interface between user sent service call to publishing +twist message that is then subscribed too by the controller + +Primary author: +Space-ROS + +Docstrings and comments added by: +Azmyin Md. Kamal, +Ph.D. student in MIE, iCORE Lab, +Louisiana State University, Louisiana, USA + +Date: August 29th, 2024 +Version: 1.0 +AI: ChatGPT 4.o + +""" + +# Imports +import rclpy +from rclpy.node import Node + +# from std_msgs.msg import String, Float64MultiArray +from geometry_msgs.msg import Twist + +# import math +# from random import randint +from std_srvs.srv import Empty + +class TeleOpRover(Node): + """Node that converts user's service request / input device commands to Twist messages.""" + + def __init__(self) -> None: + super().__init__('teleop_node') + # Setup publishers + self.motion_publisher_ = self.create_publisher(Twist, '/cmd_vel', 10) + self.o3de_motion_publisher_ = self.create_publisher(Twist, '/rover/cmd_vel', 10) + # Setup services + self.forward_srv = self.create_service(Empty, 'move_forward', self.move_forward_callback) + self.stop_srv = self.create_service(Empty, 'move_stop', self.move_stop_callback) + self.left_srv = self.create_service(Empty, 'turn_left', self.turn_left_callback) + self.right_srv = self.create_service(Empty, 'turn_right', self.turn_right_callback) + self.stopped = True + timer_period = 0.1 + self.timer = self.create_timer(timer_period, self.timer_callback) + self.curr_action = Twist() + + def timer_callback(self): + """Periodically publish velocity of rover in 3D space as Twist messages.""" + if (not self.stopped): + # Experimental + self.o3de_motion_publisher_.publish(self.curr_action) + # self.motion_publisher_.publish(self.curr_action) + + + def move_forward_callback(self, request, response): + """Print message when moving forward.""" + self.get_logger().info("Moving forward") + action = Twist() + # action.linear.x = 2.0 + action.linear.x = 2.0 # Not sure but negative value makes it move forward + self.curr_action = action + self.stopped = False + return response + + def move_stop_callback(self, request, response): + """Print message when stopped.""" + # stop timer from publishing + self.stopped = True + self.get_logger().info("Stopping") + self.curr_action = Twist() + # publish once to ensure we stop + self.motion_publisher_.publish(self.curr_action) + self.o3de_motion_publisher_.publish(self.curr_action) + return response + + def turn_left_callback(self, request, response): + """Print message when turning left.""" + self.get_logger().info("Turning left") + action = Twist() + action.linear.x = 1.0 + action.angular.z = 0.4 + self.curr_action = action + self.stopped = False + return response + + def turn_right_callback(self, request, response): + """Print message when turning right.""" + self.get_logger().info("Turning right") + self.stopped = False + action = Twist() + #action.linear.x = 1.0 + action.linear.x = 0.5 + action.angular.z = -1.5 + self.curr_action = action + self.stopped = False + return response + +def main(args=None): + """Run main.""" + rclpy.init(args=args) + teleop_node = TeleOpRover() + rclpy.spin(teleop_node) + # Destroy the node explicitly + # (optional - otherwise it will be done automatically + # when the garbage collector destroys the node object) + teleop_node.destroy_node() + rclpy.shutdown() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/o3de_mars_rover/DockerFile_O3DE_sample.txt b/o3de_mars_rover/DockerFile_O3DE_sample.txt new file mode 100644 index 00000000..eb8db8f5 --- /dev/null +++ b/o3de_mars_rover/DockerFile_O3DE_sample.txt @@ -0,0 +1,149 @@ +# Dockerfile based on https://gist.github.com/michalpelka/a571f914bf5c9822935f2654e45811ec + +ARG ROS_DISTRO=humble + +FROM husarnet/ros:${ROS_DISTRO}-ros-core + +ENV O3DE_HASH=52084aee31172c0202a1de120714e811c29dd3b7 +ENV O3DE_EXTRAS_HASH=3464657cd21c324ed90332a98a140e65e25fd942 +ENV PROJECT_NAME=ROSbotXLDemo + +ENV WORKDIR=/data/workspace +WORKDIR $WORKDIR + +ARG DEBIAN_FRONTEND=noninteractive + +# Setup time zone and locale data (necessary for SSL and HTTPS packages) +RUN apt-get update && DEBIAN_FRONTEND="noninteractive" apt-get -y \ + install \ + tzdata \ + locales \ + keyboard-configuration \ + && rm -rf /var/lib/apt/lists/* + +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ + && dpkg-reconfigure --frontend=noninteractive locales \ + && update-locale LANG=en_US.UTF-8 + +ENV LANG=en_US.UTF-8 + +# Install common tools +# deps in https://github.com/o3de/o3de/blob/development/scripts/build/build_node/Platform/Linux/package-list.ubuntu-jammy.txt +RUN apt-get update && apt-get install -y \ + bc \ + bind9-utils \ + binutils \ + ca-certificates \ + clang \ + cmake \ + file \ + firewalld \ + git \ + git-lfs \ + jq \ + kbd \ + kmod \ + less \ + lsb-release \ + libglu1-mesa-dev \ + libxcb-xinerama0 \ + libfontconfig1-dev \ + libcurl4-openssl-dev \ + libnvidia-gl-470 \ + libssl-dev \ + libxcb-xkb-dev \ + libxkbcommon-x11-dev \ + libxkbcommon-dev \ + libxcb-xfixes0-dev \ + libxcb-xinput-dev \ + libxcb-xinput0 \ + libpcre2-16-0 \ + lsof \ + net-tools \ + ninja-build \ + pciutils \ + python3-pip \ + software-properties-common \ + sudo \ + tar \ + unzip \ + vim \ + wget \ + xz-utils \ + && rm -rf /var/lib/apt/lists/* + +# Gem + ROS pacakges +RUN apt-get update && apt-get install -y \ + ros-$ROS_DISTRO-ackermann-msgs \ + ros-$ROS_DISTRO-control-toolbox \ + ros-$ROS_DISTRO-gazebo-msgs \ + ros-$ROS_DISTRO-joy \ + ros-$ROS_DISTRO-navigation2 \ + ros-$ROS_DISTRO-rviz2 \ + ros-$ROS_DISTRO-tf2-ros \ + ros-$ROS_DISTRO-urdfdom \ + ros-$ROS_DISTRO-vision-msgs \ + && rm -rf /var/lib/apt/lists/* + +## Symlink clang version to non-versioned clang and set cc to clang +RUN update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100 \ + && update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100 + +# Install o3de +RUN git clone https://github.com/o3de/o3de.git \ + && cd o3de \ + && git checkout ${O3DE_HASH} \ + && git lfs install \ + && git lfs pull \ + && python/get_python.sh + +# Install o3de-extras +RUN git clone https://github.com/o3de/o3de-extras.git \ + && cd o3de-extras \ + && git checkout ${O3DE_EXTRAS_HASH} \ + && git lfs install \ + && git lfs pull + +# regiester engine and Gems from o3de-extras +RUN ./o3de/scripts/o3de.sh register --this-engine \ + && ./o3de/scripts/o3de.sh register --gem-path ./o3de-extras/Gems/ROS2 \ + && ./o3de/scripts/o3de.sh register --gem-path ./o3de-extras/Gems/RosRobotSample \ + && ./o3de/scripts/o3de.sh register --gem-path ./o3de-extras/Gems/WarehouseSample + +# create in project from template in o3de-extras +RUN ./o3de/scripts/o3de.sh create-project \ + --project-path ${WORKDIR}/${PROJECT_NAME} \ + --template-path ./o3de-extras/Templates/Ros2ProjectTemplate/ -f + +WORKDIR ${WORKDIR}/${PROJECT_NAME} + +RUN . /opt/ros/$ROS_DISTRO/setup.sh \ + && cmake -B build/linux -S . -G "Ninja Multi-Config" -DLY_STRIP_DEBUG_SYMBOLS=ON + +RUN . /opt/ros/$ROS_DISTRO/setup.sh \ + && cmake --build build/linux --config profile --target ${PROJECT_NAME} Editor AssetProcessor + +# This final step takes long since they Assets will be downloading +RUN . /opt/ros/$ROS_DISTRO/setup.sh \ + && echo "This final step can take more than 1 hour. Good time for going for a coffee :)" \ + && cmake --build build/linux --config profile --target ${PROJECT_NAME}.Assets + +# Installing some ros2 for navigation +RUN apt-get update && apt-get install -y \ + python3-colcon-common-extensions \ + ros-$ROS_DISTRO-cyclonedds \ + ros-$ROS_DISTRO-rmw-cyclonedds-cpp \ + ros-$ROS_DISTRO-slam-toolbox \ + ros-$ROS_DISTRO-navigation2 \ + ros-$ROS_DISTRO-nav2-bringup \ + ros-$ROS_DISTRO-pointcloud-to-laserscan \ + ros-$ROS_DISTRO-teleop-twist-keyboard \ + ros-$ROS_DISTRO-ackermann-msgs \ + ros-$ROS_DISTRO-topic-tools \ + && rm -rf /var/lib/apt/lists/* + +RUN pip install python-statemachine + +WORKDIR $WORKDIR + +ENV RMW_IMPLEMENTATION=rmw_cyclonedds_cpp \ No newline at end of file diff --git a/o3de_mars_rover/Dockerfile b/o3de_mars_rover/Dockerfile new file mode 100644 index 00000000..2d13dc08 --- /dev/null +++ b/o3de_mars_rover/Dockerfile @@ -0,0 +1,320 @@ +# Copyright 2024 Azmyin Md. Kamal +# +# 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. +# +# A Docker configuration script to build the o3de_curiosit_docker image that showcases Open 3D Engine +# in simulating a Curiositry rover traversing through a test ground inspired by the NASA JPL Mars Yard +# O3DE docker file based on https://github.com/husarion/o3de-docker/blob/main/Dockerfile +# +# +# The script provides the following build arguments: +# +# VCS_REF - The git revision of the Space ROS source code (no default value). +# VERSION - The version of Space ROS (default: "preview") + +FROM openrobotics/moveit2:latest + +# Define arguments used in the metadata definition +ARG VCS_REF +ARG VERSION="preview" +ARG ROS_DISTRO=humble + +# Specify the docker image metadata +LABEL org.label-schema.schema-version="1.0" +LABEL org.label-schema.name="O3DE Curiosity Rover" +LABEL org.label-schema.description="Curiosity rover demo on a new test enviornment on the Space ROS platform and Open 3D Engine" +LABEL org.label-schema.vendor="Nasa Space ROS Sim Summer Spring Challenge 2024" +LABEL org.label-schema.version=${VERSION} +LABEL org.label-schema.url="https://github.com/space-ros" +LABEL org.label-schema.vcs-url="https://github.com/Mechazo11/space-ros-docker" +LABEL org.label-schema.vcs-ref=${VCS_REF} + +# Define a key enviornment variables +ENV DEMO_DIR=${HOME_DIR}/demos_ws +ENV IGNITION_VERSION fortress +ENV GZ_VERSION fortress +ENV PROJECT_NAME=RobotSim +ENV O3DE_ENGINE=${HOME_DIR}/o3de +ENV O3DE_DIR=${HOME_DIR}/O3DE +ENV O3DE_EXTRAS=${HOME_DIR}/o3de-extras +ENV PROJECT_PATH=${O3DE_DIR}/Projects/${PROJECT_NAME} + +# Disable prompting during package installation +ARG DEBIAN_FRONTEND=noninteractive +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=Etc/UTC + +#### Install DEMO_WS #### + +# Get rosinstall_generator +# Using Docker BuildKit cache mounts for /var/cache/apt and /var/lib/apt ensures that +# the cache won't make it into the built image but will be maintained between steps. +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sudo apt-get update -y && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ + python3-rosinstall-generator \ + libboost-python-dev build-essential cmake libboost-all-dev libois-dev \ + libzzip-dev libfreeimage-dev libfreetype6-dev libx11-dev libxt-dev libxaw7-dev \ + libsdl2-dev libpugixml-dev libglew-dev qtbase5-dev libspdlog-dev libfmt-dev \ + libignition-gazebo6-dev libssl-dev devscripts debian-keyring fakeroot debhelper \ + libboost-dev libsasl2-dev libicu-dev libzstd-dev doxygen libtinyxml-dev \ + libtinyxml2-dev python3-pyqt5 tzdata locales keyboard-configuration + +# RUN apt-get install -y tzdata +# RUN apt-get install -y locales +# RUN apt-get install -y keyboard-configuration + +RUN sudo sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ + && sudo dpkg-reconfigure --frontend=noninteractive locales \ + && sudo update-locale LANG=en_US.UTF-8 + +# RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ +# && dpkg-reconfigure --frontend=noninteractive locales \ +# && update-locale LANG=en_US.UTF-8 + +ENV LANG=en_US.UTF-8 + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sudo apt-get update -y && sudo apt-get install -y \ + bc \ + bind9-utils \ + binutils \ + ca-certificates \ + clang \ + cmake \ + file \ + firewalld \ + git \ + git-lfs \ + jq \ + kbd \ + kmod \ + less \ + lsb-release \ + libglu1-mesa-dev \ + libxcb-xinerama0 \ + libfontconfig1-dev \ + libcurl4-openssl-dev \ + libnvidia-gl-470 \ + libssl-dev \ + libxcb-xkb-dev \ + libxkbcommon-x11-dev \ + libxkbcommon-dev \ + libxcb-xfixes0-dev \ + libxcb-xinput-dev \ + libxcb-xinput0 \ + libpcre2-16-0 \ + lsof \ + net-tools \ + ninja-build \ + pciutils \ + python3-pip \ + software-properties-common \ + sudo \ + tar \ + unzip \ + vim \ + wget \ + xz-utils + # && rm -rf /var/lib/apt/lists/* # TODO need to figure out how to use this correctly + + +RUN mkdir -p ${DEMO_DIR}/src +WORKDIR ${DEMO_DIR} + +# Install libmongoc for development +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sudo apt-get install libmongoc-dev -y + +# Compile mongo cxx driver https://mongocxx.org/mongocxx-v3/installation/linux/ +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sudo apt-get install libssl-dev build-essential devscripts debian-keyring fakeroot debhelper cmake libboost-dev libsasl2-dev libicu-dev libzstd-dev doxygen -y +RUN wget https://github.com/mongodb/mongo-cxx-driver/releases/download/r3.6.7/mongo-cxx-driver-r3.6.7.tar.gz +RUN tar -xzf mongo-cxx-driver-r3.6.7.tar.gz +RUN cd mongo-cxx-driver-r3.6.7/build && cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local && sudo cmake --build . --target EP_mnmlstc_core && cmake --build . && sudo cmake --build . --target install + +# Get the source for the dependencies +# RUN vcs import src < /tmp/demo_generated_pkgs.repos +COPY --chown=${USERNAME}:${USERNAME} o3de-robot-sim.repos /tmp/ +RUN vcs import src < /tmp/o3de-robot-sim.repos && /bin/bash -c 'source "${SPACEROS_DIR}/install/setup.bash"' + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sudo apt-get update -y \ +&& /bin/bash -c 'source "${SPACEROS_DIR}/install/setup.bash"' \ +&& /bin/bash -c 'source "${MOVEIT2_DIR}/install/setup.bash"' \ +&& rosdep install --from-paths src --ignore-src -r -y --rosdistro ${ROSDISTRO} + +# Build the demo_ws +RUN /bin/bash -c 'source ${SPACEROS_DIR}/install/setup.bash && source ${MOVEIT2_DIR}/install/setup.bash \ + && colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release' + +# Create O3DE/Projects and O3DE/Gems directory +RUN if [ -d "${O3DE_DIR}/Projects" ]; then rm -rf ${O3DE_DIR}/Gems; fi +RUN mkdir -p ${O3DE_DIR}/Projects + +RUN if [ -d "${O3DE_DIR}/Gems" ]; then rm -rf ${O3DE_DIR}/Gems; fi +RUN mkdir -p ${O3DE_DIR}/Gems + +# Git clone RobotSim, NasaMarsRoverGem and MarsYardGem +WORKDIR ${O3DE_DIR}/Projects +RUN git clone --branch nasa_submission https://github.com/Mechazo11/RobotSim.git + +WORKDIR ${O3DE_DIR}/Gems +RUN git clone --branch nasa_submission https://github.com/Mechazo11/NasaCuriosityRoverGem.git +RUN git clone --branch nasa_submission https://github.com/Mechazo11/MarsYardGem.git + +## Symlink clang version to non-versioned clang and set cc to clang +# RUN update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100 \ +# && update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100 + +#### Install Open 3D Engine #### +# Install dependencies +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sudo apt-get update -y && sudo apt-get install -y \ + bc \ + bind9-utils \ + binutils \ + ca-certificates \ + clang \ + cmake \ + file \ + firewalld \ + git \ + git-lfs \ + jq \ + kbd \ + kmod \ + less \ + lsb-release \ + libglu1-mesa-dev \ + libxcb-xinerama0 \ + libfontconfig1-dev \ + libcurl4-openssl-dev \ + libnvidia-gl-470 \ + libssl-dev \ + libxcb-xkb-dev \ + libxkbcommon-x11-dev \ + libxkbcommon-dev \ + libxcb-xfixes0-dev \ + libxcb-xinput-dev \ + libxcb-xinput0 \ + libpcre2-16-0 \ + lsof \ + net-tools \ + ninja-build \ + pciutils \ + python3-pip \ + software-properties-common \ + sudo \ + tar \ + unzip \ + vim \ + wget \ + xz-utils + # && rm -rf /var/lib/apt/lists/* # TODO need to figure out how to use this correctly + +# Pull latest commit from development and build o3de. Note this does't build the whole engine +WORKDIR ${HOME_DIR} + +# Install o3de engine (automatically pulls last commit from "development" branch) +RUN git clone --single-branch -b development https://github.com/o3de/o3de.git \ + && cd o3de \ + && git lfs install \ + && git lfs pull \ + && python/get_python.sh + +# Install o3de-extras (automatically pulls last commit from "development" branch) +# Contains ROS 2 Gem and other relevant assets + +WORKDIR ${HOME_DIR} +RUN git clone --single-branch -b development https://github.com/o3de/o3de-extras.git \ + && cd o3de-extras \ + && git lfs install \ + && git lfs pull + +WORKDIR ${HOME_DIR}/o3de + +# Register RobotSim with this engine +#RUN ${O3DE_ENGINE}/scripts/o3de.sh register --this-engine +RUN ./scripts/o3de.sh register --this-engine +# Register ROS 2 Gem, Husarion robot, Curiosity rover and Mars Yard gem +# RUN ${O3DE_ENGINE}/scripts/o3de.sh register --gem-path ${O3DE_EXTRAS}/Gems/ROS2 \ +# && ${O3DE_ENGINE}/scripts/o3de.sh register --gem-path ${O3DE_EXTRAS}/Gems/RosRobotSample \ +# && ${O3DE_ENGINE}/scripts/o3de.sh register --gem-path ${O3DE_DIR}/Gems/NasaCuriosityRoverGem \ +# && ${O3DE_ENGINE}/scripts/o3de.sh register --gem-path ${O3DE_DIR}/Gems/MarsYardGem + +RUN ./scripts/o3de.sh register --gem-path ${O3DE_EXTRAS}/Gems/ROS2 \ + && ./scripts/o3de.sh register --gem-path ${O3DE_EXTRAS}/Gems/RosRobotSample \ + && ./scripts/o3de.sh register --gem-path ${O3DE_EXTRAS}/Gems/WarehouseSample \ + && ./scripts/o3de.sh register --gem-path ${O3DE_DIR}/Gems/NasaCuriosityRoverGem \ + && ./scripts/o3de.sh register --gem-path ${O3DE_DIR}/Gems/MarsYardGem + +# Register the Terrian gem which is located in o3de folder +RUN ./scripts/o3de.sh register --gem-path ${HOME_DIR}/o3de/Gems/Terrain + +# Register RobotSim project. +# Project must be registered at the very end after all dependent gems are registered +#RUN {O3DE_ENGINE}/scripts/o3de.sh register --project-path ${O3DE_DIR}/Projects/${PROJECT_NAME} +RUN ./scripts/o3de.sh register --project-path ${O3DE_DIR}/Projects/${PROJECT_NAME} + +# Move to project directory +WORKDIR ${HOME_DIR} +# Run cmake and build project (Warning takes about 10-15 mins) + +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ + --mount=type=cache,target=/var/lib/apt,sharing=locked \ + sudo apt-get update -y && sudo apt-get install -y \ + libunwind-dev + +# Testing build by manually building out a ROS 2 Humble core +# RUN sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg + +# RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ +# --mount=type=cache,target=/var/lib/apt,sharing=locked \ +# sudo apt-get update -y && sudo apt-get install -y \ +# ros-humble-ros-base + +# # Move to project directory +WORKDIR ${PROJECT_PATH} + +# Activate Cyclone DDS +# ENV RMW_IMPLEMENTATION=rmw_cyclonedds_cpp + +# Source space_ros, movit2 and demo_ws +RUN /bin/bash -c 'source "${SPACEROS_DIR}/install/setup.bash"' \ + && /bin/bash -c 'source "${MOVEIT2_DIR}/install/setup.bash"' \ + && /bin/bash -c 'source "${DEMO_DIR}/install/setup.bash"' + #&& cmake -B build/linux -G "Ninja Multi-Config" -DLY_DISABLE_TEST_MODULES=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DLY_STRIP_DEBUG_SYMBOLS=ON -DAZ_USE_PHYSX5:BOOL=ON \ + #&& cmake --build build/linux --config profile --target ${PROJECT_NAME} Editor ${PROJECT_NAME}.Assets + +#RUN /bin/bash -c 'source "/opt/ros/humble/setup.bash"' + +RUN cmake -B build/linux -G "Ninja Multi-Config" -DLY_DISABLE_TEST_MODULES=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DLY_STRIP_DEBUG_SYMBOLS=ON -DAZ_USE_PHYSX5:BOOL=ON \ + && cmake --build build/linux --config profile --target ${PROJECT_NAME} Editor ${PROJECT_NAME}.Assets + + + + +# # Add the user to the render group so that the user can access /dev/dri/renderD128 +# # /dev/dri/renderD128 gives access to hardware-accelerated rendering tool such as GPU +# RUN sudo usermod -aG render $USERNAME + +# # Setup the entrypoint +# COPY ./entrypoint.sh / +# ENTRYPOINT ["/entrypoint.sh"] +# CMD ["bash"] diff --git a/o3de_mars_rover/build.sh b/o3de_mars_rover/build.sh new file mode 100755 index 00000000..6f8e47df --- /dev/null +++ b/o3de_mars_rover/build.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +ORG=openrobotics +IMAGE=o3de_curiosity_docker +TAG=latest + +VCS_REF="" +VERSION=preview + +# Exit script with failure if build fails +set -eo pipefail + +echo "" +echo "##### Building O3DE + Space ROS Demo Docker Image #####" +echo "" + +docker build -t $ORG/$IMAGE:$TAG \ + --build-arg VCS_REF="$VCS_REF" \ + --build-arg VERSION="$VERSION" . + +echo "" +echo "##### Done! #####" +