semio_ros  0.10.6
example_attention_targets_node.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <semio_msgs_ros/AttentionTargets.h>
7 
8 //! Stores a partial pose (head/neck/torso rotations and the torso position) of a virtual humanoid
9 struct TestPose
10 {
11  //! Rotation of the head joint for the test pose (relative to global frame)
12  Eigen::Vector3d head_rotation;
13  //! Rotation of the neck joint for the test pose (relative to global frame)
14  Eigen::Vector3d neck_rotation;
15  //! Rotation of the torso joint for the test pose (relative to global frame)
16  Eigen::Vector3d torso_rotation;
17  //! Position of the torso joint for the test pose (relative to global frame)
18  Eigen::Vector3d position;
19 };
20 
21 //! Example node demonstrating how to publish targets for attention recognition
23 {
24 protected:
25  //! ROS message for a vector of attention targets
26  typedef semio_msgs_ros::AttentionTargets _AttentionTargetsMsg;
27  //! ROS message for a single attention target
28  typedef semio_msgs_ros::AttentionTarget _AttentionTargetMsg;
29 
30  //! NodeHandle used to interface with ROS
31  ros::NodeHandle & _nh_rel;
32  //! Publisher for our attention targets
33  ros::Publisher _attention_targets_pub;
34 
35  //! Pointer to the input source for humanoids
37  //! Pointer to the output sink for humanoids
39 
40  //! Whether the input source is a semio::HumanoidSourceVirtual
42 
43  //! The list of attention targets to publish
45 
46  //! The list of test poses to use if #_is_virtual_source == true
47  std::vector<TestPose> _test_poses;
48 
49 public:
50  /**
51  @param nh_rel @copybrief _nh_rel
52  @param humanoid_source_ptr @copybrief _humanoid_source_ptr
53  @param humanoid_sink_ptr @copybrief _humanoid_sink_ptr
54  */
55  ExampleAttentionTargetsNode( ros::NodeHandle & nh_rel, semio::HumanoidSource::Ptr humanoid_source_ptr, semio::HumanoidSink::Ptr humanoid_sink_ptr )
56  :
57  _nh_rel( nh_rel ),
58  _attention_targets_pub( nh_rel.advertise<_AttentionTargetsMsg>( "attention_targets", 10 ) ),
59  _humanoid_source_ptr( humanoid_source_ptr ),
60  _humanoid_sink_ptr( humanoid_sink_ptr ),
61  _is_virtual_source( std::dynamic_pointer_cast<semio::HumanoidSourceVirtual>( _humanoid_source_ptr ) )
62  {
63  size_t const cols( _nh_rel.param<int>( "cols", 13 ) );
64  size_t const rows( _nh_rel.param<int>( "rows", 7 ) );
65  double const horizontal_spacing( _nh_rel.param<double>( "h_spacing", 15 ) );
66  double const vertical_spacing( _nh_rel.param<double>( "v_spacing", 15 ) );
67  double const radius( _nh_rel.param<double>( "radius", 2 ) );
68 
69  std::cout << "using " << cols << "x" << rows << " @ " << horizontal_spacing << "x" << vertical_spacing << std::endl;
70  Eigen::Vector3d const center( radius, 0, 0 );
71 
72  double const yaw_range( horizontal_spacing * static_cast<double>( cols - 1 ) / 2.0 );
73  double const pitch_range( vertical_spacing * static_cast<double>( rows - 1 ) / 2.0 );
74 
75  for( size_t col = 0; col < cols; ++col )
76  {
77  for( size_t row = 0; row < rows; ++row )
78  {
79  double const yaw( yaw_range - static_cast<double>( col ) * horizontal_spacing );
80  double const pitch( -pitch_range + static_cast<double>( row ) * vertical_spacing );
81 
82  std::stringstream name_stream;
83  name_stream << ( col * rows + row );
84  _attention_targets.emplace(
85  name_stream.str(),
86  (
87  Eigen::Affine3d(
88  Eigen::Translation3d( center ) *
89  Eigen::Quaterniond( Eigen::AngleAxisd( M_PI, Eigen::Vector3d::UnitZ() ) )
90  ) *
91  Eigen::Affine3d(
92  Eigen::Quaterniond(
93  Eigen::AngleAxisd( yaw * M_PI/180, Eigen::Vector3d::UnitZ() ) *
94  Eigen::AngleAxisd( pitch * M_PI/180, Eigen::Vector3d::UnitY() )
95  ) *
96  Eigen::Translation3d( radius, 0, 0 )
97  )
98  ).translation()
99  );
100  }
101  }
102 
103  if( _is_virtual_source )
104  {
105  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 180 ), Eigen::Vector3d( 2, 0, 0 ) } ) );
106  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 180 + 45 ), Eigen::Vector3d( 2, 0, 0 ) } ) );
107  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 180 - 45 ), Eigen::Vector3d( 2, 0, 0 ) } ) );
108  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 180 + 90 ), Eigen::Vector3d( 2, 0, 0 ) } ) );
109  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 180 - 90 ), Eigen::Vector3d( 2, 0, 0 ) } ) );
110  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 180 ), Eigen::Vector3d( 2, -2, 0 ) } ) );
111  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 0 ), Eigen::Vector3d( 0, 0, 180 ), Eigen::Vector3d( 2, 2, 0 ) } ) );
112 
113  for( double const & torso_yaw : { 90, 45, 0, -45, -90 } )
114  {
115  for( double const & neck_yaw : { 45, 30, 15, 0, -15, -30, -45 } )
116  {
117  for( double const & head_yaw : { 45, 30, 15, 0, -15, -30, -45 } )
118  {
119  _test_poses.push_back( std::move( TestPose{ Eigen::Vector3d( 0, 0, head_yaw ), Eigen::Vector3d( 0, 0, neck_yaw ), Eigen::Vector3d( 0, 0, 180 + torso_yaw ), Eigen::Vector3d( 1, 0, 0 ) } ) );
120  }
121  }
122  }
123  }
124  }
125 
126  //! Publish all relevant data
127  void publishData()
128  {
129  //! - Publish humanoids from our input source to our output sink
130  _humanoid_sink_ptr->publish( _humanoid_source_ptr->update() );
131 
132  //----------
133  //! - Convert attention targets to ROS message
134  _AttentionTargetsMsg attention_targets_msg;
135 
136  attention_targets_msg.targets.reserve( _attention_targets.size() );
137 
138  for( auto const & attention_target : _attention_targets )
139  {
140  _AttentionTargetMsg attention_target_msg;
141 
142  attention_target_msg.name = attention_target.name_;
143  attention_target_msg.position.x = attention_target.position_.x();
144  attention_target_msg.position.y = attention_target.position_.y();
145  attention_target_msg.position.z = attention_target.position_.z();
146 
147  attention_targets_msg.targets.push_back( std::move( attention_target_msg ) );
148  }
149  //----------
150 
151  //! - Publish attention targets
152  _attention_targets_pub.publish( attention_targets_msg );
153  }
154 
155  //! Main loop
156  /**
157  - If #_is_virtual_source == true
158  - Update our humanoid source with the next test pose
159  - publishData()
160  */
161  void spin()
162  {
163  if( _is_virtual_source )
164  {
165  ros::Duration sleep_interval( 0.5 );
166  size_t test_pose_idx = 1;
167  for( auto const & test_pose : _test_poses )
168  {
169  if( !ros::ok() ) break;
170 
171  ros::spinOnce();
172 
173  std::cout << "pose " << test_pose_idx << "/" << _test_poses.size() << std::endl;
174 
175  // update virtual humanoid with new test position
176  auto humanoid_source_virtual_ptr( std::dynamic_pointer_cast<semio::HumanoidSourceVirtual>( _humanoid_source_ptr ) );
177  humanoid_source_virtual_ptr->setPosition( test_pose.position );
178  humanoid_source_virtual_ptr->setOrientation(
180  Eigen::AngleAxisd( test_pose.head_rotation.x() * M_PI/180, Eigen::Vector3d::UnitX() ) *
181  Eigen::AngleAxisd( test_pose.head_rotation.y() * M_PI/180, Eigen::Vector3d::UnitY() ) *
182  Eigen::AngleAxisd( test_pose.head_rotation.z() * M_PI/180, Eigen::Vector3d::UnitZ() ) );
183  humanoid_source_virtual_ptr->setOrientation(
185  Eigen::AngleAxisd( test_pose.neck_rotation.x() * M_PI/180, Eigen::Vector3d::UnitX() ) *
186  Eigen::AngleAxisd( test_pose.neck_rotation.y() * M_PI/180, Eigen::Vector3d::UnitY() ) *
187  Eigen::AngleAxisd( test_pose.neck_rotation.z() * M_PI/180, Eigen::Vector3d::UnitZ() ) );
188  humanoid_source_virtual_ptr->setOrientation(
190  Eigen::AngleAxisd( test_pose.torso_rotation.x() * M_PI/180, Eigen::Vector3d::UnitX() ) *
191  Eigen::AngleAxisd( test_pose.torso_rotation.y() * M_PI/180, Eigen::Vector3d::UnitY() ) *
192  Eigen::AngleAxisd( test_pose.torso_rotation.z() * M_PI/180, Eigen::Vector3d::UnitZ() ) );
193 
194  publishData();
195 
196  sleep_interval.sleep();
197  test_pose_idx++;
198  }
199  }
200  else
201  {
202  ros::Rate loop_rate( 30 );
203 
204  while( ros::ok() )
205  {
206  ros::spinOnce();
207 
208  publishData();
209 
210  loop_rate.sleep();
211  }
212  }
213  }
214 };
215 
216 int main( int argc, char ** argv )
217 {
218  ros::init( argc, argv, "example_attention_targets_node" );
219  //! - Create NodeHandle with relative namespace
220  ros::NodeHandle nh_rel( "~" );
221 
222  //! - Create semio::ros::HumanoidSourceAdapter; default to virtual source
223  semio::ros::HumanoidSourceAdapter humanoid_source_adapter( nh_rel, "virtual" );
224  //! - Create semio::ros::HumanoidSinkAdapter; default to ROS source
225  semio::ros::HumanoidSinkAdapter humanoid_sink_adapter( nh_rel, "ros" );
226 
227  //! - Create ExampleAttentionTargetsNode; pass node handle, humanoid source, and humanoid sink
228  ExampleAttentionTargetsNode example_attention_targets_node( nh_rel, humanoid_source_adapter.getHumanoidSource(), humanoid_sink_adapter.getHumanoidSink() );
229  //! - Start main loop ExampleAttentionTargetsNode::spin()
230  example_attention_targets_node.spin();
231 
232  return 0;
233 }
semio_msgs_ros::AttentionTargets _AttentionTargetsMsg
ROS message for a vector of attention targets.
decltype(std::make_shared< HumanoidSink >()) typedef Ptr
std::set< AttentionTarget > AttentionTargetArray
Example node demonstrating how to publish targets for attention recognition.
Eigen::Vector3d neck_rotation
Rotation of the neck joint for the test pose (relative to global frame)
Utility class to simplify the creation of semio::HumanoidSink instances.
bool _is_virtual_source
Whether the input source is a semio::HumanoidSourceVirtual.
void publishData()
Publish all relevant data.
ExampleAttentionTargetsNode(ros::NodeHandle &nh_rel, semio::HumanoidSource::Ptr humanoid_source_ptr, semio::HumanoidSink::Ptr humanoid_sink_ptr)
std::vector< TestPose > _test_poses
The list of test poses to use if _is_virtual_source == true.
semio::AttentionTargetArray _attention_targets
The list of attention targets to publish.
ros::NodeHandle & _nh_rel
NodeHandle used to interface with ROS.
decltype(std::make_shared< HumanoidSource >()) typedef Ptr
semio::HumanoidSink::Ptr _humanoid_sink_ptr
Pointer to the output sink for humanoids.
Eigen::Vector3d position
Position of the torso joint for the test pose (relative to global frame)
int main(int argc, char **argv)
Utility class to simplify the creation of semio::HumanoidSource instances.
semio::HumanoidSource::Ptr _humanoid_source_ptr
Pointer to the input source for humanoids.
Eigen::Vector3d torso_rotation
Rotation of the torso joint for the test pose (relative to global frame)
HumanoidSource::Ptr getHumanoidSource(std::string const &source="param")
Create a semio::HumanoidSource.
ros::Publisher _attention_targets_pub
Publisher for our attention targets.
Eigen::Vector3d head_rotation
Rotation of the head joint for the test pose (relative to global frame)
Stores a partial pose (head/neck/torso rotations and the torso position) of a virtual humanoid...
HumanoidSink::Ptr getHumanoidSink(std::string const &sink="param")
Create a semio::HumanoidSink.
semio_msgs_ros::AttentionTarget _AttentionTargetMsg
ROS message for a single attention target.