semio_ros  0.10.6
example_deictic_targets_node.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <semio_msgs_ros/DeicticTargets.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 deixis recognition
23 {
24 protected:
25  //! ROS message for a vector of deictic targets
26  typedef semio_msgs_ros::DeicticTargets _DeicticTargetsMsg;
27  //! ROS message for a single deictic target
28  typedef semio_msgs_ros::DeicticTarget _DeicticTargetMsg;
29 
30  //! NodeHandle used to interface with ROS
31  ros::NodeHandle & _nh_rel;
32  //! Publisher for our deictic targets
33  ros::Publisher _deictic_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 deictic 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  ExampleDeicticTargetsNode( ros::NodeHandle & nh_rel, semio::HumanoidSource::Ptr humanoid_source_ptr, semio::HumanoidSink::Ptr humanoid_sink_ptr )
56  :
57  _nh_rel( nh_rel ),
58  _deictic_targets_pub( nh_rel.advertise<_DeicticTargetsMsg>( "deictic_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  _deictic_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  // publish deictic targets
133  _DeicticTargetsMsg deictic_targets_msg;
134 
135  deictic_targets_msg.targets.reserve( _deictic_targets.size() );
136 
137  //----------
138  //! - Convert deictic targets to ROS message
139  for( auto const & deictic_target : _deictic_targets )
140  {
141  _DeicticTargetMsg deictic_target_msg;
142 
143  deictic_target_msg.name = deictic_target.name_;
144  deictic_target_msg.position.x = deictic_target.position_.x();
145  deictic_target_msg.position.y = deictic_target.position_.y();
146  deictic_target_msg.position.z = deictic_target.position_.z();
147 
148  deictic_targets_msg.targets.push_back( std::move( deictic_target_msg ) );
149  }
150  //----------
151 
152  //! - Publish deictic targets
153  _deictic_targets_pub.publish( deictic_targets_msg );
154  }
155 
156  //! Main loop
157  /**
158  - If #_is_virtual_source == true
159  - Update our humanoid source with the next test pose
160  - publishData()
161  */
162  void spin()
163  {
164  if( _is_virtual_source )
165  {
166  ros::Duration sleep_interval( 0.5 );
167  size_t test_pose_idx = 1;
168  for( auto const & test_pose : _test_poses )
169  {
170  if( !ros::ok() ) break;
171 
172  ros::spinOnce();
173 
174  std::cout << "pose " << test_pose_idx << "/" << _test_poses.size() << std::endl;
175 
176  // update virtual humanoid with new test position
177  auto humanoid_source_virtual_ptr( std::dynamic_pointer_cast<semio::HumanoidSourceVirtual>( _humanoid_source_ptr ) );
178  humanoid_source_virtual_ptr->setPosition( test_pose.position );
179  humanoid_source_virtual_ptr->setOrientation(
181  Eigen::AngleAxisd( test_pose.head_rotation.x() * M_PI/180, Eigen::Vector3d::UnitX() ) *
182  Eigen::AngleAxisd( test_pose.head_rotation.y() * M_PI/180, Eigen::Vector3d::UnitY() ) *
183  Eigen::AngleAxisd( test_pose.head_rotation.z() * M_PI/180, Eigen::Vector3d::UnitZ() ) );
184  humanoid_source_virtual_ptr->setOrientation(
186  Eigen::AngleAxisd( test_pose.neck_rotation.x() * M_PI/180, Eigen::Vector3d::UnitX() ) *
187  Eigen::AngleAxisd( test_pose.neck_rotation.y() * M_PI/180, Eigen::Vector3d::UnitY() ) *
188  Eigen::AngleAxisd( test_pose.neck_rotation.z() * M_PI/180, Eigen::Vector3d::UnitZ() ) );
189  humanoid_source_virtual_ptr->setOrientation(
191  Eigen::AngleAxisd( test_pose.torso_rotation.x() * M_PI/180, Eigen::Vector3d::UnitX() ) *
192  Eigen::AngleAxisd( test_pose.torso_rotation.y() * M_PI/180, Eigen::Vector3d::UnitY() ) *
193  Eigen::AngleAxisd( test_pose.torso_rotation.z() * M_PI/180, Eigen::Vector3d::UnitZ() ) );
194 
195  publishData();
196 
197  sleep_interval.sleep();
198  test_pose_idx++;
199  }
200  }
201  else
202  {
203  ros::Rate loop_rate( 30 );
204 
205  while( ros::ok() )
206  {
207  ros::spinOnce();
208 
209  publishData();
210 
211  loop_rate.sleep();
212  }
213  }
214  }
215 };
216 
217 int main( int argc, char ** argv )
218 {
219  ros::init( argc, argv, "example_deictic_targets_node" );
220  //! - Create NodeHandle with relative namespace
221  ros::NodeHandle nh_rel( "~" );
222 
223  //! - Create semio::ros::HumanoidSourceAdapter; default to virtual source
224  semio::ros::HumanoidSourceAdapter humanoid_source_adapter( nh_rel, "virtual" );
225  //! - Create semio::ros::HumanoidSinkAdapter; default to ROS source
226  semio::ros::HumanoidSinkAdapter humanoid_sink_adapter( nh_rel, "ros" );
227 
228  //! - Create ExampleDeicticTargetsNode; pass node handle, humanoid source, and humanoid sink
229  ExampleDeicticTargetsNode example_deictic_targets_node( nh_rel, humanoid_source_adapter.getHumanoidSource(), humanoid_sink_adapter.getHumanoidSink() );
230  //! - Start main loop ExampleDeicticTargetsNode::spin()
231  example_deictic_targets_node.spin();
232 
233  return 0;
234 }
semio_msgs_ros::DeicticTargets _DeicticTargetsMsg
ROS message for a vector of deictic targets.
Example node demonstrating how to publish targets for deixis recognition.
decltype(std::make_shared< HumanoidSink >()) typedef Ptr
semio_msgs_ros::DeicticTarget _DeicticTargetMsg
ROS message for a single deictic target.
void publishData()
Publish all relevant data.
ros::NodeHandle & _nh_rel
NodeHandle used to interface with ROS.
Eigen::Vector3d neck_rotation
Rotation of the neck joint for the test pose (relative to global frame)
std::set< DeicticTarget > DeicticTargetArray
Utility class to simplify the creation of semio::HumanoidSink instances.
semio::DeicticTargetArray _deictic_targets
The list of deictic targets to publish.
ros::Publisher _deictic_targets_pub
Publisher for our deictic targets.
std::vector< TestPose > _test_poses
The list of test poses to use if _is_virtual_source == true.
semio::HumanoidSink::Ptr _humanoid_sink_ptr
Pointer to the input source for humanoids.
int main(int argc, char **argv)
bool _is_virtual_source
Whether the input source is a semio::HumanoidSourceVirtual.
decltype(std::make_shared< HumanoidSource >()) typedef Ptr
Eigen::Vector3d position
Position of the torso joint for the test pose (relative to global frame)
ExampleDeicticTargetsNode(ros::NodeHandle &nh_rel, semio::HumanoidSource::Ptr humanoid_source_ptr, semio::HumanoidSink::Ptr humanoid_sink_ptr)
Utility class to simplify the creation of semio::HumanoidSource instances.
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.
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...
semio::HumanoidSource::Ptr _humanoid_source_ptr
Pointer to the output sink for humanoids.
HumanoidSink::Ptr getHumanoidSink(std::string const &sink="param")
Create a semio::HumanoidSink.