SMACC2
Loading...
Searching...
No Matches
cb_spiral_motion.cpp
Go to the documentation of this file.
1// Copyright 2021 RobosoftAI Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/*****************************************************************************************************************
16 *
17 * Authors: Pablo Inigo Blasco, Brett Aldrich
18 *
19 ******************************************************************************************************************/
20
21#include <angles/angles.h>
22#include <geometry_msgs/msg/twist.hpp>
24#include <optional>
26
27namespace cl_nav2z
28{
29
30CbSpiralMotion::CbSpiralMotion(std::optional<CbSpiralMotionOptions> options)
31{
32 if (options)
33 {
34 options_ = *options;
35 }
36 else
37 {
38 // we use default options
40 }
41}
42
44{
45 /*
46 struct CbSpiralMotionOptions
47{
48 std::optional<float> linearVelocity = 0.0f;
49 std::optional<float> maxLinearVelocity = 1.0f;
50 std::optional<float> initialAngularVelocity = 1.0f;
51 std::optional<rclcpp::Duration> spiralMotionDuration = rclcpp::Duration::from_seconds(120);
52 std::optional <float> finalRadius=10.0f;//meters
53};
54 */
55
56 auto linearVelocity = *(options_.linearVelocity);
57 auto maxLinearVelocity = *(options_.maxLinearVelocity);
58 auto initialAngularVelocity = *(options_.initialAngularVelocity);
59 auto spiralMotionDuration = *(options_.spiralMotionDuration);
60 auto finalRadius = *(options_.finalRadius);
61
62 float rate = 20.0f;
63 rclcpp::Rate r(rate);
64 cmdVelPub_ = getNode()->create_publisher<geometry_msgs::msg::Twist>("/cmd_vel", rclcpp::QoS(1));
65
66 rclcpp::Duration linearRamp = rclcpp::Duration::from_seconds(spiralMotionDuration.seconds());
67 float linearAceleration = (maxLinearVelocity - linearVelocity) / linearRamp.seconds();
68 float dt = 1.0f / rate;
69
70 // we know final radious and the constant linear velocity
71 float finalAngularVelocity = maxLinearVelocity / finalRadius;
72
73 float angularAcceleration =
74 (initialAngularVelocity - finalAngularVelocity) / spiralMotionDuration.seconds();
75
76 geometry_msgs::msg::Twist cmd_vel;
77
78 cmd_vel.linear.x = linearVelocity;
79 cmd_vel.angular.z = initialAngularVelocity;
80 auto start_time = getNode()->now();
81
82 RCLCPP_INFO_STREAM(
83 getLogger(), "[CbSpiralMotion]: initialAngularVelocity: "
84 << initialAngularVelocity << ", finalAngularVelocity: " << finalAngularVelocity
85 << ", angularAcceleration: " << angularAcceleration);
86 RCLCPP_INFO_STREAM(
87 getLogger(), "[CbSpiralMotion]: linearAceleration: "
88 << linearAceleration << ", maxLinearVelocity: " << maxLinearVelocity);
89
90 bool end_condition = false;
91
92 while (!end_condition)
93 {
94 auto current_time = getNode()->now() - start_time;
95
96 cmd_vel.linear.x += linearAceleration * dt;
97 if (cmd_vel.linear.x > maxLinearVelocity)
98 {
99 cmd_vel.linear.x = maxLinearVelocity;
100 }
101
102 float signVal = (cmd_vel.angular.z >= 0.0f) ? 1.0f : -1.0f;
103 // cmd_vel.angular.z -= signVal * angularAcceleration * dt;
104
105 float ellapsedTimeFactor = current_time.seconds() / spiralMotionDuration.seconds();
106 cmd_vel.angular.z = initialAngularVelocity * (1.0f - ellapsedTimeFactor) +
107 finalAngularVelocity * ellapsedTimeFactor;
108
109 RCLCPP_INFO(
110 getLogger(), "[CbSpiralMotion] cmd_vel.linear.x = %f, cmd_vel.angular.z = %f",
111 cmd_vel.linear.x, cmd_vel.angular.z);
112
113 cmdVelPub_->publish(cmd_vel);
114 r.sleep();
115
116 auto now = getNode()->now();
117
118 rclcpp::Duration ellapsed = now - start_time;
119 RCLCPP_INFO_STREAM(
120 getLogger(), "[CbSpiralMotion] ellapsed time: " << ellapsed.seconds() << ", total duration: "
121 << spiralMotionDuration.seconds());
122 if (ellapsed > spiralMotionDuration)
123 {
124 RCLCPP_INFO_STREAM(getLogger(), "[CbSpiralMotion] spiralMotionDuration reached");
125 end_condition = true;
126 }
127 }
128
129 // asynchronous client behaviors usually post a success event when they are done
130 // that is used in states to transition to the next state
131 this->postSuccessEvent();
132}
133
135
136} // namespace cl_nav2z
virtual rclcpp::Logger getLogger() const
virtual rclcpp::Node::SharedPtr getNode() const
std::optional< float > initialAngularVelocity
std::optional< float > linearVelocity
std::optional< rclcpp::Duration > spiralMotionDuration
std::optional< float > maxLinearVelocity
std::optional< float > finalRadius
CbSpiralMotionOptions options_
rclcpp::Publisher< geometry_msgs::msg::Twist >::SharedPtr cmdVelPub_
CbSpiralMotion(std::optional< CbSpiralMotionOptions > options=std::nullopt)