@@ -17,269 +17,14 @@ Send the platform to a location on the map.
1717<Tabs groupId = " autonomy_goto" >
1818 <TabItem value = " Python" label = " Python" default >
1919
20- ``` python
21- from action_msgs.msg import GoalStatus # Import for reference to status constants
22- from clearpath_config.common.utils.yaml import read_yaml
23- from clearpath_navigation_msgs.action import ExecuteGoTo
24- from clearpath_navigation_msgs.msg import Waypoint
25- import rclpy
26- from rclpy.action import ActionClient
27- from rclpy.node import Node
28-
29- ROBOT_CONFIG_PATH = ' /etc/clearpath/robot.yaml'
30- LOGGING_NAME = ' ExecuteGoTo'
31-
32- # TODO : Enter your map uuid and waypoint info
33- MAP_ID : str = ' '
34- WAYPOINT = Waypoint(
35- uuid = ' ' ,
36- name = ' ' ,
37- latitude = ,
38- longitude = ,
39- heading = ,
40- position_tolerance = - 1.0 , # -1.0 means off
41- yaw_tolerance = - 1.0 , # -1.0 means off
42- tasks = []
43- )
44-
45-
46- class ExecuteGoToActionClient (Node ):
47-
48- def __init__ (self , namespace : str ):
49- super ().__init__ (' execute_goto' )
50- self ._namespace = namespace
51- self ._action_client = ActionClient(self , ExecuteGoTo, f ' / { self ._namespace} /autonomy/goto ' )
52- self ._goto_goal_handle = None
53- self ._goto_goal_cancelled = False
54- self ._goto_running = False
55- self ._goto_completed = False
56-
57- # ##################################
58- # GoTo Action Client Functions #
59- # ##################################
60- def send_goto_goal (self , map_id , waypoint ):
61- goal_msg = ExecuteGoTo.Goal()
62-
63- # populate goal message
64- goal_msg.map_uuid = map_id
65- goal_msg.waypoint = waypoint
66-
67- if not self ._action_client.wait_for_server(timeout_sec = 5.0 ):
68- self .get_logger().error(f ' [ { LOGGING_NAME } ] / { self ._namespace} /autonomy/goto action server not available! ' )
69- self .destroy_node()
70- rclpy.shutdown()
71- return
72-
73- self ._send_goal_future = self ._action_client.send_goal_async(goal_msg, feedback_callback = self .goto_feedback_cb)
74- self ._send_goal_future.add_done_callback(self .goto_goal_response_cb)
75-
76- def goto_goal_response_cb (self , future ):
77- self ._goto_goal_handle = future.result()
78- if not self ._goto_goal_handle.accepted:
79- self .get_logger().info(f ' [ { LOGGING_NAME } ] GoTo Goal rejected ' )
80- self ._goto_goal_handle = None
81- self .destroy_node()
82- rclpy.shutdown()
83- return
84-
85- self ._goto_running = True
86- self ._goto_completed = False
87- self ._goto_goal_cancelled = False
88- self .get_logger().info(f ' [ { LOGGING_NAME } ] GoTo Goal accepted ' )
89-
90- self ._get_result_future = self ._goto_goal_handle.get_result_async()
91- self ._get_result_future.add_done_callback(self .goto_get_result_cb)
92-
93- def goto_feedback_cb (self , feedback_msg ):
94- feedback = feedback_msg.feedback
95- self .get_logger().info(f ' [ { LOGGING_NAME } ] GoTo has been running for: { feedback.elapsed_time:.2f } s ' , throttle_duration_sec = 60 )
96-
97- def goto_cancel_response_cb (self , future ):
98- cancel_response = future.result()
99- self .get_logger().info(f ' [ { LOGGING_NAME } ] Cancel response received: { cancel_response.return_code} ' )
100- if len (cancel_response.goals_canceling) > 0 :
101- self .get_logger().info(f ' [ { LOGGING_NAME } ] Canceling of goto goal complete ' )
102- else :
103- self .get_logger().warning(f ' [ { LOGGING_NAME } ] GoTo Goal failed to cancel ' )
104-
105- def goto_get_result_cb (self , future ):
106- result = future.result().result
107- status = future.result().status
108-
109- # Compare the status integer against the constants defined in the message
110- if status == GoalStatus.STATUS_SUCCEEDED :
111- if result.success:
112- self .get_logger().info(f ' [ { LOGGING_NAME } ] [GoTo Goal Result] Succeeded! Result: Robot completed goto! ' )
113- self ._goto_completed = True
114- else :
115- self .get_logger().info(f ' [ { LOGGING_NAME } ] [GoTo Goal Result] Succeeded! Result: Robot failed to complete goto ' )
116-
117- elif status == GoalStatus.STATUS_CANCELED :
118- self .get_logger().info(f ' [ { LOGGING_NAME } ] [GoTo Goal Result] Cancelled! ' )
119- self ._goto_goal_cancelled = True
120-
121- elif status == GoalStatus.STATUS_ABORTED :
122- self .get_logger().info(f ' [ { LOGGING_NAME } ] [GoTo Goal Result] Aborted! ' )
123- else :
124- self .get_logger().info(f ' [ { LOGGING_NAME } ] [GoTo Goal Result] Finished with unknown status: { status} ' )
125-
126- self ._goto_goal_handle = None
127- self ._goto_running = False
128-
129- self .destroy_node()
130- rclpy.shutdown()
131-
132-
133- def main (args = None ):
134- rclpy.init(args = args)
135- robot_config = read_yaml(ROBOT_CONFIG_PATH )
136- namespace = robot_config[' system' ][' ros2' ][' namespace' ]
137-
138- goto = ExecuteGoToActionClient(namespace)
139- goto.send_goto_goal(MAP_ID , WAYPOINT )
140- rclpy.spin(goto)
141-
142-
143- if __name__ == ' __main__' :
144- main()
145-
20+ ``` python reference showLineNumbers
21+ https:// github.com/ cpr- application/ clearpath_outdoornav/ blob/ ros2/ python/ endpoints/ autonomy/ goto.py
14622```
14723 </TabItem >
14824 <TabItem value = " C++" label = " C++" >
14925
150- ``` cpp
151- #include < functional>
152- #include < future>
153- #include < memory>
154- #include < string>
155- #include < yaml-cpp/yaml.h>
156-
157- #include " clearpath_navigation_msgs/action/execute_go_to.hpp"
158-
159- #include " rclcpp/rclcpp.hpp"
160- #include " rclcpp_action/rclcpp_action.hpp"
161- #include " rclcpp_components/register_node_macro.hpp"
162-
163- // TODO: Enter your map id and waypoint information
164- const std::string MAP_ID = " " ;
165- const std::string WAYPOINT_ID = " " ;
166- const std::string WAYPOINT_NAME = " " ;
167- const double WAYPOINT_LAT = ;
168- const double WAYPOINT_LON = ;
169- const double WAYPOINT_HEADING = ;
170- const double WAYPOINT_POSITION_TOLERANCE = -1.0 ; // -1.0 means off
171- const double WAYPOINT_YAW_TOLERANCE = -1.0 ; // -1.0 means off
172-
173-
174- namespace goto_action_client
175- {
176- class ExecuteGoToActionClient : public rclcpp ::Node
177- {
178- public:
179- using ExecuteGoTo = clearpath_navigation_msgs::action::ExecuteGoTo;
180- using GoalHandleExecuteGoTo = rclcpp_action::ClientGoalHandle<ExecuteGoTo >;
181-
182- explicit ExecuteGoToActionClient(const rclcpp::NodeOptions & options)
183- : Node("execute_goto", options)
184- {
185- YAML ::Node robot_config = YAML ::LoadFile (" /etc/clearpath/robot.yaml" );
186- namespace_ = robot_config [" system" ][" ros2" ][" namespace" ].as < std ::string > ();
187-
188- this - > client_ptr_ = rclcpp_action ::create_client <ExecuteGoTo >(
189- this , " /" + namespace_ + " /" + std ::string (" autonomy/goto" ));
190-
191- this - > timer_ = this - > create_wall_timer (
192- std ::chrono ::milliseconds (500 ),
193- std ::bind (& ExecuteGoToActionClient ::send_goal , this ));
194- }
195-
196- void send_goal()
197- {
198- using namespace std ::placeholders ;
199-
200- this - > timer_ - > cancel ();
201-
202- if (! this - > client_ptr_ - > wait_for_action_server ()) {
203- RCLCPP_ERROR(this ->get_logger (), " %s/autonomy/goto action server not available after waiting" , namespace_.c_str());
204- rclcpp::shutdown ();
205- }
206-
207- auto goal_msg = ExecuteGoTo ::Goal ();
208- goal_msg .map_uuid = MAP_ID ;
209-
210- auto waypoint = clearpath_navigation_msgs ::msg ::Waypoint ();
211- waypoint .uuid = WAYPOINT_ID ;
212- waypoint .name = WAYPOINT_NAME ;
213- waypoint .uuid = WAYPOINT_ID ;
214- waypoint .latitude = WAYPOINT_LAT ;
215- waypoint .longitude = WAYPOINT_LON ;
216- waypoint .heading = WAYPOINT_HEADING ;
217- waypoint .position_tolerance = WAYPOINT_POSITION_TOLERANCE ;
218- waypoint .yaw_tolerance = WAYPOINT_YAW_TOLERANCE ;
219- goal_msg .waypoint = waypoint ;
220-
221- auto send_goal_options = rclcpp_action ::Client < ExecuteGoTo > ::SendGoalOptions ();
222-
223- send_goal_options .goal_response_callback = [this ](const GoalHandleExecuteGoTo ::SharedPtr & goal_handle )
224- {
225- if (!goal_handle ) {
226- RCLCPP_ERROR (this - > get_logger (), " GoTo Goal was rejected by server" );
227- } else {
228- RCLCPP_INFO (this - > get_logger (), " GoTo Goal accepted by server, waiting for result" );
229- }
230- };
231-
232- send_goal_options .feedback_callback = [this ](
233- GoalHandleExecuteGoTo ::SharedPtr ,
234- const std ::shared_ptr < const ExecuteGoTo ::Feedback > feedback )
235- {
236- RCLCPP_INFO_THROTTLE(this ->get_logger (), *this->get_clock(), 60000 , " GoTo has been running for: %.3f" , feedback->elapsed_time);
237- };
238-
239- send_goal_options .result_callback = [this ](const GoalHandleExecuteGoTo ::WrappedResult & result )
240- {
241- switch (result.code) {
242- case rclcpp_action ::ResultCode ::SUCCEEDED :
243- if (result .result - > success )
244- {
245- RCLCPP_INFO (this - > get_logger (), " [GoTo Goal Result] Succeeded! Result: Robot arrived at goto position successfully!" );
246- }
247- else
248- {
249- RCLCPP_ERROR (this - > get_logger (), " [GoTo Goal Result] Succeeded! Result: Robot failed to arrive to goto position" );
250- }
251- break ;
252- case rclcpp_action ::ResultCode ::ABORTED :
253- RCLCPP_ERROR (this - > get_logger (), " [GoTo Goal Result] Aborted!" );
254- return ;
255- case rclcpp_action ::ResultCode ::CANCELED :
256- RCLCPP_ERROR (this - > get_logger (), " [GoTo Goal Result] Cancelled!" );
257- return ;
258- default :
259- RCLCPP_ERROR (this - > get_logger (), " [GoTo Goal Result] Finished with unknown code" );
260- return ;
261- }
262- rclcpp::shutdown ();
263- };
264-
265- this - > client_ptr_ - > async_send_goal (goal_msg , send_goal_options );
266- }
267-
268- private:
269- rclcpp_action::Client<ExecuteGoTo >::SharedPtr client_ptr_ ;
270- rclcpp::TimerBase::SharedPtr timer_ ;
271- std::string namespace_ ;
272-
273- }; // class ExecuteGoToActionClient
274-
275- } // namespace goto_action_client
276-
277- int main ()
278- {
279- }
280-
281- RCLCPP_COMPONENTS_REGISTER_NODE (goto_action_client::ExecuteGoToActionClient)
282-
26+ ``` cpp reference showLineNumbers
27+ https:// github.com/cpr-application/clearpath_outdoornav/blob/ros2/cpp/endpoints/autonomy/goto.cpp
28328```
28429 </TabItem >
28530
0 commit comments