initial commit
This commit is contained in:
commit
c7e1e82b42
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/ros2
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=ros2
|
||||
|
||||
### ROS2 ###
|
||||
install/
|
||||
log/
|
||||
build/
|
||||
|
||||
# Ignore generated docs
|
||||
*.dox
|
||||
*.wikidoc
|
||||
|
||||
# eclipse stuff
|
||||
.project
|
||||
.cproject
|
||||
|
||||
# qcreator stuff
|
||||
CMakeLists.txt.user
|
||||
|
||||
srv/_*.py
|
||||
*.pcd
|
||||
*.pyc
|
||||
qtcreator-*
|
||||
*.user
|
||||
|
||||
*~
|
||||
|
||||
# Emacs
|
||||
.#*
|
||||
|
||||
# Colcon custom files
|
||||
COLCON_IGNORE
|
||||
AMENT_IGNORE
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/ros2
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "src/Groot"]
|
||||
path = src/Groot
|
||||
url = https://github.com/BehaviorTree/Groot.git
|
||||
4
build.sh
Executable file
4
build.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
pushd "$(dirname "$0")"
|
||||
colcon build --event-handlers console_cohesion+ --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja
|
||||
popd
|
||||
1
src/Groot
Submodule
1
src/Groot
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 05fe640172e3cd447ab5db31f71355789f6a48b3
|
||||
42
src/btree_nodes/CMakeLists.txt
Normal file
42
src/btree_nodes/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
cmake_minimum_required(VERSION VERSION 3.5.1)
|
||||
project(btree_nodes)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# find dependencies
|
||||
|
||||
find_package(ament_cmake REQUIRED)
|
||||
find_package(rclcpp REQUIRED)
|
||||
find_package(geometry_msgs REQUIRED)
|
||||
find_package(behaviortree_cpp_v3 REQUIRED)
|
||||
# uncomment the following section in order to fill in
|
||||
# further dependencies manually.
|
||||
# find_package(<dependency> REQUIRED)
|
||||
|
||||
add_executable(tree src/Tree.cpp)
|
||||
ament_target_dependencies(tree geometry_msgs behaviortree_cpp_v3 rclcpp)
|
||||
|
||||
#add_executable(talker src/publisher_member_function.cpp)
|
||||
#ament_target_dependencies(talker geometry_msgs rclcpp)
|
||||
#add_executable(listener src/subscriber_member_function.cpp)
|
||||
#ament_target_dependencies(listener geometry_msgs rclcpp)
|
||||
|
||||
install(TARGETS
|
||||
tree
|
||||
DESTINATION lib/${PROJECT_NAME})
|
||||
|
||||
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()
|
||||
21
src/btree_nodes/nodes.xml
Normal file
21
src/btree_nodes/nodes.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
For instructions on using Groot and description of the following BehaviorTree nodes,
|
||||
please refer to the groot_instructions.md and REAMDE.md respectively located in the
|
||||
nav2_behavior_tree package.
|
||||
-->
|
||||
<root>
|
||||
<TreeNodesModel>
|
||||
<!-- ############################### ACTION NODES ################################# -->
|
||||
<Action ID="GenerateNewPose">
|
||||
<input_port name="target_area">Target area</input_port>
|
||||
<output_port name="pose">Generated pose in target area</output_port>
|
||||
</Action>
|
||||
|
||||
<Action ID="MoveToPose">
|
||||
<input_port name="pose_publisher">Where to publish target pose</input_port>
|
||||
<input_port name="pose_listener">Where to get current pose</input_port>
|
||||
<input_port name="target_pose">Actual target pose</input_port>
|
||||
</Action>
|
||||
</TreeNodesModel>
|
||||
</root>
|
||||
19
src/btree_nodes/package.xml
Normal file
19
src/btree_nodes/package.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?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>btree_nodes</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="bastian@todo.todo">bastian</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
<depend>rclcpp</depend>
|
||||
<depend>geometry_msgs</depend>
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
</export>
|
||||
</package>
|
||||
27
src/btree_nodes/src/Area.cpp
Normal file
27
src/btree_nodes/src/Area.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
//
|
||||
// Created by bastian on 21.02.22.
|
||||
//
|
||||
|
||||
#include "Area.h"
|
||||
|
||||
namespace BT
|
||||
{
|
||||
template <> inline Area convertFromString(StringView str)
|
||||
{
|
||||
// The next line should be removed...
|
||||
printf("Converting string: \"%s\"\n", str.data() );
|
||||
|
||||
// We expect real numbers separated by semicolons
|
||||
auto parts = splitString(str, ';');
|
||||
if (parts.size() != 2)
|
||||
{
|
||||
throw RuntimeError("invalid input)");
|
||||
}
|
||||
else{
|
||||
Position2d output;
|
||||
output.x = convertFromString<double>(parts[0]);
|
||||
output.y = convertFromString<double>(parts[1]);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/btree_nodes/src/Area.h
Normal file
23
src/btree_nodes/src/Area.h
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by bastian on 21.02.22.
|
||||
//
|
||||
|
||||
#ifndef BUILD_AREA_H
|
||||
#define BUILD_AREA_H
|
||||
|
||||
#include <behaviortree_cpp_v3/behavior_tree.h>
|
||||
#include <behaviortree_cpp_v3/bt_factory.h>
|
||||
|
||||
class Position2d{
|
||||
public:
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
class Area {
|
||||
int triangleCount;
|
||||
Position2d triangles[0] = {};
|
||||
};
|
||||
|
||||
|
||||
#endif //BUILD_AREA_H
|
||||
5
src/btree_nodes/src/GenerateNewPose.cpp
Normal file
5
src/btree_nodes/src/GenerateNewPose.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by bastian on 21.02.22.
|
||||
//
|
||||
|
||||
#include "GenerateNewPose.h"
|
||||
14
src/btree_nodes/src/GenerateNewPose.h
Normal file
14
src/btree_nodes/src/GenerateNewPose.h
Normal file
@ -0,0 +1,14 @@
|
||||
//
|
||||
// Created by bastian on 21.02.22.
|
||||
//
|
||||
|
||||
#ifndef BUILD_GENERATENEWPOSE_H
|
||||
#define BUILD_GENERATENEWPOSE_H
|
||||
|
||||
|
||||
class GenerateNewPose {
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //BUILD_GENERATENEWPOSE_H
|
||||
30
src/btree_nodes/src/MinimalSubscriber.cpp
Normal file
30
src/btree_nodes/src/MinimalSubscriber.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by bastian on 22.02.22.
|
||||
//
|
||||
|
||||
#include <memory>
|
||||
#include <geometry_msgs/msg/pose.hpp>
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
|
||||
template<typename T>
|
||||
class MinimalSubscriber : public rclcpp::Node {
|
||||
public:
|
||||
MinimalSubscriber(const std::string &node_name, const std::string &topic_name, void(*callback)(T)) :
|
||||
Node(node_name) {
|
||||
this->subscription_ = this->create_subscription<T>(
|
||||
topic_name, 10, [callback](const T result) {
|
||||
callback(result);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
typename rclcpp::Subscription<T>::SharedPtr subscription_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
std::thread spinMinimalSubscriber(const std::string &node_name, const std::string &topic_name, void(*callback)(T)) {
|
||||
return std::thread([node_name, topic_name, callback]() {
|
||||
rclcpp::spin(std::make_shared<MinimalSubscriber<T>>(node_name, topic_name, callback));
|
||||
rclcpp::shutdown();
|
||||
});
|
||||
}
|
||||
121
src/btree_nodes/src/Tree.cpp
Normal file
121
src/btree_nodes/src/Tree.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
#include <chrono>
|
||||
#include "Area.h"
|
||||
#include <behaviortree_cpp_v3/action_node.h>
|
||||
#include <rclcpp/rclcpp.hpp>
|
||||
#include "MinimalSubscriber.cpp"
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// Simple Action to print a number
|
||||
//-------------------------------------------------------------
|
||||
|
||||
using namespace BT;
|
||||
|
||||
typedef std::chrono::milliseconds Milliseconds;
|
||||
|
||||
class MyAsyncAction: public CoroActionNode
|
||||
{
|
||||
public:
|
||||
MyAsyncAction(const std::string& name):
|
||||
CoroActionNode(name, {})
|
||||
{}
|
||||
|
||||
private:
|
||||
// This is the ideal skeleton/template of an async action:
|
||||
// - A request to a remote service provider.
|
||||
// - A loop where we check if the reply has been received.
|
||||
// - You may call setStatusRunningAndYield() to "pause".
|
||||
// - Code to execute after the reply.
|
||||
// - A simple way to handle halt().
|
||||
NodeStatus tick() override
|
||||
{
|
||||
std::cout << name() <<": Started. Send Request to server." << std::endl;
|
||||
|
||||
TimePoint initial_time = Now();
|
||||
TimePoint time_before_reply = initial_time + Milliseconds(100);
|
||||
|
||||
int count = 0;
|
||||
bool reply_received = false;
|
||||
|
||||
while( !reply_received )
|
||||
{
|
||||
if( count++ == 0)
|
||||
{
|
||||
// call this only once
|
||||
std::cout << name() <<": Waiting Reply..." << std::endl;
|
||||
}
|
||||
// pretend that we received a reply
|
||||
if( Now() >= time_before_reply )
|
||||
{
|
||||
reply_received = true;
|
||||
}
|
||||
|
||||
if( !reply_received )
|
||||
{
|
||||
// set status to RUNNING and "pause/sleep"
|
||||
// If halt() is called, we will NOT resume execution
|
||||
setStatusRunningAndYield();
|
||||
}
|
||||
}
|
||||
|
||||
// This part of the code is never reached if halt() is invoked,
|
||||
// only if reply_received == true;
|
||||
std::cout << name() <<": Done. 'Waiting Reply' loop repeated "
|
||||
<< count << " times" << std::endl;
|
||||
cleanup(false);
|
||||
return NodeStatus::SUCCESS;
|
||||
}
|
||||
|
||||
// you might want to cleanup differently if it was halted or successful
|
||||
void cleanup(bool halted)
|
||||
{
|
||||
if( halted )
|
||||
{
|
||||
std::cout << name() <<": cleaning up after an halt()\n" << std::endl;
|
||||
}
|
||||
else{
|
||||
std::cout << name() <<": cleaning up after SUCCESS\n" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void halt() override
|
||||
{
|
||||
std::cout << name() <<": Halted." << std::endl;
|
||||
cleanup(true);
|
||||
// Do not forget to call this at the end.
|
||||
CoroActionNode::halt();
|
||||
}
|
||||
|
||||
TimePoint Now()
|
||||
{
|
||||
return std::chrono::high_resolution_clock::now();
|
||||
};
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
rclcpp::init(argc, argv);
|
||||
/*
|
||||
NodeHandle nh;
|
||||
|
||||
BehaviorTreeFactory factory;
|
||||
|
||||
//factory.registerNodeType<PrintValue>("PrintValue");
|
||||
//RegisterRosService<AddTwoIntsAction>(factory, "AddTwoInts", nh);
|
||||
//RegisterRosAction<FibonacciServer>(factory, "Fibonacci", nh);
|
||||
|
||||
auto tree = factory.createTreeFromText("");
|
||||
|
||||
NodeStatus status = NodeStatus::IDLE;
|
||||
|
||||
while( ros::ok() && (status == NodeStatus::IDLE || status == NodeStatus::RUNNING))
|
||||
{
|
||||
ros::spinOnce();
|
||||
status = tree.tickRoot();
|
||||
std::cout << status << std::endl;
|
||||
ros::Duration sleep_time(0.01);
|
||||
sleep_time.sleep();
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
38
src/cpp_pubsub/CMakeLists.txt
Normal file
38
src/cpp_pubsub/CMakeLists.txt
Normal file
@ -0,0 +1,38 @@
|
||||
cmake_minimum_required(VERSION VERSION 3.5.1)
|
||||
project(cpp_pubsub)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# find dependencies
|
||||
|
||||
find_package(ament_cmake REQUIRED)
|
||||
find_package(rclcpp REQUIRED)
|
||||
find_package(geometry_msgs REQUIRED)
|
||||
# uncomment the following section in order to fill in
|
||||
# further dependencies manually.
|
||||
# find_package(<dependency> REQUIRED)
|
||||
|
||||
add_executable(talker src/publisher_member_function.cpp)
|
||||
ament_target_dependencies(talker geometry_msgs rclcpp)
|
||||
add_executable(listener src/subscriber_member_function.cpp)
|
||||
ament_target_dependencies(listener geometry_msgs rclcpp)
|
||||
|
||||
install(TARGETS
|
||||
talker
|
||||
listener
|
||||
DESTINATION lib/${PROJECT_NAME})
|
||||
|
||||
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()
|
||||
19
src/cpp_pubsub/package.xml
Normal file
19
src/cpp_pubsub/package.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?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>cpp_pubsub</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="bastian@todo.todo">bastian</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
<depend>rclcpp</depend>
|
||||
<depend>geometry_msgs</depend>
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
</export>
|
||||
</package>
|
||||
54
src/cpp_pubsub/src/publisher_member_function.cpp
Normal file
54
src/cpp_pubsub/src/publisher_member_function.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <geometry_msgs/msg/pose.hpp>
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "std_msgs/msg/string.hpp"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/* This example creates a subclass of Node and uses std::bind() to register a
|
||||
* member function as a callback from the timer. */
|
||||
|
||||
class MinimalPublisher : public rclcpp::Node{
|
||||
public:
|
||||
MinimalPublisher(): Node("minimal_publisher") {
|
||||
publisher_ = this->create_publisher<geometry_msgs::msg::Pose>("topic", 10);
|
||||
timer_ = this->create_wall_timer(
|
||||
500ms, [this]{
|
||||
auto message = geometry_msgs::msg::Pose();
|
||||
message.position.x=i;
|
||||
RCLCPP_INFO(this->get_logger(), "Publishing: '%f %f %f'", message.position.x,message.position.y,message.position.z);
|
||||
i++;
|
||||
publisher_->publish(message);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
int i=0;
|
||||
rclcpp::TimerBase::SharedPtr timer_;
|
||||
rclcpp::Publisher<geometry_msgs::msg::Pose>::SharedPtr publisher_;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
rclcpp::init(argc, argv);
|
||||
rclcpp::spin(std::make_shared<MinimalPublisher>());
|
||||
rclcpp::shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
66
src/cpp_pubsub/src/subscriber_member_function.cpp
Normal file
66
src/cpp_pubsub/src/subscriber_member_function.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#include <memory>
|
||||
#include <geometry_msgs/msg/pose.hpp>
|
||||
|
||||
#include "rclcpp/rclcpp.hpp"
|
||||
#include "std_msgs/msg/string.hpp"
|
||||
|
||||
using std::placeholders::_1;
|
||||
/*
|
||||
class MinimalSubscriber : public rclcpp::Node
|
||||
{
|
||||
public:
|
||||
MinimalSubscriber(): Node("minimal_subscriber"){}
|
||||
|
||||
private:
|
||||
rclcpp::Subscription<geometry_msgs::msg::Pose>::SharedPtr subscription_ = this->create_subscription<geometry_msgs::msg::Pose>(
|
||||
"topic", 10, [this](const geometry_msgs::msg::Pose PH1) {
|
||||
RCLCPP_INFO(this->get_logger(), "I heard: '%f %f %f'", PH1.position.x,PH1.position.y,PH1.position.z);
|
||||
|
||||
//RCUTILS_LOG_INFO_NAMED(this->get_logger().get_name(),"I heard: '%s'", PH1->data.c_str());
|
||||
});
|
||||
};
|
||||
*/
|
||||
template <typename T>
|
||||
class MinimalSubscriber : public rclcpp::Node
|
||||
{
|
||||
public: MinimalSubscriber(const std::string& node_name, const std::string& topic_name, void(*fun)(T)): Node(node_name){
|
||||
this->subscription_ = this->create_subscription<T>(
|
||||
topic_name, 10, [fun](const T result) {
|
||||
fun(result);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
typename rclcpp::Subscription<T>::SharedPtr subscription_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::thread spinMinimalSubscriber(const std::string& node_name, const std::string& topic_name, void(*callback)(T)){
|
||||
return std::thread([node_name,topic_name,callback](){
|
||||
rclcpp::spin(std::make_shared<MinimalSubscriber<T>>(node_name,topic_name,callback));
|
||||
rclcpp::shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
rclcpp::init(0, nullptr);
|
||||
spinMinimalSubscriber<geometry_msgs::msg::Pose>("talker","topic",[](geometry_msgs::msg::Pose pose){
|
||||
printf("log: %f %f %f \n",pose.position.x,pose.position.y,pose.position.z);
|
||||
}).join();
|
||||
return 0;
|
||||
}
|
||||
BIN
src/gaz_simulation/.package.xml.kate-swp
Normal file
BIN
src/gaz_simulation/.package.xml.kate-swp
Normal file
Binary file not shown.
29
src/gaz_simulation/CMakeLists.txt
Normal file
29
src/gaz_simulation/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
project(gaz_simulation)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
endif()
|
||||
|
||||
# find dependencies
|
||||
find_package(ament_cmake REQUIRED)
|
||||
# uncomment the following section in order to fill in
|
||||
# further dependencies manually.
|
||||
# find_package(<dependency> REQUIRED)
|
||||
|
||||
install(DIRECTORY launch DESTINATION share/${PROJECT_NAME})
|
||||
install(DIRECTORY world DESTINATION share/${PROJECT_NAME})
|
||||
install(DIRECTORY urdf DESTINATION share/${PROJECT_NAME})
|
||||
|
||||
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()
|
||||
16
src/gaz_simulation/calc.lua
Executable file
16
src/gaz_simulation/calc.lua
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/lua
|
||||
|
||||
io.write("Radius: ")
|
||||
local radius=io.read("*line")
|
||||
io.write("Height: ")
|
||||
local height=io.read("*line")
|
||||
io.write("Weight: ")
|
||||
local weight=io.read("*line")
|
||||
|
||||
local ix_and_y=(1/12)*weight*(3*radius*radius+height*height)
|
||||
local iz=(1/2)*weight*radius*radius
|
||||
|
||||
print([[<inertial>
|
||||
<mass value="]]..tostring(weight)..[["/>
|
||||
<inertia ixx="]]..tostring(ix_and_y)..[[" ixy="0.0" ixz="0.0" iyy="]]..tostring(ix_and_y)..[[" iyz="0.0" izz="]]..tostring(iz)..[["/>
|
||||
</inertial>]])
|
||||
72
src/gaz_simulation/launch/test_launch.py
Normal file
72
src/gaz_simulation/launch/test_launch.py
Normal file
@ -0,0 +1,72 @@
|
||||
import os
|
||||
from launch import LaunchDescription
|
||||
from launch_ros.actions import Node
|
||||
from launch.actions import ExecuteProcess, IncludeLaunchDescription
|
||||
from launch_ros.substitutions import FindPackageShare
|
||||
from launch.substitutions import Command
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
|
||||
def generate_launch_description():
|
||||
robot_name = "iisy"
|
||||
package_name = "gaz_simulation"
|
||||
pkg_gazebo_ros = FindPackageShare(package='gazebo_ros').find('gazebo_ros')
|
||||
path = FindPackageShare(package=package_name).find(package_name)
|
||||
world_path = os.path.join(path, "world/test2.xml")
|
||||
urdf_path = os.path.join(path, "urdf/iisy.urdf")
|
||||
return LaunchDescription([
|
||||
IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(os.path.join(pkg_gazebo_ros, 'launch', 'gzserver.launch.py')),
|
||||
launch_arguments={'world': world_path}.items()
|
||||
),
|
||||
|
||||
# Start Gazebo client
|
||||
IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(os.path.join(pkg_gazebo_ros, 'launch', 'gzclient.launch.py'))
|
||||
),
|
||||
Node(
|
||||
package='tf2_ros',
|
||||
namespace='gaz_simulation',
|
||||
executable='static_transform_publisher',
|
||||
name='lidar_1_broadcaster',
|
||||
arguments=["1", "-1.9", "1", "1.5707963267949", "0", "0", "map", "lidar_1_link"]
|
||||
),
|
||||
Node(
|
||||
package='tf2_ros',
|
||||
namespace='gaz_simulation',
|
||||
executable='static_transform_publisher',
|
||||
name='lidar_2_broadcaster',
|
||||
arguments=["-1.9", "1", "1", "0", "0", "0", "map", "lidar_2_link"]
|
||||
),
|
||||
Node(
|
||||
package='gazebo_ros',
|
||||
executable='spawn_entity.py',
|
||||
arguments=['-entity', robot_name,
|
||||
'-topic', 'robot_description',
|
||||
'-x', '-1',
|
||||
'-y', '-1',
|
||||
'-z', '1',
|
||||
'-Y', '0'], # Yaw
|
||||
output='screen'
|
||||
),
|
||||
# Subscribe to the joint states of the robot, and publish the 3D pose of each link.
|
||||
Node(
|
||||
package='robot_state_publisher',
|
||||
executable='robot_state_publisher',
|
||||
parameters=[{'robot_description': Command(['xacro ', urdf_path])}]
|
||||
),
|
||||
|
||||
# Publish the joint states of the robot
|
||||
Node(
|
||||
package='joint_state_publisher',
|
||||
executable='joint_state_publisher',
|
||||
name='joint_state_publisher'
|
||||
)
|
||||
|
||||
# ,
|
||||
# Node(
|
||||
# namespace='turtlesim1',
|
||||
# executable='gazebo',
|
||||
# name='gazebo',
|
||||
# arguments=["test.xml"]
|
||||
# )
|
||||
])
|
||||
28
src/gaz_simulation/package.xml
Normal file
28
src/gaz_simulation/package.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<package format="3">
|
||||
<name>gaz_simulation</name>
|
||||
<version>0.244.1</version>
|
||||
<description>Launch file for simulation of pick and place</description>
|
||||
<license>Apache 2.0</license>
|
||||
<maintainer email="bastian.hofmann@xitaso.com">Bastian Hofmann</maintainer>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
|
||||
<exec_depend>gazebo-11</exec_depend>
|
||||
|
||||
<exec_depend>image_transport_plugins</exec_depend>
|
||||
<exec_depend>robot_state_publisher</exec_depend>
|
||||
<exec_depend>ros_ign_bridge</exec_depend>
|
||||
<exec_depend>ros_ign_gazebo</exec_depend>
|
||||
<exec_depend>ros_ign_image</exec_depend>
|
||||
<!-- See https://github.com/osrf/ros_ign/issues/40 -->
|
||||
<!--exec_depend>ros_ign_point_cloud</exec_depend-->
|
||||
<exec_depend>rqt_image_view</exec_depend>
|
||||
<exec_depend>rqt_plot</exec_depend>
|
||||
<exec_depend>rqt_topic</exec_depend>
|
||||
<exec_depend>rviz2</exec_depend>
|
||||
<exec_depend>xacro</exec_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
</export>
|
||||
</package>
|
||||
195
src/gaz_simulation/urdf/iisy.urdf
Normal file
195
src/gaz_simulation/urdf/iisy.urdf
Normal file
@ -0,0 +1,195 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot name="iisy" xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
<static>true</static>
|
||||
<link name='base'>
|
||||
<pose>0.025 0 0.05 0 0 0</pose>
|
||||
<collision name='collision'>
|
||||
<geometry>
|
||||
<box size=".15 .1 .1"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<geometry>
|
||||
<box size=".15 .1 .1"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<inertial>
|
||||
<mass value="6"/>
|
||||
<inertia ixx="0.0032666666666667" ixy="0.0" ixz="0.0" iyy="0.0032666666666667" iyz="0.0" izz="0.0025"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<link name="base_rot">
|
||||
<pose>0 0 0.155 0 0 0</pose>
|
||||
<collision name="collision">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".11"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".11"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<inertial>
|
||||
<mass value="2"/>
|
||||
<inertia ixx="0.0032666666666667" ixy="0.0" ixz="0.0" iyy="0.0032666666666667" iyz="0.0" izz="0.0025"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<link name="link1">
|
||||
<pose>0 0 0.36 0 0 0</pose>
|
||||
<collision name="collision">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".30"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".30"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<inertial>
|
||||
<mass value="4"/>
|
||||
<inertia ixx="0.0325" ixy="0.0" ixz="0.0" iyy="0.0325" iyz="0.0" izz="0.005"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<link name="link2_rot">
|
||||
<pose>0 0 0.585 0 0 0</pose>
|
||||
<collision name="collision">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".15"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".15"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<inertial>
|
||||
<mass value="2"/>
|
||||
<inertia ixx="0.005" ixy="0.0" ixz="0.0" iyy="0.005" iyz="0.0" izz="0.0025"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<link name="link2">
|
||||
<pose>0 0 0.735 0 0 0</pose>
|
||||
<collision name="collision">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".15"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".15"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<inertial>
|
||||
<mass value="2"/>
|
||||
<inertia ixx="0.005" ixy="0.0" ixz="0.0" iyy="0.005" iyz="0.0" izz="0.0025"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<link name="link3_rot">
|
||||
<pose>0 0 0.86 0 0 0</pose>
|
||||
<collision name="collision">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".10"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".10"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<inertial>
|
||||
<mass value="2"/>
|
||||
<inertia ixx="0.0029166666666667" ixy="0.0" ixz="0.0" iyy="0.0029166666666667" iyz="0.0" izz="0.0025"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<link name="link3">
|
||||
<pose>0 0 0.94025 0 0 0</pose>
|
||||
<collision name="collision">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".0605"/>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry>
|
||||
<cylinder radius=".05" length=".0605"/>
|
||||
</geometry>
|
||||
</visual>
|
||||
<inertial>
|
||||
<mass value="0.8"/>
|
||||
<inertia ixx="0.00074401666666667" ixy="0.0" ixz="0.0" iyy="0.00074401666666667" iyz="0.0" izz="0.001"/>
|
||||
</inertial>
|
||||
</link>
|
||||
|
||||
<joint type="continuous" name="base_rot_joint">
|
||||
<pose>0 0 -0.055 0 0 0</pose>
|
||||
<parent link="base"/>
|
||||
<child link="base_rot"/>
|
||||
<axis>
|
||||
<xyz>0 0 1</xyz>
|
||||
</axis>
|
||||
<limit effort="30" velocity="1.7453292519943"/>
|
||||
</joint>
|
||||
|
||||
<joint type="revolute" name="link1_joint">
|
||||
<pose>0 0 -0.15 0 0 0</pose>
|
||||
<parent link="base_rot"/>
|
||||
<child link="link1"/>
|
||||
<axis>
|
||||
<xyz>1 0 0</xyz>
|
||||
</axis>
|
||||
<limit effort="30" velocity="1.7453292519943" lower="-1.221730476396" upper="1.221730476396"/>
|
||||
</joint>
|
||||
|
||||
<joint type="revolute" name="link2_rot_joint">
|
||||
<pose>0 0 -0.075 0 0 0</pose>
|
||||
<parent link="link1"/>
|
||||
<child link="link2_rot"/>
|
||||
<axis>
|
||||
<xyz>1 0 0</xyz>
|
||||
</axis>
|
||||
<limit effort="30" velocity="1.7453292519943" lower="-1.3089969389957" upper="1.3089969389957"/>
|
||||
</joint>
|
||||
|
||||
<joint type="continuous" name="link2_joint">
|
||||
<pose>0 0 -0.075 0 0 0</pose>
|
||||
<parent link="link2_rot"/>
|
||||
<child link="link2"/>
|
||||
<axis>
|
||||
<xyz>0 0 1</xyz>
|
||||
</axis>
|
||||
<limit effort="30" velocity="1.7453292519943"/>
|
||||
</joint>
|
||||
|
||||
<joint type="revolute" name="link3_rot_joint">
|
||||
<pose>0 0 -0.05 0 0 0</pose>
|
||||
<parent link="link2"/>
|
||||
<child link="link3_rot"/>
|
||||
<axis>
|
||||
<xyz>1 0 0</xyz>
|
||||
</axis>
|
||||
<limit effort="30" velocity="1.7453292519943" lower="-0.95993108859688" upper="0.95993108859688"/>
|
||||
</joint>
|
||||
|
||||
<joint type="continuous" name="link3_joint">
|
||||
<pose>0 0 -0.03025 0 0 0</pose>
|
||||
<parent link="link3_rot"/>
|
||||
<child link="link3"/>
|
||||
<axis>
|
||||
<xyz>0 0 1</xyz>
|
||||
</axis>
|
||||
<limit effort="30" velocity="1.7453292519943"/>
|
||||
</joint>
|
||||
|
||||
<gazebo>
|
||||
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
|
||||
<robotNamespace>/simple_model</robotNamespace>
|
||||
</plugin>
|
||||
</gazebo>
|
||||
</robot>
|
||||
320
src/gaz_simulation/world/test2.xml
Normal file
320
src/gaz_simulation/world/test2.xml
Normal file
@ -0,0 +1,320 @@
|
||||
<sdf version='1.7'>
|
||||
<world name='default'>
|
||||
<light name='sun' type='directional'>
|
||||
<cast_shadows>1</cast_shadows>
|
||||
<pose>0 0 10 0 -0 0</pose>
|
||||
<diffuse>0.8 0.8 0.8 1</diffuse>
|
||||
<specular>0.2 0.2 0.2 1</specular>
|
||||
<attenuation>
|
||||
<range>1000</range>
|
||||
<constant>0.9</constant>
|
||||
<linear>0.01</linear>
|
||||
<quadratic>0.001</quadratic>
|
||||
</attenuation>
|
||||
<direction>-0.5 0.1 -0.9</direction>
|
||||
<spot>
|
||||
<inner_angle>0</inner_angle>
|
||||
<outer_angle>0</outer_angle>
|
||||
<falloff>0</falloff>
|
||||
</spot>
|
||||
</light>
|
||||
<model name='walls'>
|
||||
<static>1</static>
|
||||
<link name='walls_1'>
|
||||
<self_collide>0</self_collide>
|
||||
<pose>3 8 1.2</pose>
|
||||
<collision name='collision'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>10.1 .1 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>10.1 .1 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</visual>
|
||||
</link>
|
||||
<link name='walls_2'>
|
||||
<self_collide>0</self_collide>
|
||||
<pose>3 -2 1.2</pose>
|
||||
<collision name='collision'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>10.1 .1 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>10.1 .1 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</visual>
|
||||
</link>
|
||||
<link name='walls_3'>
|
||||
<self_collide>0</self_collide>
|
||||
<pose>8 3 1.2</pose>
|
||||
<collision name='collision'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 9.9 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 9.9 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</visual>
|
||||
</link>
|
||||
<link name='walls_4'>
|
||||
<self_collide>0</self_collide>
|
||||
<pose>-2 3 1.2</pose>
|
||||
<collision name='collision'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 9.9 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 9.9 2.4</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</visual>
|
||||
</link>
|
||||
</model>
|
||||
<model name="lidar_1">
|
||||
<static>1</static>
|
||||
<link name="lidar_1_link">
|
||||
<pose>1 -2 1 0 0 1.5707963267949</pose>
|
||||
<!--<collision name='collision'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 .1 .1</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 .1 .1</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</visual>-->
|
||||
<sensor name="laser" type="gpu_ray">
|
||||
<pose>0.1 0 0 0 0 0</pose>
|
||||
<ray>
|
||||
<scan>
|
||||
<horizontal>
|
||||
<samples>270</samples>
|
||||
<resolution>1</resolution>
|
||||
<min_angle>-2.3561944901923</min_angle>
|
||||
<max_angle>2.3561944901923</max_angle>
|
||||
</horizontal>
|
||||
</scan>
|
||||
<range>
|
||||
<min>0.05</min>
|
||||
<max>10</max>
|
||||
<resolution>0.05</resolution>
|
||||
</range>
|
||||
</ray>
|
||||
<always_on>1</always_on>
|
||||
<update_rate>10</update_rate>
|
||||
<visualize>true</visualize>
|
||||
|
||||
<plugin name='laser' filename='libgazebo_ros_ray_sensor.so'>
|
||||
<ros>
|
||||
<namespace>/lidar_1</namespace>
|
||||
<argument>--ros-args --remap ~/out:=scan</argument>
|
||||
</ros>
|
||||
<output_type>sensor_msgs/PointCloud2</output_type>
|
||||
</plugin>
|
||||
</sensor>
|
||||
</link>
|
||||
</model>
|
||||
<model name="lidar_2">
|
||||
<static>1</static>
|
||||
<link name="lidar_2_link">
|
||||
<pose>-2 1 1 0 0 </pose>
|
||||
<collision name='collision'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 .1 .1</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<geometry>
|
||||
<box>
|
||||
<size>.1 .1 .1</size>
|
||||
</box>
|
||||
</geometry>
|
||||
</visual>
|
||||
<sensor name="laser" type="gpu_ray">
|
||||
<pose>0.1 0 0 0 0 0</pose>
|
||||
<ray>
|
||||
<scan>
|
||||
<horizontal>
|
||||
<samples>270</samples>
|
||||
<resolution>1</resolution>
|
||||
<min_angle>-2.3561944901923</min_angle>
|
||||
<max_angle>2.3561944901923</max_angle>
|
||||
</horizontal>
|
||||
</scan>
|
||||
<range>
|
||||
<min>0.05</min>
|
||||
<max>10</max>
|
||||
<resolution>0.05</resolution>
|
||||
</range>
|
||||
</ray>
|
||||
<always_on>1</always_on>
|
||||
<update_rate>10</update_rate>
|
||||
<visualize>true</visualize>
|
||||
|
||||
<plugin name='laser' filename='libgazebo_ros_ray_sensor.so'>
|
||||
<ros>
|
||||
<namespace>/lidar_2</namespace>
|
||||
<frameName>/lidar_2_link</frameName>
|
||||
<argument>--ros-args --remap ~/out:=scan</argument>
|
||||
</ros>
|
||||
<output_type>sensor_msgs/PointCloud2</output_type>
|
||||
</plugin>
|
||||
</sensor>
|
||||
</link>
|
||||
</model>
|
||||
<model name='ground_plane'>
|
||||
<static>1</static>
|
||||
<link name='link'>
|
||||
<collision name='collision'>
|
||||
<geometry>
|
||||
<plane>
|
||||
<normal>0 0 1</normal>
|
||||
<size>100 100</size>
|
||||
</plane>
|
||||
</geometry>
|
||||
<surface>
|
||||
<contact>
|
||||
<collide_bitmask>65535</collide_bitmask>
|
||||
<ode/>
|
||||
</contact>
|
||||
<friction>
|
||||
<ode>
|
||||
<mu>100</mu>
|
||||
<mu2>50</mu2>
|
||||
</ode>
|
||||
<torsional>
|
||||
<ode/>
|
||||
</torsional>
|
||||
</friction>
|
||||
<bounce/>
|
||||
</surface>
|
||||
<max_contacts>10</max_contacts>
|
||||
</collision>
|
||||
<visual name='visual'>
|
||||
<cast_shadows>0</cast_shadows>
|
||||
<geometry>
|
||||
<plane>
|
||||
<normal>0 0 1</normal>
|
||||
<size>100 100</size>
|
||||
</plane>
|
||||
</geometry>
|
||||
<material>
|
||||
<script>
|
||||
<uri>file://media/materials/scripts/gazebo.material</uri>
|
||||
<name>Gazebo/Grey</name>
|
||||
</script>
|
||||
</material>
|
||||
</visual>
|
||||
<self_collide>0</self_collide>
|
||||
<enable_wind>0</enable_wind>
|
||||
<kinematic>0</kinematic>
|
||||
</link>
|
||||
</model>
|
||||
<actor name="actor1">
|
||||
<pose>0 1 1.25 0 0 0</pose>
|
||||
|
||||
<skin>
|
||||
<filename>walk.dae</filename>
|
||||
<scale>1.0</scale>
|
||||
</skin>
|
||||
<animation name="walking">
|
||||
<filename>walk.dae</filename>
|
||||
<scale>1.000000</scale>
|
||||
<interpolate_x>true</interpolate_x>
|
||||
</animation>
|
||||
<plugin name="actor1_plugin" filename="/home/bastian/dev_ws/build/gazebo_ros_actor/libRosActorPlugin.so">
|
||||
<target>2 2 1</target>
|
||||
<target_weight>1.15</target_weight>
|
||||
<obstacle_weight>1.8</obstacle_weight>
|
||||
<animation_factor>5.1</animation_factor>
|
||||
<ignore_obstacles>
|
||||
<model>ground_plane</model>
|
||||
</ignore_obstacles>
|
||||
</plugin>
|
||||
</actor>
|
||||
<gravity>0 0 -9.8</gravity>
|
||||
<magnetic_field>6e-06 2.3e-05 -4.2e-05</magnetic_field>
|
||||
<atmosphere type='adiabatic'/>
|
||||
<physics type='ode'>
|
||||
<max_step_size>0.001</max_step_size>
|
||||
<real_time_factor>1</real_time_factor>
|
||||
<real_time_update_rate>1000</real_time_update_rate>
|
||||
</physics>
|
||||
<scene>
|
||||
<ambient>0.4 0.4 0.4 1</ambient>
|
||||
<background>0.7 0.7 0.7 1</background>
|
||||
<shadows>1</shadows>
|
||||
</scene>
|
||||
<wind/>
|
||||
<spherical_coordinates>
|
||||
<surface_model>EARTH_WGS84</surface_model>
|
||||
<latitude_deg>0</latitude_deg>
|
||||
<longitude_deg>0</longitude_deg>
|
||||
<elevation>0</elevation>
|
||||
<heading_deg>0</heading_deg>
|
||||
</spherical_coordinates>
|
||||
<state world_name='default'>
|
||||
<sim_time>21 655000000</sim_time>
|
||||
<real_time>21 863005214</real_time>
|
||||
<wall_time>1644846646 70909467</wall_time>
|
||||
<iterations>21655</iterations>
|
||||
<model name='ground_plane'>
|
||||
<pose>0 0 0 0 -0 0</pose>
|
||||
<scale>1 1 1</scale>
|
||||
<link name='link'>
|
||||
<pose>0 0 0 0 -0 0</pose>
|
||||
<velocity>0 0 0 0 -0 0</velocity>
|
||||
<acceleration>0 0 0 0 -0 0</acceleration>
|
||||
<wrench>0 0 0 0 -0 0</wrench>
|
||||
</link>
|
||||
</model>
|
||||
<light name='sun'>
|
||||
<pose>0 0 10 0 -0 0</pose>
|
||||
</light>
|
||||
</state>
|
||||
<gui fullscreen='0'>
|
||||
<camera name='user_camera'>
|
||||
<pose>5 -5 2 0 0.275643 2.35619</pose>
|
||||
<view_controller>orbit</view_controller>
|
||||
<projection_type>perspective</projection_type>
|
||||
</camera>
|
||||
</gui>
|
||||
<plugin name="gazebo_ros_state" filename="libgazebo_ros_state.so">
|
||||
<ros>
|
||||
<namespace>/demo</namespace>
|
||||
<argument>model_states:=model_states_demo</argument>
|
||||
</ros>
|
||||
<update_rate>1.0</update_rate>
|
||||
</plugin>
|
||||
</world>
|
||||
</sdf>
|
||||
30
src/gazebo_ros_actor/CMakeLists.txt
Normal file
30
src/gazebo_ros_actor/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
||||
cmake_minimum_required(VERSION VERSION 3.5.1)
|
||||
project(gazebo_ros_actor)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(ament_cmake REQUIRED)
|
||||
find_package(rclcpp REQUIRED)
|
||||
find_package(rospy REQUIRED)
|
||||
find_package(geometry_msgs REQUIRED)
|
||||
find_package(gazebo REQUIRED)
|
||||
|
||||
link_directories(${GAZEBO_LIBRARY_DIRS})
|
||||
include_directories(include ${Boost_INCLUDE_DIR} ${GAZEBO_INCLUDE_DIRS} )
|
||||
|
||||
include_directories(
|
||||
include
|
||||
)
|
||||
|
||||
add_library(RosActorPlugin SHARED src/RosActorPlugin.cc)
|
||||
target_link_libraries(RosActorPlugin ${GAZEBO_LIBRARIES})
|
||||
ament_target_dependencies(RosActorPlugin geometry_msgs rclcpp)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
RosActorPlugin
|
||||
)
|
||||
|
||||
ament_package()
|
||||
27
src/gazebo_ros_actor/package.xml
Normal file
27
src/gazebo_ros_actor/package.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?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>gazebo_ros_actor</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="bastian@todo.todo">bastian</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
|
||||
<depend>rclcpp</depend>
|
||||
<depend>geometry_msgs</depend>
|
||||
|
||||
<test_depend>ament_lint_auto</test_depend>
|
||||
<test_depend>ament_lint_common</test_depend>
|
||||
|
||||
<exec_depend>ament_index_python</exec_depend>
|
||||
<exec_depend>rviz2</exec_depend>
|
||||
<exec_depend>launch</exec_depend>
|
||||
<exec_depend>launch_ros</exec_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
<gazebo_ros plugin_path="${prefix}/lib" gazebo_media_path="${prefix}"/>
|
||||
</export>
|
||||
</package>
|
||||
32
src/gazebo_ros_actor/src/PosePublisher.cc
Normal file
32
src/gazebo_ros_actor/src/PosePublisher.cc
Normal file
@ -0,0 +1,32 @@
|
||||
//
|
||||
// Created by bastian on 21.02.22.
|
||||
//
|
||||
|
||||
#include <rclcpp/utilities.hpp>
|
||||
#include <rclcpp/executors.hpp>
|
||||
#include <geometry_msgs/msg/pose.hpp>
|
||||
|
||||
class PosePublisher : public rclcpp::Node{
|
||||
public:
|
||||
PosePublisher(): Node("minimal_publisher") {
|
||||
publisher_ = this->create_publisher<geometry_msgs::msg::Pose>("currentPose", 10);
|
||||
}
|
||||
void update(ignition::math::Pose3d newPose){
|
||||
geometry_msgs::msg::Pose pose;
|
||||
pose.position.x=newPose.X();
|
||||
pose.position.y=newPose.Y();
|
||||
pose.position.z=newPose.Z();
|
||||
|
||||
ignition::math::Quaternion<double> quat;
|
||||
quat.Euler(newPose.Roll(),newPose.Pitch(),newPose.Yaw());
|
||||
pose.orientation.x=quat.X();
|
||||
pose.orientation.y=quat.Y();
|
||||
pose.orientation.z=quat.Z();
|
||||
pose.orientation.w=quat.W();
|
||||
|
||||
publisher_->publish(pose);
|
||||
}
|
||||
|
||||
private:
|
||||
rclcpp::Publisher<geometry_msgs::msg::Pose>::SharedPtr publisher_;
|
||||
};
|
||||
214
src/gazebo_ros_actor/src/RosActorPlugin.cc
Normal file
214
src/gazebo_ros_actor/src/RosActorPlugin.cc
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Open Source Robotics Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <ignition/math.hh>
|
||||
#include "gazebo/physics/physics.hh"
|
||||
#include "RosActorPlugin.hh"
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <rclcpp/utilities.hpp>
|
||||
#include <rclcpp/executors.hpp>
|
||||
#include <geometry_msgs/msg/pose.hpp>
|
||||
|
||||
using namespace gazebo;
|
||||
GZ_REGISTER_MODEL_PLUGIN(RosActorPlugin)
|
||||
|
||||
#define WALKING_ANIMATION "walking"
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
RosActorPlugin::RosActorPlugin()
|
||||
= default;
|
||||
|
||||
class PoseSubscriber : public rclcpp::Node{
|
||||
public:
|
||||
explicit PoseSubscriber(RosActorPlugin* plugin): Node("targetPose"){
|
||||
this->plugin = plugin;
|
||||
}
|
||||
|
||||
private:
|
||||
RosActorPlugin* plugin;
|
||||
rclcpp::Subscription<geometry_msgs::msg::Pose>::SharedPtr subscription_ = this->create_subscription<geometry_msgs::msg::Pose>(
|
||||
"actorTarget", 10, [this](const geometry_msgs::msg::Pose PH1) {
|
||||
RCLCPP_INFO(this->get_logger(), "I heard: '%f %f %f'", PH1.position.x,PH1.position.y,PH1.position.z);
|
||||
plugin->target.Set(PH1.position.x,PH1.position.y,PH1.position.z);
|
||||
});
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
void RosActorPlugin::Load(physics::ModelPtr _model, sdf::ElementPtr _sdf)
|
||||
{
|
||||
this->sdf = _sdf;
|
||||
this->actor = boost::dynamic_pointer_cast<physics::Actor>(_model);
|
||||
this->world = this->actor->GetWorld();
|
||||
|
||||
this->connections.push_back(event::Events::ConnectWorldUpdateBegin(
|
||||
[this](auto && PH1) { OnUpdate(std::forward<decltype(PH1)>(PH1)); }));
|
||||
|
||||
this->Reset();
|
||||
|
||||
// Read in the target weight
|
||||
if (_sdf->HasElement("target_weight"))
|
||||
this->targetWeight = _sdf->Get<double>("target_weight");
|
||||
else
|
||||
this->targetWeight = 1.15;
|
||||
|
||||
// Read in the obstacle weight
|
||||
if (_sdf->HasElement("obstacle_weight"))
|
||||
this->obstacleWeight = _sdf->Get<double>("obstacle_weight");
|
||||
else
|
||||
this->obstacleWeight = 1.5;
|
||||
|
||||
// Read in the animation factor (applied in the OnUpdate function).
|
||||
if (_sdf->HasElement("animation_factor"))
|
||||
this->animationFactor = _sdf->Get<double>("animation_factor");
|
||||
else
|
||||
this->animationFactor = 4.5;
|
||||
|
||||
// Add our own name to models we should ignore when avoiding obstacles.
|
||||
this->ignoreModels.push_back(this->actor->GetName());
|
||||
|
||||
// Read in the other obstacles to ignore
|
||||
if (_sdf->HasElement("ignore_obstacles"))
|
||||
{
|
||||
sdf::ElementPtr modelElem =
|
||||
_sdf->GetElement("ignore_obstacles")->GetElement("model");
|
||||
while (modelElem)
|
||||
{
|
||||
this->ignoreModels.push_back(modelElem->Get<std::string>());
|
||||
modelElem = modelElem->GetNextElement("model");
|
||||
}
|
||||
}
|
||||
|
||||
// Create a named topic, and subscribe to it.
|
||||
|
||||
std::thread spinThread([this]{
|
||||
rclcpp::spin(std::make_shared<PoseSubscriber>(this));
|
||||
rclcpp::shutdown();
|
||||
});
|
||||
spinThread.detach();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
void RosActorPlugin::Reset()
|
||||
{
|
||||
this->velocity = 0.8;
|
||||
this->lastUpdate = 0;
|
||||
|
||||
if (this->sdf && this->sdf->HasElement("target"))
|
||||
this->target = this->sdf->Get<ignition::math::Vector3d>("target");
|
||||
else
|
||||
this->target = ignition::math::Vector3d(0, 0, 1.0);
|
||||
|
||||
actor->SetWorldPose(ignition::math::Pose3d(this->target,ignition::math::Quaterniond(1.5707, 0,0)));
|
||||
|
||||
auto skelAnims = this->actor->SkeletonAnimations();
|
||||
if (skelAnims.find(WALKING_ANIMATION) == skelAnims.end())
|
||||
{
|
||||
gzerr << "Skeleton animation " << WALKING_ANIMATION << " not found.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create custom trajectory
|
||||
this->trajectoryInfo.reset(new physics::TrajectoryInfo());
|
||||
this->trajectoryInfo->type = WALKING_ANIMATION;
|
||||
this->trajectoryInfo->duration = 1.0;
|
||||
|
||||
this->actor->SetCustomTrajectory(this->trajectoryInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
void RosActorPlugin::HandleObstacles(ignition::math::Vector3d &_pos)
|
||||
{
|
||||
for (unsigned int i = 0; i < this->world->ModelCount(); ++i)
|
||||
{
|
||||
physics::ModelPtr model = this->world->ModelByIndex(i);
|
||||
if (std::find(this->ignoreModels.begin(), this->ignoreModels.end(),
|
||||
model->GetName()) == this->ignoreModels.end())
|
||||
{
|
||||
ignition::math::Vector3d offset = model->WorldPose().Pos() -
|
||||
this->actor->WorldPose().Pos();
|
||||
double modelDist = offset.Length();
|
||||
if (modelDist < 4.0)
|
||||
{
|
||||
double invModelDist = this->obstacleWeight / modelDist;
|
||||
offset.Normalize();
|
||||
offset *= invModelDist;
|
||||
_pos -= offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
void RosActorPlugin::OnUpdate(const common::UpdateInfo &_info)
|
||||
{
|
||||
// Time delta
|
||||
double dt = (_info.simTime - this->lastUpdate).Double();
|
||||
|
||||
ignition::math::Pose3d pose = this->actor->WorldPose();
|
||||
ignition::math::Vector3d pos = this->target - pose.Pos();
|
||||
ignition::math::Vector3d rpy = pose.Rot().Euler();
|
||||
|
||||
double distance = pos.Length();
|
||||
|
||||
if (distance < 0.3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Normalize the direction vector, and apply the target weight
|
||||
pos = pos.Normalize() * this->targetWeight;
|
||||
|
||||
// Adjust the direction vector by avoiding obstacles
|
||||
this->HandleObstacles(pos);
|
||||
|
||||
// Compute the yaw orientation
|
||||
ignition::math::Angle yaw = atan2(pos.Y(), pos.X()) + 1.5707 - rpy.Z();
|
||||
yaw.Normalize();
|
||||
|
||||
// Rotate in place, instead of jumping.
|
||||
if (std::abs(yaw.Radian()) > IGN_DTOR(10))
|
||||
{
|
||||
pose.Rot() = ignition::math::Quaterniond(1.5707, 0, rpy.Z()+
|
||||
yaw.Radian()*0.002);
|
||||
}
|
||||
else
|
||||
{
|
||||
pose.Pos() += pos * this->velocity * dt;
|
||||
pose.Rot() = ignition::math::Quaterniond(1.5707, 0, rpy.Z()+yaw.Radian());
|
||||
}
|
||||
|
||||
// Make sure the actor stays within bounds
|
||||
//pose.Pos().X(std::max(-3.0, std::min(3.5, pose.Pos().X())));
|
||||
//pose.Pos().Y(std::max(-10.0, std::min(2.0, pose.Pos().Y())));
|
||||
pose.Pos().Z(1.0);
|
||||
|
||||
// Distance traveled is used to coordinate motion with the walking
|
||||
// animation
|
||||
double distanceTraveled = (pose.Pos() -
|
||||
this->actor->WorldPose().Pos()).Length();
|
||||
|
||||
publisher.update(pose);
|
||||
this->actor->SetWorldPose(pose, false, false);
|
||||
this->actor->SetScriptTime(this->actor->ScriptTime() +
|
||||
(distanceTraveled * this->animationFactor));
|
||||
this->lastUpdate = _info.simTime;
|
||||
}
|
||||
94
src/gazebo_ros_actor/src/RosActorPlugin.hh
Normal file
94
src/gazebo_ros_actor/src/RosActorPlugin.hh
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Open Source Robotics Foundation
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GAZEBO_PLUGINS_ACTORPLUGIN_HH_
|
||||
#define GAZEBO_PLUGINS_ACTORPLUGIN_HH_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gazebo/common/Plugin.hh"
|
||||
#include "gazebo/physics/physics.hh"
|
||||
#include "gazebo/util/system.hh"
|
||||
#include "PosePublisher.cc"
|
||||
|
||||
namespace gazebo
|
||||
{
|
||||
class GZ_PLUGIN_VISIBLE RosActorPlugin : public ModelPlugin
|
||||
{
|
||||
/// \brief Constructor
|
||||
public: RosActorPlugin();
|
||||
|
||||
/// \brief Load the actor plugin.
|
||||
/// \param[in] _model Pointer to the parent model.
|
||||
/// \param[in] _sdf Pointer to the plugin's SDF elements.
|
||||
public: virtual void Load(physics::ModelPtr _model, sdf::ElementPtr _sdf);
|
||||
|
||||
// Documentation Inherited.
|
||||
public: virtual void Reset();
|
||||
|
||||
private: PosePublisher publisher;
|
||||
|
||||
/// \brief Function that is called every update cycle.
|
||||
/// \param[in] _info Timing information
|
||||
private: void OnUpdate(const common::UpdateInfo &_info);
|
||||
|
||||
/// \brief Helper function to avoid obstacles. This implements a very
|
||||
/// simple vector-field algorithm.
|
||||
/// \param[in] _pos Direction vector that should be adjusted according
|
||||
/// to nearby obstacles.
|
||||
private: void HandleObstacles(ignition::math::Vector3d &_pos);
|
||||
|
||||
/// \brief Pointer to the parent actor.
|
||||
private: physics::ActorPtr actor;
|
||||
|
||||
/// \brief Pointer to the world, for convenience.
|
||||
private: physics::WorldPtr world;
|
||||
|
||||
/// \brief Pointer to the sdf element.
|
||||
private: sdf::ElementPtr sdf;
|
||||
|
||||
/// \brief Velocity of the actor
|
||||
private: ignition::math::Vector3d velocity;
|
||||
|
||||
/// \brief List of connections
|
||||
private: std::vector<event::ConnectionPtr> connections;
|
||||
|
||||
/// \brief Current target location
|
||||
public: ignition::math::Vector3d target;
|
||||
|
||||
/// \brief Target location weight (used for vector field)
|
||||
private: double targetWeight = 1.0;
|
||||
|
||||
/// \brief Obstacle weight (used for vector field)
|
||||
private: double obstacleWeight = 1.0;
|
||||
|
||||
/// \brief Time scaling factor. Used to coordinate translational motion
|
||||
/// with the actor's walking animation.
|
||||
private: double animationFactor = 1.0;
|
||||
|
||||
/// \brief Time of the last update.
|
||||
private: common::Time lastUpdate;
|
||||
|
||||
/// \brief List of models to ignore. Used for vector field
|
||||
private: std::vector<std::string> ignoreModels;
|
||||
|
||||
/// \brief Custom trajectory info.
|
||||
private: physics::TrajectoryInfoPtr trajectoryInfo;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user