PaGMO  1.1.5
mga_1dsm_alpha.cpp
1 /*****************************************************************************
2  * Copyright (C) 2004-2015 The PaGMO development team, *
3  * Advanced Concepts Team (ACT), European Space Agency (ESA) *
4  * *
5  * https://github.com/esa/pagmo *
6  * *
7  * act@esa.int *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the *
21  * Free Software Foundation, Inc., *
22  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
23  *****************************************************************************/
24 
25 #include <string>
26 #include <boost/math/constants/constants.hpp>
27 #include <vector>
28 #include <numeric>
29 #include <cmath>
30 #include <keplerian_toolbox/core_functions/propagate_lagrangian.h>
31 #include <keplerian_toolbox/core_functions/fb_prop.h>
32 #include <keplerian_toolbox/lambert_problem.h>
33 
34 #include "mga_1dsm_alpha.h"
35 
36 
37 namespace pagmo { namespace problem {
38 
39 
41 
58 mga_1dsm_alpha::mga_1dsm_alpha(const std::vector<kep_toolbox::planet::planet_ptr> seq,
59  const kep_toolbox::epoch t0_l, const kep_toolbox::epoch t0_u,
60  const double tof_l, const double tof_u,
61  const double vinf_l, const double vinf_u,
62  const bool mo, const bool add_vinf_dep, const bool add_vinf_arr) :
63  base( 7 + (int)(seq.size()-2) * 4, 0, 1 + (int)mo,0,0,0.0), m_seq(), m_n_legs(seq.size()-1), m_add_vinf_dep(add_vinf_dep), m_add_vinf_arr(add_vinf_arr)
64 {
65  // We check that all planets have equal central body
66  std::vector<double> mus(seq.size());
67  for (std::vector<kep_toolbox::planet::planet_ptr>::size_type i = 0; i< seq.size(); ++i) {
68  mus[i] = seq[i]->get_mu_central_body();
69  }
70  if ((unsigned int)std::count(mus.begin(), mus.end(), mus[0]) != mus.size()) {
71  pagmo_throw(value_error,"The planets do not all have the same mu_central_body");
72  }
73  // Filling in the planetary sequence data member. This requires to construct the polymorphic planets via their clone method
74  for (std::vector<kep_toolbox::planet::planet_ptr>::size_type i = 0; i < seq.size(); ++i) {
75  m_seq.push_back(seq[i]->clone());
76  }
77 
78  // Now setting the problem bounds
79  size_type dim(7 + (m_n_legs-1) * 4);
80  decision_vector lb(dim), ub(dim);
81 
82  // First leg
83  lb[0] = t0_l.mjd2000(); ub[0] = t0_u.mjd2000();
84  lb[1] = tof_l; ub[1] = tof_u;
85  lb[2] = 0; lb[3] = 0; ub[2] = 1; ub[3] = 1;
86  lb[4] = vinf_l * 1000; ub[4] = vinf_u * 1000;
87  lb[5] = 1e-5; ub[5] = 1-1e-5;
88  lb[6] = 1e-5; ub[6] = 1-1e-5;
89 
90  // Successive legs
91  for (std::vector<kep_toolbox::planet::planet_ptr>::size_type i = 0; i < m_n_legs - 1; ++i) {
92  lb[7+4*i] = - 2 * boost::math::constants::pi<double>(); ub[7+4*i] = 2 * boost::math::constants::pi<double>();
93  lb[8+4*i] = 1.1; ub[8+4*i] = 100;
94  lb[9+4*i] = 1e-5; ub[9+4*i] = 1-1e-5;
95  lb[10+4*i] = 1e-5; ub[10+4*i] = 1-1e-5;
96  }
97 
98  // Adjusting the minimum allowed fly-by rp to the one defined in the kep_toolbox::planet class
99  for (std::vector<kep_toolbox::planet::planet_ptr>::size_type i = 1; i < m_n_legs; ++i) {
100  lb[4 + 4*i] = m_seq[i]->get_safe_radius() / m_seq[i]->get_radius();
101  }
102  set_bounds(lb,ub);
103 }
104 
106 mga_1dsm_alpha::mga_1dsm_alpha(const mga_1dsm_alpha &p) : base(p.get_dimension(), 0, p.get_f_dimension(),0,0,0.0), m_seq(), m_n_legs(p.m_n_legs), m_add_vinf_dep(p.m_add_vinf_dep), m_add_vinf_arr(p.m_add_vinf_arr)
107 {
108  for (std::vector<kep_toolbox::planet::planet_ptr>::size_type i = 0; i < p.m_seq.size();++i) {
109  m_seq.push_back(p.m_seq[i]->clone());
110  }
111  set_bounds(p.get_lb(),p.get_ub());
112 }
113 
116 {
117  return base_ptr(new mga_1dsm_alpha(*this));
118 }
119 
122 {
123 try {
124  double common_mu = m_seq[0]->get_mu_central_body();
125  // 1 - we 'decode' the chromosome recording the various times of flight (days) in the list T
126  std::vector<double> T(m_n_legs,0.0);
127  double alpha_sum = 0;
128 
129  for (size_t i = 0; i < m_n_legs; ++i) {
130  double tmp = -log(x[6+4*i]);
131  alpha_sum+= tmp;
132  T[i] = x[1] * tmp;
133  }
134  for (size_t i = 0; i < m_n_legs; ++i) {
135  T[i] /= alpha_sum;
136  }
137 
138  // 2 - We compute the epochs and ephemerides of the planetary encounters
139  std::vector<kep_toolbox::epoch> t_P(m_n_legs + 1);
140  std::vector<kep_toolbox::array3D> r_P(m_n_legs + 1);
141  std::vector<kep_toolbox::array3D> v_P(m_n_legs + 1);
142  std::vector<double> DV(m_n_legs + 1);
143  for (size_t i = 0; i<(m_n_legs + 1); ++i) {
144  t_P[i] = kep_toolbox::epoch(x[0] + std::accumulate(T.begin(), T.begin()+i, 0.0));
145  m_seq[i]->eph(t_P[i], r_P[i], v_P[i]);
146  }
147 
148  // 3 - We start with the first leg
149  double theta = 2*boost::math::constants::pi<double>()*x[2];
150  double phi = acos(2*x[3]-1)-boost::math::constants::pi<double>() / 2;
151 
152  kep_toolbox::array3D Vinf = { {x[4]*cos(phi)*cos(theta), x[4]*cos(phi)*sin(theta), x[4]*sin(phi)} };
153  kep_toolbox::array3D v0;
154  kep_toolbox::sum(v0, v_P[0], Vinf);
155  kep_toolbox::array3D r(r_P[0]), v(v0);
156  kep_toolbox::propagate_lagrangian(r,v,x[5]*T[0]*ASTRO_DAY2SEC,common_mu);
157 
158  // Lambert arc to reach seq[1]
159  double dt = (1-x[5])*T[0]*ASTRO_DAY2SEC;
160  kep_toolbox::lambert_problem l(r,r_P[1],dt,common_mu);
161  kep_toolbox::array3D v_end_l = l.get_v2()[0];
162  kep_toolbox::array3D v_beg_l = l.get_v1()[0];
163 
164  // First DSM occuring at time nu1*T1
165  kep_toolbox::diff(v, v_beg_l, v);
166  DV[0] = kep_toolbox::norm(v);
167 
168  // 4 - And we proceed with each successive leg (if any)
169  kep_toolbox::array3D v_out;
170  for (size_t i = 1; i<m_n_legs; ++i) {
171  // Fly-by
172  kep_toolbox::fb_prop(v_out, v_end_l, v_P[i], x[8+(i-1)*4] * m_seq[i]->get_radius(), x[7+(i-1)*4], m_seq[i]->get_mu_self());
173  // s/c propagation before the DSM
174  r = r_P[i];
175  v = v_out;
176  kep_toolbox::propagate_lagrangian(r,v,x[9+(i-1)*4]*T[i]*ASTRO_DAY2SEC,common_mu);
177 
178  // Lambert arc to reach Earth during (1-nu2)*T2 (second segment)
179  dt = (1-x[9+(i-1)*4])*T[i]*ASTRO_DAY2SEC;
180  kep_toolbox::lambert_problem l2(r,r_P[i+1],dt,common_mu);
181  v_end_l = l2.get_v2()[0];
182  v_beg_l = l2.get_v1()[0];
183 
184  // DSM occuring at time nu2*T2
185  kep_toolbox::diff(v, v_beg_l, v);
186  DV[i] = kep_toolbox::norm(v);
187  }
188 
189  // Last Delta-v
190  kep_toolbox::diff(v, v_end_l, v_P[m_n_legs]);
191  DV[m_n_legs] = kep_toolbox::norm(v);
192 
193 
194  // Now we return the objective(s) function
195  f[0] = std::accumulate(DV.begin(),DV.end()-1,0.0);
196  if (m_add_vinf_dep) {
197  f[0] += x[4];
198  }
199  if (m_add_vinf_arr) {
200  f[0] += DV[DV.size()-1];
201  }
202  if (get_f_dimension() == 2){
203  f[1] = std::accumulate(T.begin(),T.end(),0.0);
204  }
205 //Here the lambert solver or the lagrangian propagator went wrong
206 } catch (...) {
207  f[0] = boost::numeric::bounds<double>::highest();
208  if (get_f_dimension() == 2){
209  f[1] = boost::numeric::bounds<double>::highest();
210  }
211 }
212 }
213 
215 
225 std::string mga_1dsm_alpha::pretty(const std::vector<double> &x) const {
226 
227  double common_mu = m_seq[0]->get_mu_central_body();
228  // We set the std output format
229  std::ostringstream s;
230  s.precision(15);
231  s << std::scientific;
232 
233  // 1 - we 'decode' the chromosome recording the various times of flight (days) in the list T
234  std::vector<double> T(m_n_legs,0.0);
235  double alpha_sum = 0;
236 
237  for (size_t i = 0; i < m_n_legs; ++i) {
238  double tmp = -log(x[6+4*i]);
239  alpha_sum+= tmp;
240  T[i] = x[1] * tmp;
241  }
242  for (size_t i = 0; i < m_n_legs; ++i) {
243  T[i] /= alpha_sum;
244  }
245 
246  // 2 - We compute the epochs and ephemerides of the planetary encounters
247  std::vector<kep_toolbox::epoch> t_P(m_n_legs + 1);
248  std::vector<kep_toolbox::array3D> r_P(m_n_legs + 1);
249  std::vector<kep_toolbox::array3D> v_P(m_n_legs + 1);
250  std::vector<double> DV(m_n_legs + 1);
251  for (size_t i = 0; i<(m_n_legs + 1); ++i) {
252  t_P[i] = kep_toolbox::epoch(x[0] + std::accumulate(T.begin(), T.begin()+i, 0.0));
253  m_seq[i]->eph(t_P[i], r_P[i], v_P[i]);
254  }
255 
256  // 3 - We start with the first leg
257  s << "First Leg: " << m_seq[0]->get_name() << " to " << m_seq[1]->get_name() << std::endl;
258  s << "Departure: " << t_P[0] << " (" << t_P[0].mjd2000() << " mjd2000)" << std::endl;
259  s << "Duration: " << T[0] << " days" << std::endl;
260  s << "VINF: " << x[4] / 1000 << " km/sec" << std::endl;
261  s << "DSM after " << x[5]*T[0] << " days" << std::endl;
262  double theta = 2*boost::math::constants::pi<double>()*x[2];
263  double phi = acos(2*x[3]-1)-boost::math::constants::pi<double>() / 2;
264 
265  kep_toolbox::array3D Vinf = { {x[4]*cos(phi)*cos(theta), x[4]*cos(phi)*sin(theta), x[4]*sin(phi)} };
266 
267  kep_toolbox::array3D v0;
268  kep_toolbox::sum(v0, v_P[0], Vinf);
269  kep_toolbox::array3D r(r_P[0]), v(v0);
270  kep_toolbox::propagate_lagrangian(r,v,x[5]*T[0]*ASTRO_DAY2SEC,common_mu);
271 
272  // Lambert arc to reach seq[1]
273  double dt = (1-x[5])*T[0]*ASTRO_DAY2SEC;
274  kep_toolbox::lambert_problem l(r,r_P[1],dt,common_mu);
275  kep_toolbox::array3D v_end_l = l.get_v2()[0];
276  kep_toolbox::array3D v_beg_l = l.get_v1()[0];
277 
278  // First DSM occuring at time nu1*T1
279  kep_toolbox::diff(v, v_beg_l, v);
280  DV[0] = kep_toolbox::norm(v);
281  s << "DSM magnitude: " << DV[0] << " m/s" << std::endl;
282 
283  // 4 - And we proceed with each successive leg (if any)
284  kep_toolbox::array3D v_out;
285  for (size_t i = 1; i<m_n_legs; ++i) {
286  s << "\nleg no: " << i+1 << ": " << m_seq[i]->get_name() << " to " << m_seq[i+1]->get_name() << std::endl;
287  s << "Duration: " << T[i] << " days" << std::endl;
288  s << "Fly-by epoch: " << t_P[i] << " (" << t_P[i].mjd2000() << " mjd2000) " << std::endl;
289  s << "Fly-by radius: " << x[8+(i-1)*4] << " planetary radii" << std::endl;
290  s << "DSM after " << x[9+(i-1)*4]*T[i] << " days" << std::endl;
291  // Fly-by
292  kep_toolbox::fb_prop(v_out, v_end_l, v_P[i], x[8+(i-1)*4] * m_seq[i]->get_radius(), x[7+(i-1)*4], m_seq[i]->get_mu_self());
293  // s/c propagation before the DSM
294  r = r_P[i];
295  v = v_out;
296  kep_toolbox::propagate_lagrangian(r,v,x[9+(i-1)*4]*T[i]*ASTRO_DAY2SEC,common_mu);
297 
298  // Lambert arc to reach Earth during (1-nu2)*T2 (second segment)
299  dt = (1-x[9+(i-1)*4])*T[i]*ASTRO_DAY2SEC;
300  kep_toolbox::lambert_problem l2(r,r_P[i+1],dt,common_mu);
301  v_end_l = l2.get_v2()[0];
302  v_beg_l = l2.get_v1()[0];
303 
304  // DSM occuring at time nu2*T2
305  kep_toolbox::diff(v, v_beg_l, v);
306  DV[i] = kep_toolbox::norm(v);
307  s << "DSM magnitude: " << DV[i] << "m/s" << std::endl;
308  }
309 
310  // Last Delta-v
311  kep_toolbox::diff(v, v_end_l, v_P[m_n_legs]);
312  DV[m_n_legs] = kep_toolbox::norm(v);
313  s << "\nArrival at " << m_seq[m_n_legs]->get_name() << std::endl;
314  s << "Arrival epoch: " << t_P[m_n_legs] << " (" << t_P[m_n_legs].mjd2000() << " mjd2000) " << std::endl;
315  s << "Arrival Vinf: " << DV[m_n_legs] << "m/s" << std::endl;
316  s << "Total mission time: " << std::accumulate(T.begin(),T.end(),0.0)/365.25 << " years" << std::endl;
317  return s.str();
318 }
319 std::string mga_1dsm_alpha::get_name() const
320 {
321  return "MGA-1DSM (alpha-encoding)";
322 }
323 
325 
331 void mga_1dsm_alpha::set_tof(double tl, double tu) {
332  set_bounds(1,tl,tu);
333 }
334 
336 
342 void mga_1dsm_alpha::set_launch_window(const kep_toolbox::epoch& start, const kep_toolbox::epoch& end) {
343  set_bounds(0,start.mjd2000(),end.mjd2000());
344 }
345 
347 
352 void mga_1dsm_alpha::set_vinf(const double vinf) {
353  set_ub(4,vinf*1000);
354 }
355 
357 
360 std::vector<double> mga_1dsm_alpha::get_tof() const {
361  std::vector<double> retval;
362  const decision_vector lb = get_lb();
363  const decision_vector ub = get_ub();
364  retval.push_back(lb[1]);
365  retval.push_back(ub[1]);
366  return retval;
367 }
368 
369 
371 
374 std::vector<kep_toolbox::planet::planet_ptr> mga_1dsm_alpha::get_sequence() const {
375  return m_seq;
376 }
377 
379 
384 {
385  std::ostringstream oss;
386  oss << "\n\tSequence: ";
387  for (size_t i = 0; i<m_seq.size() ;++i) {
388  oss << m_seq[i]->get_name() << " ";
389  }
390  oss << "\n\tAdd launcher vinf to the objective?: " << (m_add_vinf_dep? " True":" False") << std::endl;
391  oss << "\n\tAdd arrival vinf to the objective?: " << (m_add_vinf_arr? " True":" False") << std::endl;
392  return oss.str();
393 }
394 
395 }} //namespaces
396 
397 BOOST_CLASS_EXPORT_IMPLEMENT(pagmo::problem::mga_1dsm_alpha)
Root PaGMO namespace.
boost::shared_ptr< base > base_ptr
Alias for shared pointer to base problem.
Definition: problem/base.h:62
std::vector< double > decision_vector
Decision vector type.
Definition: types.h:40
void set_launch_window(const kep_toolbox::epoch &, const kep_toolbox::epoch &)
Sets the mission launch window.
void set_tof(const double, const double)
Sets the mission time of flight.
void objfun_impl(fitness_vector &, const decision_vector &) const
Implementation of the objective function.
Base problem class.
Definition: problem/base.h:148
std::string pretty(const std::vector< double > &x) const
Outputs a stream with the trajectory data.
base_ptr clone() const
Clone method.
A generic MGA-1DSM Problem.
std::string get_name() const
Get problem's name.
void set_ub(const decision_vector &)
Set upper bounds from pagmo::decision_vector.
std::vector< double > fitness_vector
Fitness vector type.
Definition: types.h:42
const decision_vector & get_ub() const
Upper bounds getter.
mga_1dsm_alpha(const std::vector< kep_toolbox::planet::planet_ptr >=construct_default_sequence(), const kep_toolbox::epoch t0_l=kep_toolbox::epoch(0), const kep_toolbox::epoch t0_r=kep_toolbox::epoch(1000), const double tof_l=1.0 *365.25, const double tof_u=5.0 *365.25, const double vinf_l=0.5, const double vinf_u=2.5, const bool mo=false, const bool add_vinf_dep=false, const bool add_vinf_arr=true)
Constructor.
std::vector< double > get_tof() const
Gets the sequence of time of flights for the mga-1dsm mission.
f_size_type get_f_dimension() const
Return fitness dimension.
std::vector< kep_toolbox::planet::planet_ptr > get_sequence() const
Gets the planetary sequence defining the interplanetary mga-1dsm mission.
const decision_vector & get_lb() const
Lower bounds getter.
std::string human_readable_extra() const
Extra human readable info for the problem.
void set_bounds(const decision_vector &, const decision_vector &)
Bounds setter from pagmo::decision_vector.
decision_vector::size_type size_type
Problem's size type: the same as pagmo::decision_vector's size type.
Definition: problem/base.h:160
void set_vinf(const double)
Sets the launch hyperbolic velocity.